diff --git a/plugins/woocommerce-blocks/assets/js/blocks/product-collection/frontend.tsx b/plugins/woocommerce-blocks/assets/js/blocks/product-collection/frontend.tsx index 12b5f386209..09599b5b7b1 100644 --- a/plugins/woocommerce-blocks/assets/js/blocks/product-collection/frontend.tsx +++ b/plugins/woocommerce-blocks/assets/js/blocks/product-collection/frontend.tsx @@ -1,13 +1,7 @@ /** * External dependencies */ -import { - store, - navigate, - prefetch, - getElement, - getContext, -} from '@woocommerce/interactivity'; +import { store, getElement, getContext } from '@woocommerce/interactivity'; import { triggerProductListRenderedEvent } from '@woocommerce/base-utils'; /** @@ -120,7 +114,10 @@ const productCollectionStore = { ctx.animation = 'start'; }, 400 ); - yield navigate( ref.href ); + const { actions } = yield import( + '@woocommerce/interactivity-router' + ); + yield actions.navigate( ref.href ); // Clear the timeout if the navigation is fast. clearTimeout( timeout ); @@ -161,7 +158,10 @@ const productCollectionStore = { } if ( isValidLink( ref ) ) { - yield prefetch( ref.href ); + const { actions } = yield import( + '@woocommerce/interactivity-router' + ); + yield actions.prefetch( ref.href ); } }, }, @@ -183,7 +183,10 @@ const productCollectionStore = { const context = getContext< ProductCollectionStoreContext >(); if ( context?.isPrefetchNextOrPreviousLink && isValidLink( ref ) ) { - yield prefetch( ref.href ); + const { actions } = yield import( + '@woocommerce/interactivity-router' + ); + yield actions.prefetch( ref.href ); } }, *onRender() { diff --git a/plugins/woocommerce-blocks/assets/js/blocks/product-filters/inner-blocks/active-filters/frontend.ts b/plugins/woocommerce-blocks/assets/js/blocks/product-filters/inner-blocks/active-filters/frontend.ts index 0b462692f15..5cc1f613770 100644 --- a/plugins/woocommerce-blocks/assets/js/blocks/product-filters/inner-blocks/active-filters/frontend.ts +++ b/plugins/woocommerce-blocks/assets/js/blocks/product-filters/inner-blocks/active-filters/frontend.ts @@ -3,11 +3,6 @@ */ import { store, getContext } from '@woocommerce/interactivity'; -/** - * Internal dependencies - */ -import { navigate } from '../product-filter/frontend'; - type ActiveFiltersContext = { queryId: number; params: string[]; @@ -15,13 +10,14 @@ type ActiveFiltersContext = { store( 'woocommerce/product-filter-active', { actions: { - clearAll: () => { + *clearAll() { const { params } = getContext< ActiveFiltersContext >(); const url = new URL( window.location.href ); const { searchParams } = url; params.forEach( ( param ) => searchParams.delete( param ) ); - navigate( url.href ); + const { navigate } = yield import( '../product-filter/frontend' ); + yield navigate( url.href ); }, }, } ); diff --git a/plugins/woocommerce-blocks/assets/js/blocks/product-filters/inner-blocks/attribute-filter/frontend.ts b/plugins/woocommerce-blocks/assets/js/blocks/product-filters/inner-blocks/attribute-filter/frontend.ts index 0f9eb935586..287fae651f3 100644 --- a/plugins/woocommerce-blocks/assets/js/blocks/product-filters/inner-blocks/attribute-filter/frontend.ts +++ b/plugins/woocommerce-blocks/assets/js/blocks/product-filters/inner-blocks/attribute-filter/frontend.ts @@ -5,11 +5,6 @@ import { store, getContext } from '@woocommerce/interactivity'; import { DropdownContext } from '@woocommerce/interactivity-components/dropdown'; import { HTMLElementEvent } from '@woocommerce/types'; -/** - * Internal dependencies - */ -import { navigate } from '../product-filter/frontend'; - type AttributeFilterContext = { attributeSlug: string; queryType: 'or' | 'and'; @@ -52,7 +47,7 @@ function getSelectedTermsFromUrl( slug: string ) { store( 'woocommerce/product-filter-attribute', { actions: { - navigate: () => { + *navigate() { const dropdownContext = getContext< DropdownContext >( 'woocommerce/interactivity-dropdown' ); @@ -61,11 +56,12 @@ store( 'woocommerce/product-filter-attribute', { .map( ( item ) => item.value ) .filter( nonNullable ); - navigate( + const { navigate } = yield import( '../product-filter/frontend' ); + yield navigate( getUrl( filters, context.attributeSlug, context.queryType ) ); }, - updateProducts: ( event: HTMLElementEvent< HTMLInputElement > ) => { + *updateProducts( event: HTMLElementEvent< HTMLInputElement > ) { if ( ! event.target.value ) return; const context = getContext< AttributeFilterContext >(); @@ -88,7 +84,8 @@ store( 'woocommerce/product-filter-attribute', { ); } - navigate( + const { navigate } = yield import( '../product-filter/frontend' ); + yield navigate( getUrl( selectedTerms, context.attributeSlug, diff --git a/plugins/woocommerce-blocks/assets/js/blocks/product-filters/inner-blocks/clear-button/frontend.ts b/plugins/woocommerce-blocks/assets/js/blocks/product-filters/inner-blocks/clear-button/frontend.ts index 0bfc299b660..06a3224725d 100644 --- a/plugins/woocommerce-blocks/assets/js/blocks/product-filters/inner-blocks/clear-button/frontend.ts +++ b/plugins/woocommerce-blocks/assets/js/blocks/product-filters/inner-blocks/clear-button/frontend.ts @@ -3,11 +3,6 @@ */ import { store, getContext } from '@woocommerce/interactivity'; -/** - * Internal dependencies - */ -import { navigate } from '../product-filter/frontend'; - const getQueryParams = ( e: Event ) => { const filterNavContainer = ( e.target as HTMLElement )?.closest( 'nav.wp-block-woocommerce-product-filter' @@ -44,7 +39,7 @@ type ProductFilterContext = { store( 'woocommerce/product-filter', { actions: { - clear: ( e: Event ) => { + *clear( e: Event ) { const params = getQueryParams( e ); const url = new URL( window.location.href ); @@ -65,7 +60,10 @@ store( 'woocommerce/product-filter', { productFilterContext.hasSelectedFilter = false; if ( needsNavigate ) { - navigate( url.href ); + const { navigate } = yield import( + '../product-filter/frontend' + ); + yield navigate( url.href ); } }, }, diff --git a/plugins/woocommerce-blocks/assets/js/blocks/product-filters/inner-blocks/price-filter/frontend.ts b/plugins/woocommerce-blocks/assets/js/blocks/product-filters/inner-blocks/price-filter/frontend.ts index 844e3c364f6..0723d196022 100644 --- a/plugins/woocommerce-blocks/assets/js/blocks/product-filters/inner-blocks/price-filter/frontend.ts +++ b/plugins/woocommerce-blocks/assets/js/blocks/product-filters/inner-blocks/price-filter/frontend.ts @@ -9,7 +9,6 @@ import { debounce } from '@woocommerce/base-utils'; /** * Internal dependencies */ -import { navigate } from '../product-filter/frontend'; import type { PriceFilterContext, PriceFilterStore } from './types'; const getUrl = ( context: PriceFilterContext ) => { @@ -36,7 +35,7 @@ const getUrl = ( context: PriceFilterContext ) => { return url.href; }; -const debounceUpdate = debounce( ( context, element, event ) => { +const debounceUpdate = debounce( function* ( context, element, event ) { const { decimalSeparator } = getCurrency(); const { minRange, minPrice, maxPrice, maxRange } = context; const type = event.target.name; @@ -66,7 +65,9 @@ const debounceUpdate = debounce( ( context, element, event ) => { context.minPrice = currentMinPrice; context.maxPrice = currentMaxPrice; - navigate( + const { navigate } = yield import( '../product-filter/frontend' ); + + yield navigate( getUrl( { minRange, maxRange, @@ -184,8 +185,10 @@ store< PriceFilterStore >( 'woocommerce/product-filter-price', { element.ref.select(); } }, - reset: () => { - navigate( + *reset() { + const { navigate } = yield import( '../product-filter/frontend' ); + + yield navigate( getUrl( { minRange: 0, maxRange: 0, diff --git a/plugins/woocommerce-blocks/assets/js/blocks/product-filters/inner-blocks/product-filter/frontend.ts b/plugins/woocommerce-blocks/assets/js/blocks/product-filters/inner-blocks/product-filter/frontend.ts index 13a489f89c0..1871b5ed5ee 100644 --- a/plugins/woocommerce-blocks/assets/js/blocks/product-filters/inner-blocks/product-filter/frontend.ts +++ b/plugins/woocommerce-blocks/assets/js/blocks/product-filters/inner-blocks/product-filter/frontend.ts @@ -1,8 +1,8 @@ /** * External dependencies */ -import { navigate as navigateFn } from '@woocommerce/interactivity'; import { getSetting } from '@woocommerce/settings'; +import { store } from '@woocommerce/interactivity'; const isBlockTheme = getSetting< boolean >( 'isBlockTheme' ); const isProductArchive = getSetting< boolean >( 'isProductArchive' ); @@ -11,32 +11,42 @@ const needsRefresh = getSetting< boolean >( false ); -export function navigate( href: string, options = {} ) { - /** - * We may need to reset the current page when changing filters. - * This is because the current page may not exist for this set - * of filters and will 404 when the user navigates to it. - * - * There are different pagination formats to consider, as documented here: - * https://github.com/WordPress/gutenberg/blob/317eb8f14c8e1b81bf56972cca2694be250580e3/packages/block-library/src/query-pagination-numbers/index.php#L22-L85 - */ - const url = new URL( href ); - // When pretty permalinks are enabled, the page number may be in the path name. - url.pathname = url.pathname.replace( /\/page\/[0-9]+/i, '' ); - // When plain permalinks are enabled, the page number may be in the "paged" query parameter. - url.searchParams.delete( 'paged' ); - // On posts and pages the page number will be in a query parameter that - // identifies which block we are paginating. - url.searchParams.forEach( ( _, key ) => { - if ( key.match( /^query(?:-[0-9]+)?-page$/ ) ) { - url.searchParams.delete( key ); - } - } ); - // Make sure to update the href with the changes. - href = url.href; +const { actions } = store( 'woocommerce/product-filter-router', { + actions: { + *navigate( href: string, options = {} ) { + /** + * We may need to reset the current page when changing filters. + * This is because the current page may not exist for this set + * of filters and will 404 when the user navigates to it. + * + * There are different pagination formats to consider, as documented here: + * https://github.com/WordPress/gutenberg/blob/317eb8f14c8e1b81bf56972cca2694be250580e3/packages/block-library/src/query-pagination-numbers/index.php#L22-L85 + */ + const url = new URL( href ); + // When pretty permalinks are enabled, the page number may be in the path name. + url.pathname = url.pathname.replace( /\/page\/[0-9]+/i, '' ); + // When plain permalinks are enabled, the page number may be in the "paged" query parameter. + url.searchParams.delete( 'paged' ); + // On posts and pages the page number will be in a query parameter that + // identifies which block we are paginating. + url.searchParams.forEach( ( _, key ) => { + if ( key.match( /^query(?:-[0-9]+)?-page$/ ) ) { + url.searchParams.delete( key ); + } + } ); + // Make sure to update the href with the changes. + href = url.href; - if ( needsRefresh || ( ! isBlockTheme && isProductArchive ) ) { - return ( window.location.href = href ); - } - return navigateFn( href, options ); -} + if ( needsRefresh || ( ! isBlockTheme && isProductArchive ) ) { + return ( window.location.href = href ); + } + + const { actions: routerActions } = yield import( + '@woocommerce/interactivity-router' + ); + yield routerActions.navigate( href, options ); + }, + }, +} ); + +export const { navigate } = actions; diff --git a/plugins/woocommerce-blocks/assets/js/blocks/product-filters/inner-blocks/rating-filter/frontend.ts b/plugins/woocommerce-blocks/assets/js/blocks/product-filters/inner-blocks/rating-filter/frontend.ts index 3bd9f961704..59abfdaecb1 100644 --- a/plugins/woocommerce-blocks/assets/js/blocks/product-filters/inner-blocks/rating-filter/frontend.ts +++ b/plugins/woocommerce-blocks/assets/js/blocks/product-filters/inner-blocks/rating-filter/frontend.ts @@ -5,11 +5,6 @@ import { getContext, store } from '@woocommerce/interactivity'; import { CheckboxListContext } from '@woocommerce/interactivity-components/checkbox-list'; import { DropdownContext } from '@woocommerce/interactivity-components/dropdown'; -/** - * Internal dependencies - */ -import { navigate } from '../product-filter/frontend'; - function getUrl( filters: Array< string | null > ) { filters = filters.filter( Boolean ); const url = new URL( window.location.href ); @@ -27,7 +22,7 @@ function getUrl( filters: Array< string | null > ) { store( 'woocommerce/product-filter-rating', { actions: { - onCheckboxChange: () => { + *onCheckboxChange() { const checkboxContext = getContext< CheckboxListContext >( 'woocommerce/interactivity-checkbox-list' ); @@ -40,9 +35,11 @@ store( 'woocommerce/product-filter-rating', { return item.value; } ); - navigate( getUrl( filters ) ); + const { navigate } = yield import( '../product-filter/frontend' ); + + yield navigate( getUrl( filters ) ); }, - onDropdownChange: () => { + *onDropdownChange() { const dropdownContext = getContext< DropdownContext >( 'woocommerce/interactivity-dropdown' ); @@ -51,9 +48,10 @@ store( 'woocommerce/product-filter-rating', { const items = selectedItems || []; const filters = items.map( ( i ) => i.value ); - navigate( getUrl( filters ) ); + const { navigate } = yield import( '../product-filter/frontend' ); + yield navigate( getUrl( filters ) ); }, - removeFilter: () => { + *removeFilter() { const { value } = getContext< { value: string } >(); // get the active filters from the url: const url = new URL( window.location.href ); @@ -70,7 +68,8 @@ store( 'woocommerce/product-filter-rating', { filtersArr.splice( index, 1 ); } - navigate( getUrl( filtersArr ) ); + const { navigate } = yield import( '../product-filter/frontend' ); + yield navigate( getUrl( filtersArr ) ); }, }, } ); diff --git a/plugins/woocommerce-blocks/assets/js/blocks/product-filters/inner-blocks/stock-filter/frontend.ts b/plugins/woocommerce-blocks/assets/js/blocks/product-filters/inner-blocks/stock-filter/frontend.ts index 9833ff753c1..b49bfbf1100 100644 --- a/plugins/woocommerce-blocks/assets/js/blocks/product-filters/inner-blocks/stock-filter/frontend.ts +++ b/plugins/woocommerce-blocks/assets/js/blocks/product-filters/inner-blocks/stock-filter/frontend.ts @@ -6,11 +6,6 @@ import { DropdownContext } from '@woocommerce/interactivity-components/dropdown' import { HTMLElementEvent } from '@woocommerce/types'; import { CheckboxListContext } from '@woocommerce/interactivity-components/checkbox-list'; -/** - * Internal dependencies - */ -import { navigate } from '../product-filter/frontend'; - const getUrl = ( activeFilters: string ) => { const url = new URL( window.location.href ); const { searchParams } = url; @@ -26,7 +21,7 @@ const getUrl = ( activeFilters: string ) => { store( 'woocommerce/product-filter-stock-status', { actions: { - onCheckboxChange: () => { + *onCheckboxChange() { const checkboxContext = getContext< CheckboxListContext >( 'woocommerce/interactivity-checkbox-list' ); @@ -39,9 +34,10 @@ store( 'woocommerce/product-filter-stock-status', { return item.value; } ); - navigate( getUrl( filters.join( ',' ) ) ); + const { navigate } = yield import( '../product-filter/frontend' ); + yield navigate( getUrl( filters.join( ',' ) ) ); }, - onDropdownChange: () => { + *onDropdownChange() { const dropdownContext = getContext< DropdownContext >( 'woocommerce/interactivity-dropdown' ); @@ -49,10 +45,10 @@ store( 'woocommerce/product-filter-stock-status', { const selectedItems = dropdownContext.selectedItems; const items = selectedItems || []; const filters = items.map( ( i ) => i.value ); - - navigate( getUrl( filters.join( ',' ) ) ); + const { navigate } = yield import( '../product-filter/frontend' ); + yield navigate( getUrl( filters.join( ',' ) ) ); }, - updateProducts: ( event: HTMLElementEvent< HTMLInputElement > ) => { + *updateProducts( event: HTMLElementEvent< HTMLInputElement > ) { // get the active filters from the url: const url = new URL( window.location.href ); const currentFilters = @@ -74,10 +70,10 @@ store( 'woocommerce/product-filter-stock-status', { filtersArr.splice( index, 1 ); } } - - navigate( getUrl( filtersArr.join( ',' ) ) ); + const { navigate } = yield import( '../product-filter/frontend' ); + yield navigate( getUrl( filtersArr.join( ',' ) ) ); }, - removeFilter: () => { + *removeFilter() { const { value } = getContext< { value: string } >(); // get the active filters from the url: const url = new URL( window.location.href ); @@ -94,7 +90,8 @@ store( 'woocommerce/product-filter-stock-status', { filtersArr.splice( index, 1 ); } - navigate( getUrl( filtersArr.join( ',' ) ) ); + const { navigate } = yield import( '../product-filter/frontend' ); + yield navigate( getUrl( filtersArr.join( ',' ) ) ); }, }, } );