[Experimental] Price filter: fix range slider update (#50935)

* Price filter: fix range slider update

* Add changefile(s) from automation for the following project(s): woocommerce-blocks, woocommerce

* Fix linting error

* Remove unneeded state setter

* Update plugins/woocommerce-blocks/assets/js/blocks/product-filter/inner-blocks/price-filter/frontend.ts

Co-authored-by: Alexandre Lara <allexandrelara@gmail.com>

* Fix linting error

---------

Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: Alexandre Lara <allexandrelara@gmail.com>
This commit is contained in:
Roy Ho 2024-08-26 19:57:01 -07:00 committed by GitHub
parent 5c58d9d50c
commit cc07a5f902
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 118 additions and 8 deletions

View File

@ -76,20 +76,88 @@ const debounceUpdate = debounce( ( context, element, event ) => {
);
}, 1000 );
const constrainRangeSliderValues = (
/**
* Tuple containing min and max values.
*/
values: [ number, number ],
/**
* Min allowed value for the sliders.
*/
min?: number | null,
/**
* Max allowed value for the sliders.
*/
max?: number | null,
/**
* Step value for the sliders.
*/
step = 1,
/**
* Whether we're currently interacting with the min range slider or not, so we update the correct values.
*/
isMin = false
): { minPrice: number; maxPrice: number } => {
let [ minValue, maxValue ] = values;
const isFinite = ( n: number | null | undefined ): n is number =>
Number.isFinite( n );
if ( ! isFinite( minValue ) ) {
minValue = min || 0;
}
if ( ! isFinite( maxValue ) ) {
maxValue = max || step;
}
if ( isFinite( min ) && min > minValue ) {
minValue = min;
}
if ( isFinite( max ) && max <= minValue ) {
minValue = max - step;
}
if ( isFinite( min ) && min >= maxValue ) {
maxValue = min + step;
}
if ( isFinite( max ) && max < maxValue ) {
maxValue = max;
}
if ( ! isMin && minValue >= maxValue ) {
minValue = maxValue - step;
}
if ( isMin && maxValue <= minValue ) {
maxValue = minValue + step;
}
return { minPrice: minValue, maxPrice: maxValue };
};
const getRangeStyle = (
minPrice: number,
maxPrice: number,
minRange: number,
maxRange: number
) => {
return `--low: ${
( 100 * ( minPrice - minRange ) ) / ( maxRange - minRange )
}%; --high: ${
( 100 * ( maxPrice - minRange ) ) / ( maxRange - minRange )
}%;`;
};
store< PriceFilterStore >( 'woocommerce/product-filter-price', {
state: {
rangeStyle: () => {
const { minPrice, maxPrice, minRange, maxRange } =
getContext< PriceFilterContext >();
return [
`--low: ${
( 100 * ( minPrice - minRange ) ) / ( maxRange - minRange )
}%`,
`--high: ${
( 100 * ( maxPrice - minRange ) ) / ( maxRange - minRange )
}%`,
].join( ';' );
return getRangeStyle( minPrice, maxPrice, minRange, maxRange );
},
formattedMinPrice: () => {
const { minPrice } = getContext< PriceFilterContext >();
@ -126,5 +194,40 @@ store< PriceFilterStore >( 'woocommerce/product-filter-price', {
} )
);
},
updateRange: ( event: HTMLElementEvent< HTMLInputElement > ) => {
const context = getContext< PriceFilterContext >();
const { minPrice, maxPrice, minRange, maxRange } = context;
const isMin = event.target.classList.contains( 'min' );
const targetValue = Number( event.target.value );
const stepValue = 1;
const currentValues: [ number, number ] = isMin
? [
Math.round( targetValue / stepValue ) * stepValue,
maxPrice,
]
: [
minPrice,
Math.round( targetValue / stepValue ) * stepValue,
];
const values = constrainRangeSliderValues(
currentValues,
minRange,
maxRange,
stepValue,
isMin
);
if ( targetValue >= maxPrice ) {
context.maxPrice = minPrice + 1;
} else if ( targetValue <= minPrice ) {
context.minPrice = maxPrice - 1;
}
if ( isMin ) {
context.minPrice = values.minPrice;
} else {
context.maxPrice = values.maxPrice;
}
},
},
} );

View File

@ -34,5 +34,6 @@ export type PriceFilterStore = {
updateProducts: ( event: HTMLElementEvent< HTMLInputElement > ) => void;
selectInputContent: () => void;
reset: () => void;
updateRange: ( event: HTMLElementEvent< HTMLInputElement > ) => void;
};
};

View File

@ -0,0 +1,4 @@
Significance: patch
Type: tweak
Comment: Price slider: fix range bar styling and dynamic input

View File

@ -234,6 +234,7 @@ final class ProductFilterPrice extends AbstractBlock {
data-wc-bind--max="context.maxRange"
data-wc-bind--value="context.minPrice"
data-wc-on--change="actions.updateProducts"
data-wc-on--input="actions.updateRange"
>
<input
type="range"
@ -246,6 +247,7 @@ final class ProductFilterPrice extends AbstractBlock {
data-wc-bind--max="context.maxRange"
data-wc-bind--value="context.maxPrice"
data-wc-on--change="actions.updateProducts"
data-wc-on--input="actions.updateRange"
>
</div>
<div class="wp-block-woocommerce-product-filter-price-content-right-input text">