134 lines
3.6 KiB
TypeScript
134 lines
3.6 KiB
TypeScript
/**
|
|
* External dependencies
|
|
*/
|
|
|
|
import { WP_REST_API_Category } from 'wp-types';
|
|
import { ProductResponseItem } from '@woocommerce/types';
|
|
import { Placeholder, Icon, Button } from '@wordpress/components';
|
|
import { __ } from '@wordpress/i18n';
|
|
import ProductCategoryControl from '@woocommerce/editor-components/product-category-control';
|
|
import ProductControl from '@woocommerce/editor-components/product-control';
|
|
import { ComponentType } from 'react';
|
|
|
|
/**
|
|
* Internal dependencies
|
|
*/
|
|
import { BLOCK_NAMES } from './constants';
|
|
import { EditorBlock, GenericBlockUIConfig } from './types';
|
|
import { getClassPrefixFromName } from './utils';
|
|
|
|
interface EditModeConfiguration extends GenericBlockUIConfig {
|
|
description: string;
|
|
editLabel: string;
|
|
}
|
|
|
|
type EditModeRequiredAttributes = {
|
|
categoryId?: number;
|
|
editMode: boolean;
|
|
mediaId: number;
|
|
mediaSrc: string;
|
|
productId?: number;
|
|
};
|
|
|
|
interface EditModeRequiredProps< T > {
|
|
attributes: EditModeRequiredAttributes & EditorBlock< T >[ 'attributes' ];
|
|
debouncedSpeak: ( label: string ) => void;
|
|
setAttributes: ( attrs: Partial< EditModeRequiredAttributes > ) => void;
|
|
triggerUrlUpdate: () => void;
|
|
}
|
|
|
|
type EditModeProps< T extends EditorBlock< T > > = T &
|
|
EditModeRequiredProps< T >;
|
|
|
|
export const withEditMode = ( {
|
|
description,
|
|
editLabel,
|
|
icon,
|
|
label,
|
|
}: EditModeConfiguration ) => < T extends EditorBlock< T > >(
|
|
Component: ComponentType< T >
|
|
) => ( props: EditModeProps< T > ) => {
|
|
const {
|
|
attributes,
|
|
debouncedSpeak,
|
|
name,
|
|
setAttributes,
|
|
triggerUrlUpdate = () => void null,
|
|
} = props;
|
|
|
|
const className = getClassPrefixFromName( name );
|
|
|
|
const onDone = () => {
|
|
setAttributes( { editMode: false } );
|
|
debouncedSpeak( editLabel );
|
|
};
|
|
|
|
if ( attributes.editMode ) {
|
|
return (
|
|
<Placeholder
|
|
icon={ <Icon icon={ icon } /> }
|
|
label={ label }
|
|
className={ className }
|
|
>
|
|
{ description }
|
|
<div className={ `${ className }__selection` }>
|
|
{ name === BLOCK_NAMES.featuredCategory && (
|
|
// Ignoring this TS error for now as it seems that `ProductCategoryControl`
|
|
// types might be too strict.
|
|
// @todo Convert `ProductCategoryControl` to TypeScript
|
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
// @ts-ignore
|
|
<ProductCategoryControl
|
|
selected={ [ attributes.categoryId ] }
|
|
onChange={ (
|
|
value: WP_REST_API_Category[] = []
|
|
) => {
|
|
const id = value[ 0 ] ? value[ 0 ].id : 0;
|
|
setAttributes( {
|
|
categoryId: id,
|
|
mediaId: 0,
|
|
mediaSrc: '',
|
|
} );
|
|
triggerUrlUpdate();
|
|
} }
|
|
isSingle
|
|
/>
|
|
) }
|
|
{ name === BLOCK_NAMES.featuredProduct && (
|
|
<ProductControl
|
|
selected={
|
|
attributes.productId
|
|
? [ attributes.productId ]
|
|
: []
|
|
}
|
|
// `ProductControl` is not yet a TypeScript file and the types
|
|
// are incorrectly generated for the wrapped HOC, so `showVariation`
|
|
// doesn't appear in the allowed props
|
|
// @todo Convert `ProductControl` to TypeScript
|
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
// @ts-ignore
|
|
showVariations
|
|
onChange={ (
|
|
value: ProductResponseItem[] = []
|
|
) => {
|
|
const id = value[ 0 ] ? value[ 0 ].id : 0;
|
|
setAttributes( {
|
|
productId: id,
|
|
mediaId: 0,
|
|
mediaSrc: '',
|
|
} );
|
|
triggerUrlUpdate();
|
|
} }
|
|
/>
|
|
) }
|
|
<Button isPrimary onClick={ onDone }>
|
|
{ __( 'Done', 'woo-gutenberg-products-block' ) }
|
|
</Button>
|
|
</div>
|
|
</Placeholder>
|
|
);
|
|
}
|
|
|
|
return <Component { ...props } />;
|
|
};
|