[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:
parent
97e4c55aeb
commit
161bf51bd3
|
@ -11,7 +11,6 @@ import { PreviewDropdown } from '../../components/preview-dropdown';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
label: string;
|
label: string;
|
||||||
textColor: string;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const AttributeDropdown = ( { label }: Props ) => {
|
export const AttributeDropdown = ( { label }: Props ) => {
|
||||||
|
|
|
@ -41,8 +41,6 @@ import { Inspector } from './components/inspector-controls';
|
||||||
import { AttributeCheckboxList } from './components/attribute-checkbox-list';
|
import { AttributeCheckboxList } from './components/attribute-checkbox-list';
|
||||||
import { AttributeDropdown } from './components/attribute-dropdown';
|
import { AttributeDropdown } from './components/attribute-dropdown';
|
||||||
import './style.scss';
|
import './style.scss';
|
||||||
import { extractBuiltInColor } from '../../utils';
|
|
||||||
import { useStyleProps } from '../../../../base/hooks';
|
|
||||||
|
|
||||||
const ATTRIBUTES = getSetting< AttributeSetting[] >( 'attributes', [] );
|
const ATTRIBUTES = getSetting< AttributeSetting[] >( 'attributes', [] );
|
||||||
|
|
||||||
|
@ -62,13 +60,6 @@ const Edit = ( props: EditProps ) => {
|
||||||
showCounts,
|
showCounts,
|
||||||
} = blockAttributes;
|
} = 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 attributeObject = getAttributeFromId( attributeId );
|
||||||
|
|
||||||
const [ isEditing, setIsEditing ] = useState(
|
const [ isEditing, setIsEditing ] = useState(
|
||||||
|
@ -267,7 +258,6 @@ const Edit = ( props: EditProps ) => {
|
||||||
attributeObject.label ||
|
attributeObject.label ||
|
||||||
__( 'attribute', 'woocommerce' )
|
__( 'attribute', 'woocommerce' )
|
||||||
}
|
}
|
||||||
textColor={ textColor || '' }
|
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<AttributeCheckboxList
|
<AttributeCheckboxList
|
||||||
|
|
|
@ -15,6 +15,10 @@ interface ActiveAttributeFilterContext extends AttributeFilterContext {
|
||||||
value: string;
|
value: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function nonNullable< T >( value: T ): value is NonNullable< T > {
|
||||||
|
return value !== null && value !== undefined;
|
||||||
|
}
|
||||||
|
|
||||||
function getUrl(
|
function getUrl(
|
||||||
selectedTerms: string[],
|
selectedTerms: string[],
|
||||||
slug: string,
|
slug: string,
|
||||||
|
@ -47,18 +51,14 @@ store( 'woocommerce/collection-attribute-filter', {
|
||||||
const dropdownContext = getContext< DropdownContext >(
|
const dropdownContext = getContext< DropdownContext >(
|
||||||
'woocommerce/interactivity-dropdown'
|
'woocommerce/interactivity-dropdown'
|
||||||
);
|
);
|
||||||
|
|
||||||
const context = getContext< AttributeFilterContext >();
|
const context = getContext< AttributeFilterContext >();
|
||||||
|
const filters = dropdownContext.selectedItems
|
||||||
|
.map( ( item ) => item.value )
|
||||||
|
.filter( nonNullable );
|
||||||
|
|
||||||
if ( dropdownContext.selectedItem.value ) {
|
navigate(
|
||||||
navigate(
|
getUrl( filters, context.attributeSlug, context.queryType )
|
||||||
getUrl(
|
);
|
||||||
[ dropdownContext.selectedItem.value ],
|
|
||||||
context.attributeSlug,
|
|
||||||
context.queryType
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
updateProducts: ( event: HTMLElementEvent< HTMLInputElement > ) => {
|
updateProducts: ( event: HTMLElementEvent< HTMLInputElement > ) => {
|
||||||
if ( ! event.target.value ) return;
|
if ( ! event.target.value ) return;
|
||||||
|
|
|
@ -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;
|
|
||||||
};
|
|
|
@ -2,7 +2,6 @@
|
||||||
* External dependencies
|
* External dependencies
|
||||||
*/
|
*/
|
||||||
import { getContext, store } from '@woocommerce/interactivity';
|
import { getContext, store } from '@woocommerce/interactivity';
|
||||||
import { __ } from '@wordpress/i18n';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal dependencies
|
* Internal dependencies
|
||||||
|
@ -11,6 +10,7 @@ import './style.scss';
|
||||||
|
|
||||||
export type DropdownContext = {
|
export type DropdownContext = {
|
||||||
selectType: 'multiple' | 'single';
|
selectType: 'multiple' | 'single';
|
||||||
|
defaultPlaceholder: string;
|
||||||
item: {
|
item: {
|
||||||
label: string;
|
label: string;
|
||||||
value: string;
|
value: string;
|
||||||
|
@ -42,18 +42,18 @@ type DropdownStore = {
|
||||||
store< DropdownStore >( 'woocommerce/interactivity-dropdown', {
|
store< DropdownStore >( 'woocommerce/interactivity-dropdown', {
|
||||||
state: {
|
state: {
|
||||||
get placeholderText(): string {
|
get placeholderText(): string {
|
||||||
const { selectType, selectedItems } =
|
const { selectType, selectedItems, defaultPlaceholder } =
|
||||||
getContext< DropdownContext >();
|
getContext< DropdownContext >();
|
||||||
|
|
||||||
if ( selectType === 'single' ) {
|
if ( selectType === 'single' ) {
|
||||||
return selectedItems?.length && selectedItems[ 0 ].label
|
return selectedItems?.length && selectedItems[ 0 ].label
|
||||||
? selectedItems[ 0 ]?.label
|
? selectedItems[ 0 ]?.label
|
||||||
: __( 'Select an option', 'woocommerce' );
|
: defaultPlaceholder;
|
||||||
} else if (
|
} else if (
|
||||||
selectType === 'multiple' &&
|
selectType === 'multiple' &&
|
||||||
selectedItems.length === 0
|
selectedItems.length === 0
|
||||||
) {
|
) {
|
||||||
return __( 'Select options', 'woocommerce' );
|
return defaultPlaceholder;
|
||||||
}
|
}
|
||||||
|
|
||||||
return '';
|
return '';
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
Significance: patch
|
||||||
|
Type: add
|
||||||
|
|
||||||
|
[Experimental] support passing a placeholder text to the interactivity Dropdown component.
|
|
@ -211,8 +211,10 @@ final class CollectionAttributeFilter extends AbstractBlock {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
$list_items = array();
|
$list_items = array();
|
||||||
$selected_item = array();
|
$selected_items = array();
|
||||||
|
|
||||||
|
$product_attribute = wc_get_attribute( $attributes['attributeId'] );
|
||||||
|
|
||||||
foreach ( $options as $option ) {
|
foreach ( $options as $option ) {
|
||||||
$item = array(
|
$item = array(
|
||||||
|
@ -223,7 +225,7 @@ final class CollectionAttributeFilter extends AbstractBlock {
|
||||||
$list_items[] = $item;
|
$list_items[] = $item;
|
||||||
|
|
||||||
if ( $option['selected'] ) {
|
if ( $option['selected'] ) {
|
||||||
$selected_item = $item;
|
$selected_items[] = $item;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,7 +233,10 @@ final class CollectionAttributeFilter extends AbstractBlock {
|
||||||
array(
|
array(
|
||||||
'items' => $list_items,
|
'items' => $list_items,
|
||||||
'action' => 'woocommerce/collection-attribute-filter::actions.navigate',
|
'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 ),
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -222,7 +222,8 @@ final class CollectionRatingFilter extends AbstractBlock {
|
||||||
* @return array<array-key, array>
|
* @return array<array-key, array>
|
||||||
*/
|
*/
|
||||||
private function get_dropdown_props( $rating_counts, $selected_ratings_query, $show_counts, $select_type ) {
|
private function get_dropdown_props( $rating_counts, $selected_ratings_query, $show_counts, $select_type ) {
|
||||||
$ratings_array = explode( ',', $selected_ratings_query );
|
$ratings_array = explode( ',', $selected_ratings_query );
|
||||||
|
$placeholder_text = 'single' === $select_type ? __( 'Select a rating', 'woocommerce' ) : __( 'Select ratings', 'woocommerce' );
|
||||||
|
|
||||||
$selected_items = array_reduce(
|
$selected_items = array_reduce(
|
||||||
$rating_counts,
|
$rating_counts,
|
||||||
|
@ -259,6 +260,7 @@ final class CollectionRatingFilter extends AbstractBlock {
|
||||||
'select_type' => $select_type,
|
'select_type' => $select_type,
|
||||||
'selected_items' => $selected_items,
|
'selected_items' => $selected_items,
|
||||||
'action' => 'woocommerce/collection-rating-filter::actions.onDropdownChange',
|
'action' => 'woocommerce/collection-rating-filter::actions.onDropdownChange',
|
||||||
|
'placeholder' => $placeholder_text,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -151,6 +151,8 @@ final class CollectionStockFilter extends AbstractBlock {
|
||||||
$select_type = $attributes['selectType'] ?? 'single';
|
$select_type = $attributes['selectType'] ?? 'single';
|
||||||
$stock_statuses = wc_get_product_stock_status_options();
|
$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.
|
// check the url params to select initial item on page load.
|
||||||
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verification is not required here.
|
// 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 ] ) ) : '';
|
$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',
|
'action' => 'woocommerce/collection-stock-filter::actions.navigate',
|
||||||
'selected_items' => $selected_items,
|
'selected_items' => $selected_items,
|
||||||
'select_type' => $select_type,
|
'select_type' => $select_type,
|
||||||
|
'placeholder' => $placeholder_text,
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
?>
|
?>
|
||||||
|
|
|
@ -24,15 +24,18 @@ class Dropdown {
|
||||||
// Items should be an array of objects with a label and value property.
|
// Items should be an array of objects with a label and value property.
|
||||||
$items = $props['items'] ?? array();
|
$items = $props['items'] ?? array();
|
||||||
|
|
||||||
|
$default_placeholder = 'single' === $select_type ? __( 'Select an option', 'woocommerce' ) : __( 'Select options', 'woocommerce' );
|
||||||
|
$placeholder = $props['placeholder'] ?? $default_placeholder;
|
||||||
|
|
||||||
$dropdown_context = array(
|
$dropdown_context = array(
|
||||||
'selectedItems' => $selected_items,
|
'selectedItems' => $selected_items,
|
||||||
'isOpen' => false,
|
'isOpen' => false,
|
||||||
'selectType' => $select_type,
|
'selectType' => $select_type,
|
||||||
|
'defaultPlaceholder' => $placeholder,
|
||||||
);
|
);
|
||||||
|
|
||||||
$action = $props['action'] ?? '';
|
$action = $props['action'] ?? '';
|
||||||
$namespace = wp_json_encode( array( 'namespace' => 'woocommerce/interactivity-dropdown' ) );
|
$namespace = wp_json_encode( array( 'namespace' => 'woocommerce/interactivity-dropdown' ) );
|
||||||
$default_placeholder = 'single' === $select_type ? __( 'Select an option', 'woocommerce' ) : __( 'Select options', 'woocommerce' );
|
|
||||||
|
|
||||||
ob_start();
|
ob_start();
|
||||||
?>
|
?>
|
||||||
|
@ -41,7 +44,7 @@ class Dropdown {
|
||||||
<div class="wc-interactivity-dropdown__dropdown" tabindex="-1" >
|
<div class="wc-interactivity-dropdown__dropdown" tabindex="-1" >
|
||||||
<div class="wc-interactivity-dropdown__dropdown-selection" id="options-dropdown" tabindex="0" aria-haspopup="listbox">
|
<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">
|
<span class="wc-interactivity-dropdown__placeholder" data-wc-text="state.placeholderText">
|
||||||
<?php echo esc_html( $default_placeholder ); ?>
|
<?php echo esc_html( $placeholder ); ?>
|
||||||
</span>
|
</span>
|
||||||
<?php if ( 'multiple' === $select_type ) { ?>
|
<?php if ( 'multiple' === $select_type ) { ?>
|
||||||
<div class="selected-options">
|
<div class="selected-options">
|
||||||
|
@ -53,6 +56,7 @@ class Dropdown {
|
||||||
<span class="wc-interactivity-dropdown__badge-text" data-wc-text="context.item.label"></span>
|
<span class="wc-interactivity-dropdown__badge-text" data-wc-text="context.item.label"></span>
|
||||||
<svg
|
<svg
|
||||||
data-wc-on--click="actions.unselectDropdownItem"
|
data-wc-on--click="actions.unselectDropdownItem"
|
||||||
|
data-wc-on--click--parent-action="<?php echo esc_attr( $action ); ?>"
|
||||||
class="wc-interactivity-dropdown__badge-remove"
|
class="wc-interactivity-dropdown__badge-remove"
|
||||||
width="24"
|
width="24"
|
||||||
height="24"
|
height="24"
|
||||||
|
@ -68,12 +72,13 @@ class Dropdown {
|
||||||
<?php foreach ( $selected_items as $selected ) { ?>
|
<?php foreach ( $selected_items as $selected ) { ?>
|
||||||
<div
|
<div
|
||||||
class="wc-interactivity-dropdown__selected-badge"
|
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
|
data-wc-each-child
|
||||||
>
|
>
|
||||||
<span class="wc-interactivity-dropdown__badge-text"><?php echo esc_html( $selected['label'] ); ?></span>
|
<span class="wc-interactivity-dropdown__badge-text"><?php echo esc_html( $selected['label'] ); ?></span>
|
||||||
<svg
|
<svg
|
||||||
data-wc-on--click="actions.unselectDropdownItem"
|
data-wc-on--click="actions.unselectDropdownItem"
|
||||||
|
data-wc-on--click--parent-action="<?php echo esc_attr( $action ); ?>"
|
||||||
class="wc-interactivity-dropdown__badge-remove"
|
class="wc-interactivity-dropdown__badge-remove"
|
||||||
width="24"
|
width="24"
|
||||||
height="24"
|
height="24"
|
||||||
|
|
Loading…
Reference in New Issue