[Experimental] Allow overriding placeholder in interactivity Dropdown::render (#43211)

* add: multiple select support to attribute dropdown
* fix: remove active filter from dropdown
* chore: remove unused extractBuiltinColor

---------
Co-authored-by: Tung Du <dinhtungdu@gmail.com>
This commit is contained in:
Sam Seay 2024-01-03 15:52:45 +08:00 committed by GitHub
parent 97e4c55aeb
commit 161bf51bd3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 63 additions and 67 deletions

View File

@ -11,7 +11,6 @@ import { PreviewDropdown } from '../../components/preview-dropdown';
type Props = {
label: string;
textColor: string;
};
export const AttributeDropdown = ( { label }: Props ) => {

View File

@ -41,8 +41,6 @@ import { Inspector } from './components/inspector-controls';
import { AttributeCheckboxList } from './components/attribute-checkbox-list';
import { AttributeDropdown } from './components/attribute-dropdown';
import './style.scss';
import { extractBuiltInColor } from '../../utils';
import { useStyleProps } from '../../../../base/hooks';
const ATTRIBUTES = getSetting< AttributeSetting[] >( 'attributes', [] );
@ -62,13 +60,6 @@ const Edit = ( props: EditProps ) => {
showCounts,
} = blockAttributes;
const { className, style } = useStyleProps( props.attributes );
const builtInColor = extractBuiltInColor( className );
const textColor = builtInColor
? `var(--wp--preset--color--${ builtInColor })`
: style.color;
const attributeObject = getAttributeFromId( attributeId );
const [ isEditing, setIsEditing ] = useState(
@ -267,7 +258,6 @@ const Edit = ( props: EditProps ) => {
attributeObject.label ||
__( 'attribute', 'woocommerce' )
}
textColor={ textColor || '' }
/>
) : (
<AttributeCheckboxList

View File

@ -15,6 +15,10 @@ interface ActiveAttributeFilterContext extends AttributeFilterContext {
value: string;
}
function nonNullable< T >( value: T ): value is NonNullable< T > {
return value !== null && value !== undefined;
}
function getUrl(
selectedTerms: string[],
slug: string,
@ -47,18 +51,14 @@ store( 'woocommerce/collection-attribute-filter', {
const dropdownContext = getContext< DropdownContext >(
'woocommerce/interactivity-dropdown'
);
const context = getContext< AttributeFilterContext >();
const filters = dropdownContext.selectedItems
.map( ( item ) => item.value )
.filter( nonNullable );
if ( dropdownContext.selectedItem.value ) {
navigate(
getUrl(
[ dropdownContext.selectedItem.value ],
context.attributeSlug,
context.queryType
)
getUrl( filters, context.attributeSlug, context.queryType )
);
}
},
updateProducts: ( event: HTMLElementEvent< HTMLInputElement > ) => {
if ( ! event.target.value ) return;

View File

@ -1,12 +0,0 @@
/**
* Extracts the built-in color from a block class name string if it exists.
* Returns null if no built-in color is found.
*
* @param blockClassString The block class name string.
* @return {string|null} The color name or null if no built-in color is found.
*/
export const extractBuiltInColor = ( blockClassString: string ) => {
const regex = /has-(?!link|text|background)([a-z-]+)-color/;
const match = blockClassString.match( regex );
return match ? match[ 1 ] : null;
};

View File

@ -2,7 +2,6 @@
* External dependencies
*/
import { getContext, store } from '@woocommerce/interactivity';
import { __ } from '@wordpress/i18n';
/**
* Internal dependencies
@ -11,6 +10,7 @@ import './style.scss';
export type DropdownContext = {
selectType: 'multiple' | 'single';
defaultPlaceholder: string;
item: {
label: string;
value: string;
@ -42,18 +42,18 @@ type DropdownStore = {
store< DropdownStore >( 'woocommerce/interactivity-dropdown', {
state: {
get placeholderText(): string {
const { selectType, selectedItems } =
const { selectType, selectedItems, defaultPlaceholder } =
getContext< DropdownContext >();
if ( selectType === 'single' ) {
return selectedItems?.length && selectedItems[ 0 ].label
? selectedItems[ 0 ]?.label
: __( 'Select an option', 'woocommerce' );
: defaultPlaceholder;
} else if (
selectType === 'multiple' &&
selectedItems.length === 0
) {
return __( 'Select options', 'woocommerce' );
return defaultPlaceholder;
}
return '';

View File

@ -0,0 +1,4 @@
Significance: patch
Type: add
[Experimental] support passing a placeholder text to the interactivity Dropdown component.

View File

@ -212,7 +212,9 @@ final class CollectionAttributeFilter extends AbstractBlock {
}
$list_items = array();
$selected_item = array();
$selected_items = array();
$product_attribute = wc_get_attribute( $attributes['attributeId'] );
foreach ( $options as $option ) {
$item = array(
@ -223,7 +225,7 @@ final class CollectionAttributeFilter extends AbstractBlock {
$list_items[] = $item;
if ( $option['selected'] ) {
$selected_item = $item;
$selected_items[] = $item;
}
}
@ -231,7 +233,10 @@ final class CollectionAttributeFilter extends AbstractBlock {
array(
'items' => $list_items,
'action' => 'woocommerce/collection-attribute-filter::actions.navigate',
'selected_items' => array( $selected_item ),
'selected_items' => $selected_items,
'select_type' => $attributes['selectType'] ?? 'multiple',
// translators: %s is a product attribute name.
'placeholder' => sprintf( __( 'Select %s', 'woocommerce' ), $product_attribute->name ),
)
);
}

View File

@ -223,6 +223,7 @@ final class CollectionRatingFilter extends AbstractBlock {
*/
private function get_dropdown_props( $rating_counts, $selected_ratings_query, $show_counts, $select_type ) {
$ratings_array = explode( ',', $selected_ratings_query );
$placeholder_text = 'single' === $select_type ? __( 'Select a rating', 'woocommerce' ) : __( 'Select ratings', 'woocommerce' );
$selected_items = array_reduce(
$rating_counts,
@ -259,6 +260,7 @@ final class CollectionRatingFilter extends AbstractBlock {
'select_type' => $select_type,
'selected_items' => $selected_items,
'action' => 'woocommerce/collection-rating-filter::actions.onDropdownChange',
'placeholder' => $placeholder_text,
);
}
}

View File

@ -151,6 +151,8 @@ final class CollectionStockFilter extends AbstractBlock {
$select_type = $attributes['selectType'] ?? 'single';
$stock_statuses = wc_get_product_stock_status_options();
$placeholder_text = 'single' === $select_type ? __( 'Select stock status', 'woocommerce' ) : __( 'Select stock statuses', 'woocommerce' );
// check the url params to select initial item on page load.
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verification is not required here.
$query = isset( $_GET[ self::STOCK_STATUS_QUERY_VAR ] ) ? sanitize_text_field( wp_unslash( $_GET[ self::STOCK_STATUS_QUERY_VAR ] ) ) : '';
@ -236,6 +238,7 @@ final class CollectionStockFilter extends AbstractBlock {
'action' => 'woocommerce/collection-stock-filter::actions.navigate',
'selected_items' => $selected_items,
'select_type' => $select_type,
'placeholder' => $placeholder_text,
)
);
?>

View File

@ -24,15 +24,18 @@ class Dropdown {
// Items should be an array of objects with a label and value property.
$items = $props['items'] ?? array();
$default_placeholder = 'single' === $select_type ? __( 'Select an option', 'woocommerce' ) : __( 'Select options', 'woocommerce' );
$placeholder = $props['placeholder'] ?? $default_placeholder;
$dropdown_context = array(
'selectedItems' => $selected_items,
'isOpen' => false,
'selectType' => $select_type,
'defaultPlaceholder' => $placeholder,
);
$action = $props['action'] ?? '';
$namespace = wp_json_encode( array( 'namespace' => 'woocommerce/interactivity-dropdown' ) );
$default_placeholder = 'single' === $select_type ? __( 'Select an option', 'woocommerce' ) : __( 'Select options', 'woocommerce' );
ob_start();
?>
@ -41,7 +44,7 @@ class Dropdown {
<div class="wc-interactivity-dropdown__dropdown" tabindex="-1" >
<div class="wc-interactivity-dropdown__dropdown-selection" id="options-dropdown" tabindex="0" aria-haspopup="listbox">
<span class="wc-interactivity-dropdown__placeholder" data-wc-text="state.placeholderText">
<?php echo esc_html( $default_placeholder ); ?>
<?php echo esc_html( $placeholder ); ?>
</span>
<?php if ( 'multiple' === $select_type ) { ?>
<div class="selected-options">
@ -53,6 +56,7 @@ class Dropdown {
<span class="wc-interactivity-dropdown__badge-text" data-wc-text="context.item.label"></span>
<svg
data-wc-on--click="actions.unselectDropdownItem"
data-wc-on--click--parent-action="<?php echo esc_attr( $action ); ?>"
class="wc-interactivity-dropdown__badge-remove"
width="24"
height="24"
@ -68,12 +72,13 @@ class Dropdown {
<?php foreach ( $selected_items as $selected ) { ?>
<div
class="wc-interactivity-dropdown__selected-badge"
data-wc-key="<?php echo esc_attr( $selected['label'] ); ?>"
data-wc-key="<?php echo esc_attr( $selected['value'] ); ?>"
data-wc-each-child
>
<span class="wc-interactivity-dropdown__badge-text"><?php echo esc_html( $selected['label'] ); ?></span>
<svg
data-wc-on--click="actions.unselectDropdownItem"
data-wc-on--click--parent-action="<?php echo esc_attr( $action ); ?>"
class="wc-interactivity-dropdown__badge-remove"
width="24"
height="24"