Skip to content

Commit

Permalink
DataViews: Type the BulkActionsToolbar component (#61673)
Browse files Browse the repository at this point in the history
Co-authored-by: youknowriad <youknowriad@git.wordpress.org>
Co-authored-by: jorgefilipecosta <jorgefilipecosta@git.wordpress.org>
  • Loading branch information
3 people authored May 16, 2024
1 parent 2c3d996 commit 6a51b24
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,30 @@ import { useReducedMotion } from '@wordpress/compose';
* Internal dependencies
*/
import { ActionWithModal } from './item-actions';
import type { Action, AnyItem } from './types';
import type { ActionTriggerProps } from './item-actions';

interface ActionButtonProps< Item extends AnyItem > {
action: Action< Item >;
selectedItems: Item[];
actionInProgress: string | null;
setActionInProgress: ( actionId: string | null ) => void;
}

interface ToolbarContentProps< Item extends AnyItem > {
selection: string[];
actionsToShow: Action< Item >[];
selectedItems: Item[];
setSelection: ( selection: Item[] ) => void;
}

interface BulkActionsToolbarProps< Item extends AnyItem > {
data: Item[];
selection: string[];
actions: Action< Item >[];
setSelection: ( selection: Item[] ) => void;
getItemId: ( item: Item ) => string;
}

const SNACKBAR_VARIANTS = {
init: {
Expand All @@ -37,7 +61,11 @@ const SNACKBAR_VARIANTS = {
},
};

function ActionTrigger( { action, onClick, isBusy } ) {
function ActionTrigger< Item extends AnyItem >( {
action,
onClick,
isBusy,
}: ActionTriggerProps< Item > ) {
return (
<ToolbarButton
disabled={ isBusy }
Expand All @@ -53,58 +81,49 @@ function ActionTrigger( { action, onClick, isBusy } ) {
);
}

const EMPTY_ARRAY = [];
const EMPTY_ARRAY: [] = [];

function ActionButton( {
function ActionButton< Item extends AnyItem >( {
action,
selectedItems,
actionInProgress,
setActionInProgress,
} ) {
}: ActionButtonProps< Item > ) {
const selectedEligibleItems = useMemo( () => {
return selectedItems.filter( ( item ) => {
return action.isEligible( item );
return ! action.isEligible || action.isEligible( item );
} );
}, [ action, selectedItems ] );
if ( !! action.RenderModal ) {
if ( 'RenderModal' in action ) {
return (
<ActionWithModal
key={ action.id }
action={ action }
items={ selectedEligibleItems }
ActionTrigger={ ActionTrigger }
onActionStart={ () => {
setActionInProgress( action.id );
} }
onActionPerformed={ () => {
setActionInProgress( null );
} }
/>
);
}
return (
<ActionTrigger
key={ action.id }
action={ action }
items={ selectedItems }
onClick={ () => {
setActionInProgress( action.id );
action.callback( selectedItems, () => {
setActionInProgress( action.id );
} );
action.callback( selectedItems );
} }
isBusy={ actionInProgress === action.id }
/>
);
}

function renderToolbarContent(
selection,
actionsToShow,
selectedItems,
actionInProgress,
setActionInProgress,
setSelection
function renderToolbarContent< Item extends AnyItem >(
selection: string[],
actionsToShow: Action< Item >[],
selectedItems: Item[],
actionInProgress: string | null,
setActionInProgress: ( actionId: string | null ) => void,
setSelection: ( selection: Item[] ) => void
) {
return (
<>
Expand Down Expand Up @@ -152,14 +171,16 @@ function renderToolbarContent(
);
}

function ToolbarContent( {
function ToolbarContent< Item extends AnyItem >( {
selection,
actionsToShow,
selectedItems,
setSelection,
} ) {
const [ actionInProgress, setActionInProgress ] = useState( null );
const buttons = useRef( null );
}: ToolbarContentProps< Item > ) {
const [ actionInProgress, setActionInProgress ] = useState< string | null >(
null
);
const buttons = useRef< JSX.Element | null >( null );
if ( ! actionInProgress ) {
if ( buttons.current ) {
buttons.current = null;
Expand All @@ -185,13 +206,13 @@ function ToolbarContent( {
return buttons.current;
}

export default function BulkActionsToolbar( {
export default function BulkActionsToolbar< Item extends AnyItem >( {
data,
selection,
actions = EMPTY_ARRAY,
setSelection,
getItemId,
} ) {
}: BulkActionsToolbarProps< Item > ) {
const isReducedMotion = useReducedMotion();
const selectedItems = useMemo( () => {
return data.filter( ( item ) =>
Expand All @@ -205,7 +226,10 @@ export default function BulkActionsToolbar( {
return (
action.supportsBulk &&
action.icon &&
selectedItems.some( ( item ) => action.isEligible( item ) )
selectedItems.some(
( item ) =>
! action.isEligible || action.isEligible( item )
)
);
} ),
[ actions, selectedItems ]
Expand Down
16 changes: 5 additions & 11 deletions packages/dataviews/src/item-actions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,10 @@ const {
kebabCase,
} = unlock( componentsPrivateApis );

interface ButtonTriggerProps< Item extends AnyItem > {
action: Action< Item >;
onClick: MouseEventHandler;
}

interface DropdownMenuItemTriggerProps< Item extends AnyItem > {
export interface ActionTriggerProps< Item extends AnyItem > {
action: Action< Item >;
onClick: MouseEventHandler;
isBusy?: boolean;
}

interface ActionModalProps< Item extends AnyItem > {
Expand All @@ -48,9 +44,7 @@ interface ActionModalProps< Item extends AnyItem > {

interface ActionWithModalProps< Item extends AnyItem >
extends ActionModalProps< Item > {
ActionTrigger: (
props: ButtonTriggerProps< Item > | DropdownMenuItemTriggerProps< Item >
) => ReactElement;
ActionTrigger: ( props: ActionTriggerProps< Item > ) => ReactElement;
isBusy?: boolean;
}

Expand All @@ -73,7 +67,7 @@ interface CompactItemActionsProps< Item extends AnyItem > {
function ButtonTrigger< Item extends AnyItem >( {
action,
onClick,
}: ButtonTriggerProps< Item > ) {
}: ActionTriggerProps< Item > ) {
return (
<Button
label={ action.label }
Expand All @@ -88,7 +82,7 @@ function ButtonTrigger< Item extends AnyItem >( {
function DropdownMenuItemTrigger< Item extends AnyItem >( {
action,
onClick,
}: DropdownMenuItemTriggerProps< Item > ) {
}: ActionTriggerProps< Item > ) {
return (
<DropdownMenuItem
onClick={ onClick }
Expand Down

0 comments on commit 6a51b24

Please sign in to comment.