/** * WordPress dependencies */ import { Button, CheckboxControl } from '@wordpress/components'; import { useRegistry } from '@wordpress/data'; import { useContext, useMemo, useState } from '@wordpress/element'; import { Stack } from '@wordpress/ui'; import { __ } from '@wordpress/i18n'; /** * Internal dependencies */ import DataViewsPagination from '../dataviews-pagination'; import DataViewsContext from '../dataviews-context'; import type { SetSelection } from '../../types/private'; import type { Action } from '../../types'; import getFooterMessage from '../../utils/get-footer-message'; const EMPTY_ARRAY: [] = []; export function useIsMultiselectPicker< Item >( actions: Action< Item >[] | undefined ) { return useMemo( () => { return actions?.every( ( action ) => action.supportsBulk ); }, [ actions ] ); } function BulkSelectionCheckbox< Item >( { selection, selectedItems, onChangeSelection, data, getItemId, disableSelectAll = false, }: { selection: string[]; selectedItems: Item[]; onChangeSelection: SetSelection; data: Item[]; getItemId: ( item: Item ) => string; disableSelectAll?: boolean; } ) { const hasSelection = selection.length > 0; const areAllSelected = selectedItems.length === data.length; if ( disableSelectAll ) { return ( { onChangeSelection( [] ); } } aria-label={ __( 'Deselect all' ) } /> ); } return ( { if ( areAllSelected ) { // Deselect all - remove the current page from the total selection. onChangeSelection( selection.filter( ( id ) => ! data.some( ( item ) => id === getItemId( item ) ) ) ); } else { // Select all - merge the current page into the total selection. const selectionSet = new Set( [ ...selection, ...data.map( ( item ) => getItemId( item ) ), ] ); onChangeSelection( Array.from( selectionSet ) ); } } } aria-label={ areAllSelected ? __( 'Deselect all' ) : __( 'Select all' ) } /> ); } function ActionButtons< Item >( { actions, items, selection, }: { actions: Action< Item >[]; items: Item[]; selection: string[]; } ) { const registry = useRegistry(); const [ actionInProgress, setActionInProgress ] = useState< string | null >( null ); return ( { actions.map( ( action ) => { // Only support actions with callbacks for DataViewsPicker. // This is because many use cases of the picker will be already within modals. if ( ! ( 'callback' in action ) ) { return null; } const { id, label, icon, isPrimary, callback } = action; const _label = typeof label === 'string' ? label : label( items ); const variant = isPrimary ? 'primary' : 'tertiary'; const isInProgress = id === actionInProgress; return ( ); } ) } ); } export function DataViewsPickerFooter() { const { data, selection, onChangeSelection, getItemId, actions = EMPTY_ARRAY, paginationInfo, view, } = useContext( DataViewsContext ); const isMultiselect = useIsMultiselectPicker( actions ); const message = getFooterMessage( selection.length, data.length, paginationInfo.totalItems, !! view.infiniteScrollEnabled ); const selectedItems = useMemo( () => data.filter( ( item ) => selection.includes( getItemId( item ) ) ), [ selection, getItemId, data ] ); return ( { isMultiselect && ( ) } { message } { Boolean( actions?.length ) && (
) }
); }