Create New Item
Item Type
File
Folder
Item Name
Search file in folder and subfolders...
Are you sure want to rename?
primogenial
/
plugins
/
woocommerce
/
packages
/
woocommerce-blocks
/
assets
/
js
/
blocks
/
active-filters
:
utils.tsx
Advanced Search
Upload
New Item
Settings
Back
Back Up
Advanced Editor
Save
/** * External dependencies */ import { __, sprintf } from '@wordpress/i18n'; import { formatPrice } from '@woocommerce/price-format'; import { RemovableChip } from '@woocommerce/base-components/chip'; import Label from '@woocommerce/base-components/label'; import { getQueryArgs, addQueryArgs, removeQueryArgs } from '@wordpress/url'; import { changeUrl } from '@woocommerce/utils'; import { Icon, closeSmall } from '@wordpress/icons'; /** * Format a min/max price range to display. * * @param {number} minPrice The min price, if set. * @param {number} maxPrice The max price, if set. */ export const formatPriceRange = ( minPrice: number, maxPrice: number ) => { if ( Number.isFinite( minPrice ) && Number.isFinite( maxPrice ) ) { return sprintf( /* translators: %1$s min price, %2$s max price */ __( 'Between %1$s and %2$s', 'woo-gutenberg-products-block' ), formatPrice( minPrice ), formatPrice( maxPrice ) ); } if ( Number.isFinite( minPrice ) ) { return sprintf( /* translators: %s min price */ __( 'From %s', 'woo-gutenberg-products-block' ), formatPrice( minPrice ) ); } return sprintf( /* translators: %s max price */ __( 'Up to %s', 'woo-gutenberg-products-block' ), formatPrice( maxPrice ) ); }; interface RemovableListItemProps { type: string; name: string; prefix?: string | JSX.Element; showLabel?: boolean; isLoading?: boolean; displayStyle: string; removeCallback?: () => void; } /** * Render a removable item in the active filters block list. * * @param {Object} listItem The removable item to render. * @param {string} listItem.type Type string. * @param {string} listItem.name Name string. * @param {string} [listItem.prefix=''] Prefix shown before item name. * @param {Function} listItem.removeCallback Callback to remove item. * @param {string} listItem.displayStyle Whether it's a list or chips. * @param {boolean} [listItem.showLabel=true] Should the label be shown for * this item? */ export const renderRemovableListItem = ( { type, name, prefix = '', removeCallback = () => null, showLabel = true, displayStyle, }: RemovableListItemProps ) => { const prefixedName = prefix ? ( <> { prefix } { name } </> ) : ( name ); const removeText = sprintf( /* translators: %s attribute value used in the filter. For example: yellow, green, small, large. */ __( 'Remove %s filter', 'woo-gutenberg-products-block' ), name ); return ( <li className="wc-block-active-filters__list-item" key={ type + ':' + name } > { showLabel && ( <span className="wc-block-active-filters__list-item-type"> { type + ': ' } </span> ) } { displayStyle === 'chips' ? ( <RemovableChip element="span" text={ prefixedName } onRemove={ removeCallback } radius="large" ariaLabel={ removeText } /> ) : ( <span className="wc-block-active-filters__list-item-name"> <button className="wc-block-active-filters__list-item-remove" onClick={ removeCallback } > <Icon className="wc-block-components-chip__remove-icon" icon={ closeSmall } size={ 16 } /> <Label screenReaderLabel={ removeText } /> </button> { prefixedName } </span> ) } </li> ); }; /** * Update the current URL to update or remove provided query arguments. * * * @param {Array<string|Record<string, string>>} args Args to remove */ export const removeArgsFromFilterUrl = ( ...args: ( string | Record< string, string > )[] ) => { if ( ! window ) { return; } const url = window.location.href; const currentQuery = getQueryArgs( url ); const cleanUrl = removeQueryArgs( url, ...Object.keys( currentQuery ) ); args.forEach( ( item ) => { if ( typeof item === 'string' ) { return delete currentQuery[ item ]; } if ( typeof item === 'object' ) { const key = Object.keys( item )[ 0 ]; const currentQueryValue = currentQuery[ key ] .toString() .split( ',' ); currentQuery[ key ] = currentQueryValue .filter( ( value ) => value !== item[ key ] ) .join( ',' ); } } ); const filteredQuery = Object.fromEntries( Object.entries( currentQuery ).filter( ( [ , value ] ) => value ) ); const newUrl = addQueryArgs( cleanUrl, filteredQuery ); changeUrl( newUrl ); }; /** * Prefixes typically expected before filters in the URL. */ const FILTER_QUERY_VALUES = [ 'min_price', 'max_price', 'rating_filter', 'filter_', 'query_type_', ]; /** * Check if the URL contains arguments that could be Woo filter keys. */ const keyIsAFilter = ( key: string ): boolean => { let keyIsFilter = false; for ( let i = 0; FILTER_QUERY_VALUES.length > i; i++ ) { const keyToMatch = FILTER_QUERY_VALUES[ i ]; const trimmedKey = key.substring( 0, keyToMatch.length ); if ( keyToMatch === trimmedKey ) { keyIsFilter = true; break; } } return keyIsFilter; }; /** * Clean the filter URL. */ export const cleanFilterUrl = () => { if ( ! window ) { return; } const url = window.location.href; const args = getQueryArgs( url ); const cleanUrl = removeQueryArgs( url, ...Object.keys( args ) ); const remainingArgs = Object.fromEntries( Object.keys( args ) .filter( ( arg ) => { if ( keyIsAFilter( arg ) ) { return false; } return true; } ) .map( ( key ) => [ key, args[ key ] ] ) ); const newUrl = addQueryArgs( cleanUrl, remainingArgs ); changeUrl( newUrl ); }; export const maybeUrlContainsFilters = (): boolean => { if ( ! window ) { return false; } const url = window.location.href; const args = getQueryArgs( url ); const filterKeys = Object.keys( args ); let maybeHasFilter = false; for ( let i = 0; filterKeys.length > i; i++ ) { const key = filterKeys[ i ]; if ( keyIsAFilter( key ) ) { maybeHasFilter = true; break; } } return maybeHasFilter; }; interface StoreAttributes { attribute_id: string; attribute_label: string; attribute_name: string; attribute_orderby: string; attribute_public: number; attribute_type: string; } export const urlContainsAttributeFilter = ( attributes: StoreAttributes[] ): boolean => { if ( ! window ) { return false; } const storeAttributeKeys = attributes.map( ( attr ) => `filter_${ attr.attribute_name }` ); const url = window.location.href; const args = getQueryArgs( url ); const urlFilterKeys = Object.keys( args ); let filterIsInUrl = false; for ( let i = 0; urlFilterKeys.length > i; i++ ) { const urlKey = urlFilterKeys[ i ]; if ( storeAttributeKeys.includes( urlKey ) ) { filterIsInUrl = true; break; } } return filterIsInUrl; };