Add slotFills for header items (#43687)

* Add slotFills for header items

* Refactor plugin-header-items

* Add changelog

* Remove order prop

* Fix lint

* Change constant name

* Rename constant

* Add callback to fills

* Make icon not required

* Add fallback plugin
This commit is contained in:
Fernando Marichal 2024-01-30 16:58:20 -03:00 committed by GitHub
parent 05aa24df0b
commit e703b3d947
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 124 additions and 1 deletions

View File

@ -0,0 +1,4 @@
Significance: minor
Type: add
Add slotFills for header items #43687

View File

@ -10,6 +10,10 @@ import { Button, Tooltip } from '@wordpress/components';
import { chevronLeft, group, Icon } from '@wordpress/icons';
import { getNewPath, navigateTo } from '@woocommerce/navigation';
import { recordEvent } from '@woocommerce/tracks';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore No types for this exist yet.
// eslint-disable-next-line @woocommerce/dependency-group
import { PinnedItems } from '@wordpress/interface';
/**
* Internal dependencies
@ -20,7 +24,7 @@ import { PreviewButton } from './preview-button';
import { SaveDraftButton } from './save-draft-button';
import { PublishButton } from './publish-button';
import { Tabs } from '../tabs';
import { TRACKS_SOURCE } from '../../constants';
import { HEADER_PINNED_ITEMS_SCOPE, TRACKS_SOURCE } from '../../constants';
export type HeaderProps = {
onTabSelect: ( tabId: string | null ) => void;
@ -156,6 +160,7 @@ export function Header( {
/>
<WooHeaderItem.Slot name="product" />
<PinnedItems.Slot scope={ HEADER_PINNED_ITEMS_SCOPE } />
<MoreMenu />
</div>
</div>

View File

@ -1,2 +1,3 @@
export * from './header';
export * from './woo-more-menu-item';
export * from './plugin-header-items';

View File

@ -0,0 +1,2 @@
export * from './plugin-header-item-modal';
export * from './plugin-header-item-popover';

View File

@ -0,0 +1,49 @@
/**
* External dependencies
*/
import { createElement, Fragment, useState } from '@wordpress/element';
import { Button, Modal } from '@wordpress/components';
import { plugins } from '@wordpress/icons';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore No types for this exist yet.
// eslint-disable-next-line @woocommerce/dependency-group
import { PinnedItems } from '@wordpress/interface';
/**
* Internal dependencies
*/
import { HEADER_PINNED_ITEMS_SCOPE } from '../../../constants';
import { PluginHeaderItemModalProps } from './types';
export const PluginHeaderItemModal: React.FC< PluginHeaderItemModalProps > = ( {
children,
label,
icon,
title,
} ) => {
const [ isOpen, setOpen ] = useState( false );
const childrenToRender =
typeof children === 'function'
? children( { isOpen, setOpen } )
: children;
return (
<PinnedItems scope={ HEADER_PINNED_ITEMS_SCOPE }>
<>
<Button
variant="tertiary"
icon={ icon ?? plugins }
label={ label }
onClick={ () => setOpen( ! isOpen ) }
/>
{ isOpen && (
<Modal
title={ title }
onRequestClose={ () => setOpen( false ) }
>
{ childrenToRender }
</Modal>
) }
</>
</PinnedItems>
);
};

View File

@ -0,0 +1,47 @@
/**
* External dependencies
*/
import { createElement, Fragment, useState } from '@wordpress/element';
import { Button, Popover } from '@wordpress/components';
import { plugins } from '@wordpress/icons';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore No types for this exist yet.
// eslint-disable-next-line @woocommerce/dependency-group
import { PinnedItems } from '@wordpress/interface';
/**
* Internal dependencies
*/
import { HEADER_PINNED_ITEMS_SCOPE } from '../../../constants';
import { PluginHeaderItemPopoverProps } from './types';
export const PluginHeaderItemPopover: React.FC<
PluginHeaderItemPopoverProps
> = ( { children, label, icon } ) => {
const [ isVisible, setVisible ] = useState( false );
const childrenToRender =
typeof children === 'function'
? children( { isVisible, setVisible } )
: children;
return (
<PinnedItems scope={ HEADER_PINNED_ITEMS_SCOPE }>
<>
<Button
variant="tertiary"
icon={ icon ?? plugins }
label={ label }
onClick={ () => setVisible( ! isVisible ) }
/>
{ isVisible && (
<Popover
onFocusOutside={ () => setVisible( false ) }
onClose={ () => setVisible( false ) }
focusOnMount="container"
>
{ childrenToRender }
</Popover>
) }
</>
</PinnedItems>
);
};

View File

@ -0,0 +1,12 @@
export type PluginHeaderItemModalProps = {
children?: React.ReactNode;
icon?: React.ReactNode;
label?: string;
title: string;
};
export type PluginHeaderItemPopoverProps = {
children?: React.ReactNode;
icon?: React.ReactNode;
label?: string;
};

View File

@ -10,6 +10,7 @@ export { DetailsFeatureField as __experimentalDetailsFeatureField } from './deta
export { DetailsSummaryField as __experimentalDetailsSummaryField } from './details-summary-field';
export { DetailsDescriptionField as __experimentalDetailsDescriptionField } from './details-description-field';
export { WooProductMoreMenuItem as __experimentalWooProductMoreMenuItem } from './header';
export { PluginHeaderItemModal, PluginHeaderItemPopover } from './header';
export {
Editor as __experimentalEditor,
initBlocks as __experimentalInitBlocks,

View File

@ -55,6 +55,8 @@ export const PRODUCT_SCHEDULED_SALE_SLUG = 'product-scheduled-sale';
export const TRACKS_SOURCE = 'product-block-editor-v1';
export const HEADER_PINNED_ITEMS_SCOPE = 'woocommerce/product-editor';
/**
* Since the pagination component does not exposes the way of
* changing the per page options which are [25, 50, 75, 100]