From fb48365af1ca662eb1f044c953d15b126e2e528f Mon Sep 17 00:00:00 2001 From: Kelly Dwan Date: Thu, 1 Feb 2024 11:55:58 -0500 Subject: [PATCH] Query Filter: Update to match new Interactivity API format (#563) * Query Filter: Update to match new Interactivity API format * Pass translations from PHP This is a workaround for i18n functions, since they can't be imported into a module * Fix linter issue * Switch back to PostCSS --- mu-plugins/blocks/query-filter/render.php | 37 +-- mu-plugins/blocks/query-filter/src/block.json | 4 +- mu-plugins/blocks/query-filter/src/index.js | 1 + .../query-filter/{postcss => src}/style.pcss | 0 mu-plugins/blocks/query-filter/src/view.js | 252 +++++++++--------- 5 files changed, 144 insertions(+), 150 deletions(-) rename mu-plugins/blocks/query-filter/{postcss => src}/style.pcss (100%) diff --git a/mu-plugins/blocks/query-filter/render.php b/mu-plugins/blocks/query-filter/render.php index 08711b53d..e0beab420 100644 --- a/mu-plugins/blocks/query-filter/render.php +++ b/mu-plugins/blocks/query-filter/render.php @@ -41,7 +41,7 @@ 'hasHover' => false, 'hasMultiple' => $has_multiple, ]; -$encoded_state = wp_json_encode( [ 'wporg' => [ 'queryFilter' => $init_state ] ] ); +$encoded_state = wp_json_encode( $init_state ); // Set up a unique ID for this filter. $html_id = wp_unique_id( "filter-{$settings['key']}-" ); @@ -66,43 +66,43 @@ ?>
- data-wp-interactive + data-wp-interactive="" data-wp-context="" - data-wp-effect="effects.wporg.queryFilter.init" - data-wp-class--is-modal-open="context.wporg.queryFilter.isOpen" - data-wp-on--keydown="actions.wporg.queryFilter.handleKeydown" + data-wp-watch="effects.init" + data-wp-class--is-modal-open="context.isOpen" + data-wp-on--keydown="actions.handleKeydown" >

@@ -140,6 +140,9 @@ class="wporg-query-filter__modal-close" * @param WP_Block $block The current block being rendered. */ do_action( 'wporg_query_filter_in_form', $settings['key'], $block ); + + /* translators: %s is count of currently selected filters. */ + $label_count = __( 'Apply (%s)', 'wporg' ); ?>
@@ -147,11 +150,13 @@ class="wporg-query-filter__modal-close" type="button" class="wporg-query-filter__modal-action-clear" value="" - data-wp-on--click="actions.wporg.queryFilter.clearSelection" + data-wp-on--click="actions.clearSelection" aria-disabled="" /> value="" />
diff --git a/mu-plugins/blocks/query-filter/src/block.json b/mu-plugins/blocks/query-filter/src/block.json index 9fe083993..f4b4a6544 100644 --- a/mu-plugins/blocks/query-filter/src/block.json +++ b/mu-plugins/blocks/query-filter/src/block.json @@ -24,7 +24,7 @@ } }, "editorScript": "file:./index.js", - "style": "file:./style.css", - "viewScript": "file:./view.js", + "style": "file:./style-index.css", + "viewModule": "file:./view.js", "render": "file:../render.php" } diff --git a/mu-plugins/blocks/query-filter/src/index.js b/mu-plugins/blocks/query-filter/src/index.js index 792022189..66e617e60 100644 --- a/mu-plugins/blocks/query-filter/src/index.js +++ b/mu-plugins/blocks/query-filter/src/index.js @@ -9,6 +9,7 @@ import { useBlockProps } from '@wordpress/block-editor'; * Internal dependencies */ import metadata from './block.json'; +import './style.pcss'; function Edit( { attributes, name } ) { return ( diff --git a/mu-plugins/blocks/query-filter/postcss/style.pcss b/mu-plugins/blocks/query-filter/src/style.pcss similarity index 100% rename from mu-plugins/blocks/query-filter/postcss/style.pcss rename to mu-plugins/blocks/query-filter/src/style.pcss diff --git a/mu-plugins/blocks/query-filter/src/view.js b/mu-plugins/blocks/query-filter/src/view.js index c89e7ccf4..6017effd9 100644 --- a/mu-plugins/blocks/query-filter/src/view.js +++ b/mu-plugins/blocks/query-filter/src/view.js @@ -1,8 +1,7 @@ /** * WordPress dependencies */ -import { __, sprintf } from '@wordpress/i18n'; -import { store as wpStore } from '@wordpress/interactivity'; +import { getContext, getElement, store } from '@wordpress/interactivity'; // See https://github.com/WordPress/gutenberg/blob/37f52ae884a40f7cb77ac2484648b4e4ad973b59/packages/block-library/src/navigation/view-interactivity.js const focusableSelectors = [ @@ -15,151 +14,140 @@ const focusableSelectors = [ '[tabindex]:not([tabindex^="-"])', ]; -/** - * Toggles the overflow-x style of the query filter between 'hidden' and 'scroll'. - * - * In certain themes (e.g., showcase), an 'overflow-x: scroll' is added on mobile screens to always display - * the horizontal scrollbar, indicating to users that there's more content to the right. - * However, this persistent display feature causes the dropdown menu to be overlaid by the scrollbar - * when opened (See issue https://github.com/WordPress/wporg-mu-plugins/issues/467#issuecomment-1754349676). - * This function serves to address that issue. - * - */ -function toggleOverflowX() { - const filtersElement = document.querySelector( '.wporg-query-filters' ); +const { actions } = store( 'wporg/query-filter', { + actions: { + /** + * Toggles the overflow-x style of the query filter between 'hidden' and 'scroll'. + * + * In certain themes (e.g., showcase), an 'overflow-x: scroll' is added on mobile screens to always display + * the horizontal scrollbar, indicating to users that there's more content to the right. + * However, this persistent display feature causes the dropdown menu to be overlaid by the scrollbar + * when opened (See issue https://github.com/WordPress/wporg-mu-plugins/issues/467#issuecomment-1754349676). + * This function serves to address that issue. + * + */ + toggleOverflowX: () => { + const filtersElement = document.querySelector( '.wporg-query-filters' ); - if ( filtersElement ) { - const currentOverflowX = window.getComputedStyle( filtersElement ).overflowX; + if ( filtersElement ) { + const currentOverflowX = window.getComputedStyle( filtersElement ).overflowX; - if ( 'hidden' === currentOverflowX ) { - filtersElement.style.overflowX = 'scroll'; - } else if ( 'scroll' === currentOverflowX || 'auto' === currentOverflowX ) { - filtersElement.style.overflowX = 'hidden'; - } - } -} + if ( 'hidden' === currentOverflowX ) { + filtersElement.style.overflowX = 'scroll'; + } else if ( 'scroll' === currentOverflowX || 'auto' === currentOverflowX ) { + filtersElement.style.overflowX = 'hidden'; + } + } + }, -function closeDropdown( store ) { - const { context } = store; - context.wporg.queryFilter.isOpen = false; - context.wporg.queryFilter.form?.reset(); + closeDropdown: () => { + const context = getContext(); + context.isOpen = false; + context.form?.reset(); - const count = context.wporg.queryFilter.form?.querySelectorAll( 'input:checked' ).length; - updateButtons( store, count ); - document.documentElement.classList.remove( 'is-query-filter-open' ); + const count = context.form?.querySelectorAll( 'input:checked' ).length; + actions.updateButtons( count ); + document.documentElement.classList.remove( 'is-query-filter-open' ); - toggleOverflowX(); -} + actions.toggleOverflowX(); + }, -function updateButtons( store, count ) { - const { context } = store; - if ( ! context.wporg.queryFilter.form ) { - return; - } + updateButtons: ( count ) => { + const context = getContext(); + if ( ! context.form ) { + return; + } - const applyButton = context.wporg.queryFilter.form.querySelector( 'input[type="submit"]' ); - const clearButton = context.wporg.queryFilter.form.querySelector( '.wporg-query-filter__modal-action-clear' ); + const applyButton = context.form.querySelector( 'input[type="submit"]' ); + const clearButton = context.form.querySelector( '.wporg-query-filter__modal-action-clear' ); - // Only update the apply button if multiple selections are allowed. - if ( context.wporg.queryFilter.hasMultiple ) { - if ( count ) { - /* translators: %s is count of currently selected filters. */ - applyButton.value = sprintf( __( 'Apply (%s)', 'wporg' ), count ); - } else { - applyButton.value = __( 'Apply', 'wporg' ); - } - } + // Only update the apply button if multiple selections are allowed. + if ( context.hasMultiple ) { + if ( count ) { + applyButton.value = applyButton.dataset.labelWithCount.replace( '%s', count ); + } else { + applyButton.value = applyButton.dataset.label; + } + } - clearButton.setAttribute( 'aria-disabled', count ? 'false' : 'true' ); -} + clearButton.setAttribute( 'aria-disabled', count ? 'false' : 'true' ); + }, -wpStore( { - actions: { - wporg: { - queryFilter: { - toggle: ( store ) => { - const { context } = store; - if ( context.wporg.queryFilter.isOpen ) { - closeDropdown( store ); - } else { - context.wporg.queryFilter.isOpen = true; - document.documentElement.classList.add( 'is-query-filter-open' ); - toggleOverflowX(); - } - }, - handleKeydown: ( store ) => { - const { context, event } = store; - // If Escape close the dropdown. - if ( event.key === 'Escape' ) { - closeDropdown( store ); - context.wporg.queryFilter.toggleButton.focus(); - return; - } + toggle: () => { + const context = getContext(); + if ( context.isOpen ) { + actions.closeDropdown(); + } else { + context.isOpen = true; + document.documentElement.classList.add( 'is-query-filter-open' ); + actions.toggleOverflowX(); + } + }, + handleKeydown: ( event ) => { + const context = getContext(); + // If Escape close the dropdown. + if ( event.key === 'Escape' ) { + actions.closeDropdown(); + context.toggleButton.focus(); + return; + } - // Trap focus. - if ( event.key === 'Tab' ) { - // If shift + tab it change the direction. - if ( - event.shiftKey && - window.document.activeElement === context.wporg.queryFilter.firstFocusableElement - ) { - event.preventDefault(); - context.wporg.queryFilter.lastFocusableElement.focus(); - } else if ( - ! event.shiftKey && - window.document.activeElement === context.wporg.queryFilter.lastFocusableElement - ) { - event.preventDefault(); - context.wporg.queryFilter.firstFocusableElement.focus(); - } - } - }, - handleFormChange: ( store ) => { - const { context } = store; - const count = context.wporg.queryFilter.form.querySelectorAll( 'input:checked' ).length; - updateButtons( store, count ); - }, - clearSelection: ( store ) => { - const { context, ref } = store; - if ( 'true' === ref.getAttribute( 'aria-disabled' ) ) { - return; - } - context.wporg.queryFilter.form - .querySelectorAll( 'input' ) - .forEach( ( input ) => ( input.checked = false ) ); - updateButtons( store, 0 ); - }, - }, + // Trap focus. + if ( event.key === 'Tab' ) { + // If shift + tab it change the direction. + if ( event.shiftKey && window.document.activeElement === context.firstFocusableElement ) { + event.preventDefault(); + context.lastFocusableElement.focus(); + } else if ( ! event.shiftKey && window.document.activeElement === context.lastFocusableElement ) { + event.preventDefault(); + context.firstFocusableElement.focus(); + } + } + }, + handleFormChange: () => { + const context = getContext(); + const count = context.form.querySelectorAll( 'input:checked' ).length; + actions.updateButtons( count ); + }, + clearSelection: () => { + const context = getContext(); + const { ref } = getElement(); + if ( 'true' === ref.getAttribute( 'aria-disabled' ) ) { + return; + } + context.form.querySelectorAll( 'input' ).forEach( ( input ) => ( input.checked = false ) ); + actions.updateButtons( 0 ); }, }, effects: { - wporg: { - queryFilter: { - init: ( { context, ref } ) => { - context.wporg.queryFilter.toggleButton = ref.querySelector( '.wporg-query-filter__toggle' ); - context.wporg.queryFilter.form = ref.querySelector( 'form' ); + init: () => { + const context = getContext(); + const { ref } = getElement(); + context.toggleButton = ref.querySelector( '.wporg-query-filter__toggle' ); + context.form = ref.querySelector( 'form' ); - if ( context.wporg.queryFilter.isOpen ) { - const focusableElements = ref.querySelectorAll( focusableSelectors ); - context.wporg.queryFilter.firstFocusableElement = focusableElements[ 0 ]; - context.wporg.queryFilter.lastFocusableElement = - focusableElements[ focusableElements.length - 1 ]; - } - }, - checkPosition: ( { context, ref } ) => { - if ( context.wporg.queryFilter.isOpen ) { - const position = ref.getBoundingClientRect(); - if ( position.left < 0 ) { - ref.style.left = 0; - } - } - }, - focusFirstElement: ( { context, ref } ) => { - if ( context.wporg.queryFilter.isOpen ) { - ref.querySelector( 'form input:first-child' ).focus(); - } - }, - }, + if ( context.isOpen ) { + const focusableElements = ref.querySelectorAll( focusableSelectors ); + context.firstFocusableElement = focusableElements[ 0 ]; + context.lastFocusableElement = focusableElements[ focusableElements.length - 1 ]; + } + }, + checkPosition: () => { + const context = getContext(); + const { ref } = getElement(); + if ( context.isOpen ) { + const position = ref.getBoundingClientRect(); + if ( position.left < 0 ) { + ref.style.left = 0; + } + } + }, + focusFirstElement: () => { + const context = getContext(); + const { ref } = getElement(); + if ( context.isOpen ) { + ref.querySelector( 'form input:first-child' ).focus(); + } }, }, } );