Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/dataviews/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Unreleased

### Enhancements

- DataViews: Add Shift+Click range selection through a shared `useSelectionProps` hook that layouts can adopt, wired up in the table and grid layouts.[#80046](https://github.com/WordPress/gutenberg/pull/80046)

### Bug Fix

- DataViews: Fix the `list` layout ignoring the density setting, the refreshing state, and the loading state when `groupBy` is set. [#80255](https://github.com/WordPress/gutenberg/pull/80255)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,34 +59,35 @@ function ActionWithModal< Item >( {
);
}

export function hasAPossibleBulkAction< Item >(
actions: Action< Item >[],
item: Item
) {
return actions.some(
( action ) =>
action.supportsBulk &&
( ! action.isEligible || action.isEligible( item ) )
);
}

export function useHasAPossibleBulkAction< Item >(
actions: Action< Item >[],
item: Item
) {
return useMemo( () => {
return actions.some( ( action ) => {
return (
action.supportsBulk &&
( ! action.isEligible || action.isEligible( item ) )
);
} );
}, [ actions, item ] );
return useMemo(
() => hasAPossibleBulkAction( actions, item ),
[ actions, item ]
);
}

export function useSomeItemHasAPossibleBulkAction< Item >(
actions: Action< Item >[],
data: Item[]
) {
return useMemo( () => {
return data.some( ( item ) => {
return actions.some( ( action ) => {
return (
action.supportsBulk &&
( ! action.isEligible || action.isEligible( item ) )
);
} );
} );
}, [ actions, data ] );
return useMemo(
() => data.some( ( item ) => hasAPossibleBulkAction( actions, item ) ),
[ actions, data ]
);
}

interface BulkSelectionCheckboxProps< Item > {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import {
import { Stack, Tooltip } from '@wordpress/ui';
import { __, sprintf } from '@wordpress/i18n';
import { useInstanceId } from '@wordpress/compose';
import { isAppleOS } from '@wordpress/keycodes';
import {
useCallback,
useContext,
Expand All @@ -41,6 +40,7 @@ import type {
ViewGrid as ViewGridType,
} from '../../../types';
import type { SetSelection } from '../../../types/private';
import type { SelectionProps } from '../utils/use-selection-props';
import { ItemClickWrapper } from '../utils/item-click-wrapper';
const { Badge: WCBadge } = unlock( componentsPrivateApis );
import { useGridColumns } from './preview-size-picker';
Expand Down Expand Up @@ -184,23 +184,6 @@ const GridItem = forwardRef< HTMLDivElement, GridItemProps< any > >(
'is-selected': hasBulkAction && isSelected,
}
) }
onClickCapture={ ( event ) => {
props.onClickCapture?.( event );
if ( isAppleOS() ? event.metaKey : event.ctrlKey ) {
event.stopPropagation();
event.preventDefault();
if ( ! hasBulkAction ) {
return;
}
onChangeSelection(
isSelected
? selection.filter(
( itemId ) => id !== itemId
)
: [ ...selection, id ]
);
}
} }
>
<ItemClickWrapper
item={ item }
Expand Down Expand Up @@ -358,6 +341,7 @@ interface CompositeGridProps< Item > {
) => ReactElement;
getItemId: ( item: Item ) => string;
actions: Action< Item >[];
getSelectionProps: ( id: string ) => SelectionProps;
}

export default function CompositeGrid< Item >( {
Expand All @@ -375,6 +359,7 @@ export default function CompositeGrid< Item >( {
renderItemLink,
getItemId,
actions,
getSelectionProps,
}: CompositeGridProps< Item > ) {
const { paginationInfo, resizeObserverRef } =
useContext( DataViewsContext );
Expand Down Expand Up @@ -476,6 +461,7 @@ export default function CompositeGrid< Item >( {
) }
{ data.map( ( item ) => {
const itemId = getItemId( item );
const selectionProps = getSelectionProps( itemId );
// Use position from item for infinite scroll
const stablePosition = ( item as any ).position;
return (
Expand All @@ -497,6 +483,18 @@ export default function CompositeGrid< Item >( {
getItemId={ getItemId }
item={ item }
actions={ actions }
onMouseDown={ ( event ) => {
props.onMouseDown?.( event );
selectionProps.onMouseDown(
event
);
} }
onClickCapture={ ( event ) => {
props.onClickCapture?.( event );
selectionProps.onClickCapture(
event
);
} }
mediaField={ mediaField }
titleField={ titleField }
descriptionField={
Expand Down Expand Up @@ -560,6 +558,8 @@ export default function CompositeGrid< Item >( {
>
{ row.map( ( item ) => {
const itemId = getItemId( item );
const selectionProps =
getSelectionProps( itemId );
return (
<Composite.Item
key={ itemId }
Expand All @@ -583,6 +583,24 @@ export default function CompositeGrid< Item >( {
getItemId={ getItemId }
item={ item }
actions={ actions }
onMouseDown={ ( event ) => {
props.onMouseDown?.(
event
);
selectionProps.onMouseDown(
event
);
} }
onClickCapture={ (
event
) => {
props.onClickCapture?.(
event
);
selectionProps.onClickCapture(
event
);
} }
mediaField={ mediaField }
titleField={ titleField }
descriptionField={
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { Stack } from '@wordpress/ui';
*/
import type { ViewGridProps } from '../../../types';
import getDataByGroup from '../utils/get-data-by-group';
import useSelectionProps from '../utils/use-selection-props';
import CompositeGrid from './composite-grid';
import { useDelayedLoading } from '../../../hooks/use-delayed-loading';

Expand All @@ -40,6 +41,20 @@ function ViewGrid< Item >( {
: null;
const dataByGroup = groupField ? getDataByGroup( data, groupField ) : null;
const isInfiniteScroll = view.infiniteScrollEnabled && ! dataByGroup;
// The selection hook must see every selectable item in render order so a
// Shift+Click range can span groups and share a single anchor. Each
// CompositeGrid renders one group, so derive it here from the flattened
// group order rather than inside CompositeGrid.
const orderedData = dataByGroup
? Array.from( dataByGroup.values() ).flat()
: data;
const { getSelectionProps } = useSelectionProps( {
data: orderedData,
actions,
getItemId,
selection,
onChangeSelection,
} );
if ( ! hasData ) {
return (
<div
Expand All @@ -66,6 +81,7 @@ function ViewGrid< Item >( {
renderItemLink,
getItemId,
actions,
getSelectionProps,
};
return (
<>
Expand Down
Loading
Loading