@wordpress/dataviews 4.2.0 → 4.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/README.md +47 -7
  3. package/build/components/dataviews/index.js +3 -5
  4. package/build/components/dataviews/index.js.map +1 -1
  5. package/build/components/dataviews-bulk-actions/index.js +145 -141
  6. package/build/components/dataviews-bulk-actions/index.js.map +1 -1
  7. package/build/components/dataviews-filters/add-filter.js +4 -6
  8. package/build/components/dataviews-filters/add-filter.js.map +1 -1
  9. package/build/components/dataviews-filters/search-widget.js +28 -18
  10. package/build/components/dataviews-filters/search-widget.js.map +1 -1
  11. package/build/components/dataviews-footer/index.js +45 -0
  12. package/build/components/dataviews-footer/index.js.map +1 -0
  13. package/build/components/dataviews-item-actions/index.js +5 -8
  14. package/build/components/dataviews-item-actions/index.js.map +1 -1
  15. package/build/components/dataviews-pagination/index.js +4 -4
  16. package/build/components/dataviews-pagination/index.js.map +1 -1
  17. package/build/components/dataviews-view-config/index.js +171 -32
  18. package/build/components/dataviews-view-config/index.js.map +1 -1
  19. package/build/dataforms-layouts/panel/index.js +4 -1
  20. package/build/dataforms-layouts/panel/index.js.map +1 -1
  21. package/build/dataviews-layouts/index.js +48 -2
  22. package/build/dataviews-layouts/index.js.map +1 -1
  23. package/build/dataviews-layouts/list/index.js +124 -84
  24. package/build/dataviews-layouts/list/index.js.map +1 -1
  25. package/build/dataviews-layouts/table/column-header-menu.js +52 -54
  26. package/build/dataviews-layouts/table/column-header-menu.js.map +1 -1
  27. package/build/dataviews-layouts/table/index.js +7 -35
  28. package/build/dataviews-layouts/table/index.js.map +1 -1
  29. package/build/normalize-fields.js +4 -2
  30. package/build/normalize-fields.js.map +1 -1
  31. package/build/types.js.map +1 -1
  32. package/build-module/components/dataviews/index.js +3 -5
  33. package/build-module/components/dataviews/index.js.map +1 -1
  34. package/build-module/components/dataviews-bulk-actions/index.js +145 -143
  35. package/build-module/components/dataviews-bulk-actions/index.js.map +1 -1
  36. package/build-module/components/dataviews-filters/add-filter.js +4 -6
  37. package/build-module/components/dataviews-filters/add-filter.js.map +1 -1
  38. package/build-module/components/dataviews-filters/search-widget.js +28 -18
  39. package/build-module/components/dataviews-filters/search-widget.js.map +1 -1
  40. package/build-module/components/dataviews-footer/index.js +38 -0
  41. package/build-module/components/dataviews-footer/index.js.map +1 -0
  42. package/build-module/components/dataviews-item-actions/index.js +5 -8
  43. package/build-module/components/dataviews-item-actions/index.js.map +1 -1
  44. package/build-module/components/dataviews-pagination/index.js +5 -5
  45. package/build-module/components/dataviews-pagination/index.js.map +1 -1
  46. package/build-module/components/dataviews-view-config/index.js +177 -38
  47. package/build-module/components/dataviews-view-config/index.js.map +1 -1
  48. package/build-module/dataforms-layouts/panel/index.js +4 -1
  49. package/build-module/dataforms-layouts/panel/index.js.map +1 -1
  50. package/build-module/dataviews-layouts/index.js +45 -1
  51. package/build-module/dataviews-layouts/index.js.map +1 -1
  52. package/build-module/dataviews-layouts/list/index.js +125 -83
  53. package/build-module/dataviews-layouts/list/index.js.map +1 -1
  54. package/build-module/dataviews-layouts/table/column-header-menu.js +52 -54
  55. package/build-module/dataviews-layouts/table/column-header-menu.js.map +1 -1
  56. package/build-module/dataviews-layouts/table/index.js +9 -37
  57. package/build-module/dataviews-layouts/table/index.js.map +1 -1
  58. package/build-module/normalize-fields.js +4 -2
  59. package/build-module/normalize-fields.js.map +1 -1
  60. package/build-module/types.js.map +1 -1
  61. package/build-style/style-rtl.css +79 -63
  62. package/build-style/style.css +79 -63
  63. package/build-types/components/dataviews/index.d.ts.map +1 -1
  64. package/build-types/components/dataviews/stories/fixtures.d.ts +27 -131
  65. package/build-types/components/dataviews/stories/fixtures.d.ts.map +1 -1
  66. package/build-types/components/dataviews/stories/index.story.d.ts +12 -53
  67. package/build-types/components/dataviews/stories/index.story.d.ts.map +1 -1
  68. package/build-types/components/dataviews-bulk-actions/index.d.ts +11 -1
  69. package/build-types/components/dataviews-bulk-actions/index.d.ts.map +1 -1
  70. package/build-types/components/dataviews-filters/add-filter.d.ts.map +1 -1
  71. package/build-types/components/dataviews-filters/search-widget.d.ts.map +1 -1
  72. package/build-types/components/dataviews-footer/index.d.ts +2 -0
  73. package/build-types/components/dataviews-footer/index.d.ts.map +1 -0
  74. package/build-types/components/dataviews-item-actions/index.d.ts.map +1 -1
  75. package/build-types/components/dataviews-view-config/index.d.ts.map +1 -1
  76. package/build-types/dataforms-layouts/panel/index.d.ts.map +1 -1
  77. package/build-types/dataviews-layouts/index.d.ts +4 -2
  78. package/build-types/dataviews-layouts/index.d.ts.map +1 -1
  79. package/build-types/dataviews-layouts/list/index.d.ts.map +1 -1
  80. package/build-types/dataviews-layouts/table/column-header-menu.d.ts.map +1 -1
  81. package/build-types/dataviews-layouts/table/index.d.ts.map +1 -1
  82. package/build-types/normalize-fields.d.ts.map +1 -1
  83. package/build-types/types.d.ts +2 -0
  84. package/build-types/types.d.ts.map +1 -1
  85. package/package.json +11 -11
  86. package/src/components/dataviews/index.tsx +2 -6
  87. package/src/components/dataviews/stories/fixtures.tsx +690 -0
  88. package/src/components/dataviews/stories/index.story.tsx +164 -0
  89. package/src/components/dataviews/style.scss +2 -0
  90. package/src/components/dataviews-bulk-actions/index.tsx +264 -213
  91. package/src/components/dataviews-bulk-actions/style.scss +9 -4
  92. package/src/components/dataviews-filters/add-filter.tsx +7 -11
  93. package/src/components/dataviews-filters/search-widget.tsx +45 -17
  94. package/src/components/dataviews-filters/style.scss +12 -2
  95. package/src/components/dataviews-footer/index.tsx +50 -0
  96. package/src/components/dataviews-footer/style.scss +40 -0
  97. package/src/components/dataviews-item-actions/index.tsx +8 -14
  98. package/src/components/dataviews-pagination/index.tsx +5 -5
  99. package/src/components/dataviews-pagination/style.scss +0 -19
  100. package/src/components/dataviews-view-config/index.tsx +252 -53
  101. package/src/components/dataviews-view-config/style.scss +25 -0
  102. package/src/dataforms-layouts/panel/index.tsx +2 -0
  103. package/src/dataviews-layouts/grid/style.scss +1 -1
  104. package/src/dataviews-layouts/index.ts +63 -2
  105. package/src/dataviews-layouts/list/index.tsx +199 -127
  106. package/src/dataviews-layouts/list/style.scss +10 -4
  107. package/src/dataviews-layouts/table/column-header-menu.tsx +85 -87
  108. package/src/dataviews-layouts/table/index.tsx +8 -65
  109. package/src/dataviews-layouts/table/style.scss +0 -5
  110. package/src/normalize-fields.ts +2 -0
  111. package/src/style.scss +1 -1
  112. package/src/types.ts +2 -0
  113. package/tsconfig.tsbuildinfo +1 -1
  114. package/build/components/dataviews-bulk-actions-toolbar/index.js +0 -207
  115. package/build/components/dataviews-bulk-actions-toolbar/index.js.map +0 -1
  116. package/build-module/components/dataviews-bulk-actions-toolbar/index.js +0 -201
  117. package/build-module/components/dataviews-bulk-actions-toolbar/index.js.map +0 -1
  118. package/build-types/components/dataviews-bulk-actions-toolbar/index.d.ts +0 -2
  119. package/build-types/components/dataviews-bulk-actions-toolbar/index.d.ts.map +0 -1
  120. package/src/components/dataviews/stories/fixtures.js +0 -250
  121. package/src/components/dataviews/stories/index.story.js +0 -71
  122. package/src/components/dataviews-bulk-actions-toolbar/index.tsx +0 -288
  123. package/src/components/dataviews-bulk-actions-toolbar/style.scss +0 -45
@@ -2,47 +2,23 @@
2
2
  * WordPress dependencies
3
3
  */
4
4
  import {
5
- privateApis as componentsPrivateApis,
6
5
  Button,
7
- Modal,
6
+ CheckboxControl,
7
+ __experimentalHStack as HStack,
8
8
  } from '@wordpress/components';
9
9
  import { __, sprintf, _n } from '@wordpress/i18n';
10
- import { useMemo, useState, useCallback, useContext } from '@wordpress/element';
10
+ import { useMemo, useState, useRef, useContext } from '@wordpress/element';
11
11
  import { useRegistry } from '@wordpress/data';
12
+ import { closeSmall } from '@wordpress/icons';
12
13
 
13
14
  /**
14
15
  * Internal dependencies
15
16
  */
16
17
  import DataViewsContext from '../dataviews-context';
17
- import { LAYOUT_TABLE, LAYOUT_GRID } from '../../constants';
18
- import { unlock } from '../../lock-unlock';
19
- import type { Action, ActionModal } from '../../types';
20
-
21
- const {
22
- DropdownMenuV2: DropdownMenu,
23
- DropdownMenuGroupV2: DropdownMenuGroup,
24
- DropdownMenuItemV2: DropdownMenuItem,
25
- DropdownMenuSeparatorV2: DropdownMenuSeparator,
26
- } = unlock( componentsPrivateApis );
27
-
28
- interface ActionWithModalProps< Item > {
29
- action: ActionModal< Item >;
30
- selectedItems: Item[];
31
- setActionWithModal: ( action?: ActionModal< Item > ) => void;
32
- onMenuOpenChange: ( isOpen: boolean ) => void;
33
- }
34
-
35
- interface BulkActionsItemProps< Item > {
36
- action: Action< Item >;
37
- selectedItems: Item[];
38
- setActionWithModal: ( action?: ActionModal< Item > ) => void;
39
- }
40
-
41
- interface ActionsMenuGroupProps< Item > {
42
- actions: Action< Item >[];
43
- selectedItems: Item[];
44
- setActionWithModal: ( action?: ActionModal< Item > ) => void;
45
- }
18
+ import { ActionWithModal } from '../dataviews-item-actions';
19
+ import type { Action } from '../../types';
20
+ import type { SetSelection } from '../../private-types';
21
+ import type { ActionTriggerProps } from '../dataviews-item-actions';
46
22
 
47
23
  export function useHasAPossibleBulkAction< Item >(
48
24
  actions: Action< Item >[],
@@ -74,126 +50,231 @@ export function useSomeItemHasAPossibleBulkAction< Item >(
74
50
  }, [ actions, data ] );
75
51
  }
76
52
 
77
- function ActionWithModal< Item >( {
78
- action,
79
- selectedItems,
80
- setActionWithModal,
81
- onMenuOpenChange,
82
- }: ActionWithModalProps< Item > ) {
83
- const eligibleItems = useMemo( () => {
84
- return selectedItems.filter(
85
- ( item ) => ! action.isEligible || action.isEligible( item )
86
- );
87
- }, [ action, selectedItems ] );
88
- const { RenderModal, hideModalHeader } = action;
89
- const onCloseModal = useCallback( () => {
90
- setActionWithModal( undefined );
91
- }, [ setActionWithModal ] );
53
+ interface BulkSelectionCheckboxProps< Item > {
54
+ selection: string[];
55
+ onChangeSelection: SetSelection;
56
+ data: Item[];
57
+ actions: Action< Item >[];
58
+ getItemId: ( item: Item ) => string;
59
+ }
92
60
 
93
- if ( ! eligibleItems.length ) {
94
- return null;
95
- }
61
+ export function BulkSelectionCheckbox< Item >( {
62
+ selection,
63
+ onChangeSelection,
64
+ data,
65
+ actions,
66
+ getItemId,
67
+ }: BulkSelectionCheckboxProps< Item > ) {
68
+ const selectableItems = useMemo( () => {
69
+ return data.filter( ( item ) => {
70
+ return actions.some(
71
+ ( action ) =>
72
+ action.supportsBulk &&
73
+ ( ! action.isEligible || action.isEligible( item ) )
74
+ );
75
+ } );
76
+ }, [ data, actions ] );
77
+ const selectedItems = data.filter(
78
+ ( item ) =>
79
+ selection.includes( getItemId( item ) ) &&
80
+ selectableItems.includes( item )
81
+ );
82
+ const areAllSelected = selectedItems.length === selectableItems.length;
83
+ return (
84
+ <CheckboxControl
85
+ className="dataviews-view-table-selection-checkbox"
86
+ __nextHasNoMarginBottom
87
+ checked={ areAllSelected }
88
+ indeterminate={ ! areAllSelected && !! selectedItems.length }
89
+ onChange={ () => {
90
+ if ( areAllSelected ) {
91
+ onChangeSelection( [] );
92
+ } else {
93
+ onChangeSelection(
94
+ selectableItems.map( ( item ) => getItemId( item ) )
95
+ );
96
+ }
97
+ } }
98
+ aria-label={
99
+ areAllSelected ? __( 'Deselect all' ) : __( 'Select all' )
100
+ }
101
+ />
102
+ );
103
+ }
104
+
105
+ interface ActionButtonProps< Item > {
106
+ action: Action< Item >;
107
+ selectedItems: Item[];
108
+ actionInProgress: string | null;
109
+ setActionInProgress: ( actionId: string | null ) => void;
110
+ }
111
+
112
+ interface ToolbarContentProps< Item > {
113
+ selection: string[];
114
+ onChangeSelection: SetSelection;
115
+ data: Item[];
116
+ actions: Action< Item >[];
117
+ getItemId: ( item: Item ) => string;
118
+ }
96
119
 
120
+ function ActionTrigger< Item >( {
121
+ action,
122
+ onClick,
123
+ isBusy,
124
+ items,
125
+ }: ActionTriggerProps< Item > ) {
97
126
  const label =
98
- typeof action.label === 'string'
99
- ? action.label
100
- : action.label( selectedItems );
127
+ typeof action.label === 'string' ? action.label : action.label( items );
101
128
  return (
102
- <Modal
103
- title={ ! hideModalHeader ? label : undefined }
104
- __experimentalHideHeader={ !! hideModalHeader }
105
- onRequestClose={ onCloseModal }
106
- overlayClassName="dataviews-bulk-actions__modal"
107
- >
108
- <RenderModal
109
- items={ eligibleItems }
110
- closeModal={ onCloseModal }
111
- onActionPerformed={ () => onMenuOpenChange( false ) }
112
- />
113
- </Modal>
129
+ <Button
130
+ disabled={ isBusy }
131
+ accessibleWhenDisabled
132
+ label={ label }
133
+ icon={ action.icon }
134
+ isDestructive={ action.isDestructive }
135
+ size="compact"
136
+ onClick={ onClick }
137
+ isBusy={ isBusy }
138
+ tooltipPosition="top"
139
+ />
114
140
  );
115
141
  }
116
142
 
117
- function BulkActionItem< Item >( {
143
+ const EMPTY_ARRAY: [] = [];
144
+
145
+ function ActionButton< Item >( {
118
146
  action,
119
147
  selectedItems,
120
- setActionWithModal,
121
- }: BulkActionsItemProps< Item > ) {
148
+ actionInProgress,
149
+ setActionInProgress,
150
+ }: ActionButtonProps< Item > ) {
122
151
  const registry = useRegistry();
123
- const eligibleItems = useMemo( () => {
124
- return selectedItems.filter(
125
- ( item ) => ! action.isEligible || action.isEligible( item )
126
- );
152
+ const selectedEligibleItems = useMemo( () => {
153
+ return selectedItems.filter( ( item ) => {
154
+ return ! action.isEligible || action.isEligible( item );
155
+ } );
127
156
  }, [ action, selectedItems ] );
128
-
129
- const shouldShowModal = 'RenderModal' in action;
130
-
157
+ if ( 'RenderModal' in action ) {
158
+ return (
159
+ <ActionWithModal
160
+ key={ action.id }
161
+ action={ action }
162
+ items={ selectedEligibleItems }
163
+ ActionTrigger={ ActionTrigger }
164
+ />
165
+ );
166
+ }
131
167
  return (
132
- <DropdownMenuItem
168
+ <ActionTrigger
133
169
  key={ action.id }
134
- hideOnClick={ ! shouldShowModal }
170
+ action={ action }
135
171
  onClick={ async () => {
136
- if ( shouldShowModal ) {
137
- setActionWithModal( action );
138
- } else {
139
- action.callback( eligibleItems, { registry } );
140
- }
172
+ setActionInProgress( action.id );
173
+ await action.callback( selectedItems, {
174
+ registry,
175
+ } );
176
+ setActionInProgress( null );
141
177
  } }
142
- suffix={ eligibleItems.length }
143
- >
144
- { action.label }
145
- </DropdownMenuItem>
178
+ items={ selectedEligibleItems }
179
+ isBusy={ actionInProgress === action.id }
180
+ />
146
181
  );
147
182
  }
148
183
 
149
- function ActionsMenuGroup< Item >( {
150
- actions,
151
- selectedItems,
152
- setActionWithModal,
153
- }: ActionsMenuGroupProps< Item > ) {
154
- const elligibleActions = useMemo( () => {
155
- return actions.filter( ( action ) => {
156
- return selectedItems.some(
157
- ( item ) => ! action.isEligible || action.isEligible( item )
158
- );
159
- } );
160
- }, [ actions, selectedItems ] );
161
- if ( ! elligibleActions.length ) {
162
- return null;
163
- }
184
+ function renderFooterContent< Item >(
185
+ data: Item[],
186
+ actions: Action< Item >[],
187
+ getItemId: ( item: Item ) => string,
188
+ selection: string[],
189
+ actionsToShow: Action< Item >[],
190
+ selectedItems: Item[],
191
+ actionInProgress: string | null,
192
+ setActionInProgress: ( actionId: string | null ) => void,
193
+ onChangeSelection: SetSelection
194
+ ) {
195
+ const message =
196
+ selectedItems.length > 0
197
+ ? sprintf(
198
+ /* translators: %d: number of items. */
199
+ _n(
200
+ '%d Item selected',
201
+ '%d Items selected',
202
+ selectedItems.length
203
+ ),
204
+ selectedItems.length
205
+ )
206
+ : sprintf(
207
+ /* translators: %d: number of items. */
208
+ _n( '%d Item', '%d Items', data.length ),
209
+ data.length
210
+ );
164
211
  return (
165
- <>
166
- <DropdownMenuGroup>
167
- { elligibleActions.map( ( action ) => (
168
- <BulkActionItem
169
- key={ action.id }
170
- action={ action }
171
- selectedItems={ selectedItems }
172
- setActionWithModal={ setActionWithModal }
212
+ <HStack
213
+ expanded={ false }
214
+ className="dataviews-bulk-actions-footer__container"
215
+ spacing={ 3 }
216
+ >
217
+ <BulkSelectionCheckbox
218
+ selection={ selection }
219
+ onChangeSelection={ onChangeSelection }
220
+ data={ data }
221
+ actions={ actions }
222
+ getItemId={ getItemId }
223
+ />
224
+ <span className="dataviews-bulk-actions-footer__item-count">
225
+ { message }
226
+ </span>
227
+ <HStack
228
+ className="dataviews-bulk-actions-footer__action-buttons"
229
+ expanded={ false }
230
+ spacing={ 1 }
231
+ >
232
+ { actionsToShow.map( ( action ) => {
233
+ return (
234
+ <ActionButton
235
+ key={ action.id }
236
+ action={ action }
237
+ selectedItems={ selectedItems }
238
+ actionInProgress={ actionInProgress }
239
+ setActionInProgress={ setActionInProgress }
240
+ />
241
+ );
242
+ } ) }
243
+ { selectedItems.length > 0 && (
244
+ <Button
245
+ icon={ closeSmall }
246
+ showTooltip
247
+ tooltipPosition="top"
248
+ size="compact"
249
+ label={ __( 'Cancel' ) }
250
+ disabled={ !! actionInProgress }
251
+ accessibleWhenDisabled={ false }
252
+ onClick={ () => {
253
+ onChangeSelection( EMPTY_ARRAY );
254
+ } }
173
255
  />
174
- ) ) }
175
- </DropdownMenuGroup>
176
- <DropdownMenuSeparator />
177
- </>
256
+ ) }
257
+ </HStack>
258
+ </HStack>
178
259
  );
179
260
  }
180
261
 
181
- function _BulkActions() {
182
- const {
183
- data,
184
- actions = [],
185
- selection,
186
- onChangeSelection,
187
- getItemId,
188
- } = useContext( DataViewsContext );
262
+ function FooterContent< Item >( {
263
+ selection,
264
+ actions,
265
+ onChangeSelection,
266
+ data,
267
+ getItemId,
268
+ }: ToolbarContentProps< Item > ) {
269
+ const [ actionInProgress, setActionInProgress ] = useState< string | null >(
270
+ null
271
+ );
272
+ const footerContent = useRef< JSX.Element | null >( null );
273
+
189
274
  const bulkActions = useMemo(
190
275
  () => actions.filter( ( action ) => action.supportsBulk ),
191
276
  [ actions ]
192
277
  );
193
- const [ isMenuOpen, onMenuOpenChange ] = useState( false );
194
- const [ actionWithModal, setActionWithModal ] = useState<
195
- ActionModal< any > | undefined
196
- >();
197
278
  const selectableItems = useMemo( () => {
198
279
  return data.filter( ( item ) => {
199
280
  return bulkActions.some(
@@ -202,8 +283,6 @@ function _BulkActions() {
202
283
  } );
203
284
  }, [ data, bulkActions ] );
204
285
 
205
- const numberSelectableItems = selectableItems.length;
206
-
207
286
  const selectedItems = useMemo( () => {
208
287
  return data.filter(
209
288
  ( item ) =>
@@ -212,94 +291,66 @@ function _BulkActions() {
212
291
  );
213
292
  }, [ selection, data, getItemId, selectableItems ] );
214
293
 
215
- const areAllSelected = selectedItems.length === numberSelectableItems;
216
-
217
- if ( bulkActions.length === 0 ) {
218
- return null;
219
- }
220
- return (
221
- <>
222
- <DropdownMenu
223
- open={ isMenuOpen }
224
- onOpenChange={ onMenuOpenChange }
225
- label={ __( 'Bulk actions' ) }
226
- style={ { minWidth: '240px' } }
227
- trigger={
228
- <Button
229
- className="dataviews-bulk-actions__edit-button"
230
- __next40pxDefaultSize
231
- variant="tertiary"
232
- size="compact"
233
- >
234
- { selectedItems.length
235
- ? sprintf(
236
- /* translators: %d: Number of items. */
237
- _n(
238
- 'Edit %d item',
239
- 'Edit %d items',
240
- selectedItems.length
241
- ),
242
- selectedItems.length
243
- )
244
- : __( 'Bulk edit' ) }
245
- </Button>
246
- }
247
- >
248
- <ActionsMenuGroup
249
- actions={ bulkActions }
250
- setActionWithModal={ setActionWithModal }
251
- selectedItems={ selectedItems }
252
- />
253
- <DropdownMenuGroup>
254
- <DropdownMenuItem
255
- disabled={ areAllSelected }
256
- hideOnClick={ false }
257
- onClick={ () => {
258
- onChangeSelection(
259
- selectableItems.map( ( item ) =>
260
- getItemId( item )
261
- )
262
- );
263
- } }
264
- suffix={ numberSelectableItems }
265
- >
266
- { __( 'Select all' ) }
267
- </DropdownMenuItem>
268
- <DropdownMenuItem
269
- disabled={ selection.length === 0 }
270
- hideOnClick={ false }
271
- onClick={ () => {
272
- onChangeSelection( [] );
273
- } }
274
- >
275
- { __( 'Deselect' ) }
276
- </DropdownMenuItem>
277
- </DropdownMenuGroup>
278
- </DropdownMenu>
279
- { actionWithModal && (
280
- <ActionWithModal
281
- action={ actionWithModal }
282
- selectedItems={ selectedItems }
283
- setActionWithModal={ setActionWithModal }
284
- onMenuOpenChange={ onMenuOpenChange }
285
- />
286
- ) }
287
- </>
294
+ const actionsToShow = useMemo(
295
+ () =>
296
+ actions.filter( ( action ) => {
297
+ return (
298
+ action.supportsBulk &&
299
+ action.icon &&
300
+ selectedItems.some(
301
+ ( item ) =>
302
+ ! action.isEligible || action.isEligible( item )
303
+ )
304
+ );
305
+ } ),
306
+ [ actions, selectedItems ]
288
307
  );
308
+ if ( ! actionInProgress ) {
309
+ if ( footerContent.current ) {
310
+ footerContent.current = null;
311
+ }
312
+ return renderFooterContent(
313
+ data,
314
+ actions,
315
+ getItemId,
316
+ selection,
317
+ actionsToShow,
318
+ selectedItems,
319
+ actionInProgress,
320
+ setActionInProgress,
321
+ onChangeSelection
322
+ );
323
+ } else if ( ! footerContent.current ) {
324
+ footerContent.current = renderFooterContent(
325
+ data,
326
+ actions,
327
+ getItemId,
328
+ selection,
329
+ actionsToShow,
330
+ selectedItems,
331
+ actionInProgress,
332
+ setActionInProgress,
333
+ onChangeSelection
334
+ );
335
+ }
336
+ return footerContent.current;
289
337
  }
290
338
 
291
- export default function BulkActions() {
292
- const { data, actions = [], view } = useContext( DataViewsContext );
293
- const hasPossibleBulkAction = useSomeItemHasAPossibleBulkAction(
294
- actions,
295
- data
339
+ export function BulkActionsFooter() {
340
+ const {
341
+ data,
342
+ selection,
343
+ actions = EMPTY_ARRAY,
344
+ onChangeSelection,
345
+ getItemId,
346
+ } = useContext( DataViewsContext );
347
+ return (
348
+ <FooterContent
349
+ selection={ selection }
350
+ onChangeSelection={ onChangeSelection }
351
+ data={ data }
352
+ actions={ actions }
353
+ getItemId={ getItemId }
354
+ />
296
355
  );
297
- if (
298
- ! [ LAYOUT_TABLE, LAYOUT_GRID ].includes( view.type ) ||
299
- ! hasPossibleBulkAction
300
- ) {
301
- return null;
302
- }
303
-
304
- return <_BulkActions />;
305
356
  }
@@ -1,7 +1,12 @@
1
- .dataviews-bulk-actions__modal {
2
- z-index: z-index(".dataviews-bulk-actions__modal");
1
+
2
+ .dataviews-bulk-actions-footer__item-count {
3
+ color: $gray-900;
4
+ font-weight: 500;
5
+ font-size: 11px;
6
+ text-transform: uppercase;
3
7
  }
4
8
 
5
- .dataviews-bulk-actions__edit-button.components-button {
6
- flex-shrink: 0;
9
+ .dataviews-bulk-actions-footer__container {
10
+ margin-right: auto;
11
+ min-height: $grid-unit-40;
7
12
  }
@@ -19,11 +19,7 @@ import { forwardRef } from '@wordpress/element';
19
19
  import { unlock } from '../../lock-unlock';
20
20
  import type { NormalizedFilter, View } from '../../types';
21
21
 
22
- const {
23
- DropdownMenuV2: DropdownMenu,
24
- DropdownMenuItemV2: DropdownMenuItem,
25
- DropdownMenuItemLabelV2: DropdownMenuItemLabel,
26
- } = unlock( componentsPrivateApis );
22
+ const { DropdownMenuV2 } = unlock( componentsPrivateApis );
27
23
 
28
24
  interface AddFilterProps {
29
25
  filters: NormalizedFilter[];
@@ -43,10 +39,10 @@ export function AddFilterDropdownMenu( {
43
39
  } ) {
44
40
  const inactiveFilters = filters.filter( ( filter ) => ! filter.isVisible );
45
41
  return (
46
- <DropdownMenu trigger={ trigger }>
42
+ <DropdownMenuV2 trigger={ trigger }>
47
43
  { inactiveFilters.map( ( filter ) => {
48
44
  return (
49
- <DropdownMenuItem
45
+ <DropdownMenuV2.Item
50
46
  key={ filter.field }
51
47
  onClick={ () => {
52
48
  setOpenedFilter( filter.field );
@@ -64,13 +60,13 @@ export function AddFilterDropdownMenu( {
64
60
  } );
65
61
  } }
66
62
  >
67
- <DropdownMenuItemLabel>
63
+ <DropdownMenuV2.ItemLabel>
68
64
  { filter.name }
69
- </DropdownMenuItemLabel>
70
- </DropdownMenuItem>
65
+ </DropdownMenuV2.ItemLabel>
66
+ </DropdownMenuV2.Item>
71
67
  );
72
68
  } ) }
73
- </DropdownMenu>
69
+ </DropdownMenuV2>
74
70
  );
75
71
  }
76
72