@wordpress/dataviews 2.1.0 → 3.0.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 (159) hide show
  1. package/CHANGELOG.md +24 -5
  2. package/README.md +5 -5
  3. package/build/add-filter.js +1 -1
  4. package/build/add-filter.js.map +1 -1
  5. package/build/bulk-actions-toolbar.js +5 -2
  6. package/build/bulk-actions-toolbar.js.map +1 -1
  7. package/build/bulk-actions.js +11 -21
  8. package/build/bulk-actions.js.map +1 -1
  9. package/build/dataform.js +78 -0
  10. package/build/dataform.js.map +1 -0
  11. package/build/dataviews.js +26 -31
  12. package/build/dataviews.js.map +1 -1
  13. package/build/filter-and-sort-data-view.js +4 -1
  14. package/build/filter-and-sort-data-view.js.map +1 -1
  15. package/build/filter-summary.js +6 -5
  16. package/build/filter-summary.js.map +1 -1
  17. package/build/filters.js +1 -1
  18. package/build/filters.js.map +1 -1
  19. package/build/index.js +7 -0
  20. package/build/index.js.map +1 -1
  21. package/build/item-actions.js +17 -6
  22. package/build/item-actions.js.map +1 -1
  23. package/build/lock-unlock.js +1 -1
  24. package/build/lock-unlock.js.map +1 -1
  25. package/build/normalize-fields.js.map +1 -1
  26. package/build/pagination.js +2 -2
  27. package/build/pagination.js.map +1 -1
  28. package/build/private-types.js +6 -0
  29. package/build/private-types.js.map +1 -0
  30. package/build/reset-filters.js +1 -1
  31. package/build/reset-filters.js.map +1 -1
  32. package/build/search-widget.js +8 -6
  33. package/build/search-widget.js.map +1 -1
  34. package/build/single-selection-checkbox.js +5 -16
  35. package/build/single-selection-checkbox.js.map +1 -1
  36. package/build/types.js.map +1 -1
  37. package/build/utils.js.map +1 -1
  38. package/build/view-actions.js +76 -65
  39. package/build/view-actions.js.map +1 -1
  40. package/build/view-grid.js +7 -19
  41. package/build/view-grid.js.map +1 -1
  42. package/build/view-list.js +15 -8
  43. package/build/view-list.js.map +1 -1
  44. package/build/view-table.js +22 -25
  45. package/build/view-table.js.map +1 -1
  46. package/build-module/add-filter.js +1 -1
  47. package/build-module/add-filter.js.map +1 -1
  48. package/build-module/bulk-actions-toolbar.js +5 -2
  49. package/build-module/bulk-actions-toolbar.js.map +1 -1
  50. package/build-module/bulk-actions.js +12 -22
  51. package/build-module/bulk-actions.js.map +1 -1
  52. package/build-module/dataform.js +72 -0
  53. package/build-module/dataform.js.map +1 -0
  54. package/build-module/dataviews.js +24 -31
  55. package/build-module/dataviews.js.map +1 -1
  56. package/build-module/filter-and-sort-data-view.js +4 -1
  57. package/build-module/filter-and-sort-data-view.js.map +1 -1
  58. package/build-module/filter-summary.js +6 -5
  59. package/build-module/filter-summary.js.map +1 -1
  60. package/build-module/filters.js +1 -1
  61. package/build-module/filters.js.map +1 -1
  62. package/build-module/index.js +1 -0
  63. package/build-module/index.js.map +1 -1
  64. package/build-module/item-actions.js +17 -6
  65. package/build-module/item-actions.js.map +1 -1
  66. package/build-module/lock-unlock.js +1 -1
  67. package/build-module/lock-unlock.js.map +1 -1
  68. package/build-module/normalize-fields.js.map +1 -1
  69. package/build-module/pagination.js +2 -2
  70. package/build-module/pagination.js.map +1 -1
  71. package/build-module/private-types.js +2 -0
  72. package/build-module/private-types.js.map +1 -0
  73. package/build-module/reset-filters.js +1 -1
  74. package/build-module/reset-filters.js.map +1 -1
  75. package/build-module/search-widget.js +8 -6
  76. package/build-module/search-widget.js.map +1 -1
  77. package/build-module/single-selection-checkbox.js +5 -16
  78. package/build-module/single-selection-checkbox.js.map +1 -1
  79. package/build-module/types.js.map +1 -1
  80. package/build-module/utils.js.map +1 -1
  81. package/build-module/view-actions.js +80 -68
  82. package/build-module/view-actions.js.map +1 -1
  83. package/build-module/view-grid.js +7 -19
  84. package/build-module/view-grid.js.map +1 -1
  85. package/build-module/view-list.js +15 -8
  86. package/build-module/view-list.js.map +1 -1
  87. package/build-module/view-table.js +22 -25
  88. package/build-module/view-table.js.map +1 -1
  89. package/build-style/style-rtl.css +8 -24
  90. package/build-style/style.css +8 -24
  91. package/build-types/bulk-actions-toolbar.d.ts +5 -4
  92. package/build-types/bulk-actions-toolbar.d.ts.map +1 -1
  93. package/build-types/bulk-actions.d.ts +7 -6
  94. package/build-types/bulk-actions.d.ts.map +1 -1
  95. package/build-types/dataform.d.ts +17 -0
  96. package/build-types/dataform.d.ts.map +1 -0
  97. package/build-types/dataviews.d.ts +15 -6
  98. package/build-types/dataviews.d.ts.map +1 -1
  99. package/build-types/filter-and-sort-data-view.d.ts +2 -2
  100. package/build-types/filter-and-sort-data-view.d.ts.map +1 -1
  101. package/build-types/filter-summary.d.ts.map +1 -1
  102. package/build-types/filters.d.ts +3 -3
  103. package/build-types/filters.d.ts.map +1 -1
  104. package/build-types/index.d.ts +1 -0
  105. package/build-types/index.d.ts.map +1 -1
  106. package/build-types/item-actions.d.ts +10 -10
  107. package/build-types/item-actions.d.ts.map +1 -1
  108. package/build-types/normalize-fields.d.ts +2 -2
  109. package/build-types/normalize-fields.d.ts.map +1 -1
  110. package/build-types/private-types.d.ts +3 -0
  111. package/build-types/private-types.d.ts.map +1 -0
  112. package/build-types/single-selection-checkbox.d.ts +5 -5
  113. package/build-types/single-selection-checkbox.d.ts.map +1 -1
  114. package/build-types/stories/fixtures.d.ts +14 -1
  115. package/build-types/stories/fixtures.d.ts.map +1 -1
  116. package/build-types/stories/index.story.d.ts +15 -1
  117. package/build-types/stories/index.story.d.ts.map +1 -1
  118. package/build-types/types.d.ts +73 -38
  119. package/build-types/types.d.ts.map +1 -1
  120. package/build-types/utils.d.ts +2 -2
  121. package/build-types/utils.d.ts.map +1 -1
  122. package/build-types/view-actions.d.ts +4 -4
  123. package/build-types/view-actions.d.ts.map +1 -1
  124. package/build-types/view-grid.d.ts +2 -2
  125. package/build-types/view-grid.d.ts.map +1 -1
  126. package/build-types/view-list.d.ts +2 -2
  127. package/build-types/view-list.d.ts.map +1 -1
  128. package/build-types/view-table.d.ts +2 -2
  129. package/build-types/view-table.d.ts.map +1 -1
  130. package/package.json +10 -9
  131. package/src/add-filter.tsx +1 -1
  132. package/src/bulk-actions-toolbar.tsx +18 -14
  133. package/src/bulk-actions.tsx +31 -45
  134. package/src/dataform.tsx +106 -0
  135. package/src/dataviews.tsx +55 -60
  136. package/src/filter-and-sort-data-view.ts +13 -3
  137. package/src/filter-summary.tsx +18 -12
  138. package/src/filters.tsx +4 -4
  139. package/src/index.ts +1 -0
  140. package/src/item-actions.tsx +27 -24
  141. package/src/lock-unlock.ts +1 -1
  142. package/src/normalize-fields.ts +5 -3
  143. package/src/pagination.tsx +2 -2
  144. package/src/private-types.tsx +2 -0
  145. package/src/reset-filters.tsx +1 -1
  146. package/src/search-widget.tsx +6 -6
  147. package/src/single-selection-checkbox.tsx +14 -29
  148. package/src/stories/fixtures.js +17 -1
  149. package/src/stories/index.story.js +15 -28
  150. package/src/style.scss +10 -22
  151. package/src/test/filter-and-sort-data-view.js +16 -1
  152. package/src/types.ts +75 -47
  153. package/src/utils.ts +2 -4
  154. package/src/view-actions.tsx +105 -102
  155. package/src/view-grid.tsx +21 -38
  156. package/src/view-list.tsx +22 -22
  157. package/src/view-table.tsx +45 -45
  158. package/tsconfig.json +1 -0
  159. package/tsconfig.tsbuildinfo +1 -1
package/src/view-list.tsx CHANGED
@@ -27,16 +27,17 @@ import {
27
27
  } from '@wordpress/element';
28
28
  import { __ } from '@wordpress/i18n';
29
29
  import { moreVertical } from '@wordpress/icons';
30
+ import { useRegistry } from '@wordpress/data';
30
31
 
31
32
  /**
32
33
  * Internal dependencies
33
34
  */
34
35
  import { unlock } from './lock-unlock';
35
- import type { Action, AnyItem, NormalizedField, ViewListProps } from './types';
36
+ import type { Action, NormalizedField, ViewListProps } from './types';
36
37
 
37
38
  import { ActionsDropdownMenuGroup, ActionModal } from './item-actions';
38
39
 
39
- interface ListViewItemProps< Item extends AnyItem > {
40
+ interface ListViewItemProps< Item > {
40
41
  actions: Action< Item >[];
41
42
  id?: string;
42
43
  isSelected: boolean;
@@ -56,7 +57,7 @@ const {
56
57
  DropdownMenuV2: DropdownMenu,
57
58
  } = unlock( componentsPrivateApis );
58
59
 
59
- function ListItem< Item extends AnyItem >( {
60
+ function ListItem< Item >( {
60
61
  actions,
61
62
  id,
62
63
  isSelected,
@@ -67,6 +68,7 @@ function ListItem< Item extends AnyItem >( {
67
68
  store,
68
69
  visibleFields,
69
70
  }: ListViewItemProps< Item > ) {
71
+ const registry = useRegistry();
70
72
  const itemRef = useRef< HTMLElement >( null );
71
73
  const labelId = `${ id }-label`;
72
74
  const descriptionId = `${ id }-description`;
@@ -182,7 +184,7 @@ function ListItem< Item extends AnyItem >( {
182
184
  </HStack>
183
185
  </CompositeItem>
184
186
  </div>
185
- { actions?.length > 0 && (
187
+ { eligibleActions?.length > 0 && (
186
188
  <HStack
187
189
  spacing={ 1 }
188
190
  justify="flex-end"
@@ -235,11 +237,12 @@ function ListItem< Item extends AnyItem >( {
235
237
  primaryAction.isDestructive
236
238
  }
237
239
  size="compact"
238
- onClick={ () =>
239
- primaryAction.callback( [
240
- item,
241
- ] )
242
- }
240
+ onClick={ () => {
241
+ primaryAction.callback(
242
+ [ item ],
243
+ { registry }
244
+ );
245
+ } }
243
246
  />
244
247
  }
245
248
  />
@@ -255,7 +258,7 @@ function ListItem< Item extends AnyItem >( {
255
258
  size="compact"
256
259
  icon={ moreVertical }
257
260
  label={ __( 'Actions' ) }
258
- __experimentalIsFocusable
261
+ accessibleWhenDisabled
259
262
  disabled={ ! actions.length }
260
263
  onKeyDown={ ( event: {
261
264
  key: string;
@@ -300,9 +303,7 @@ function ListItem< Item extends AnyItem >( {
300
303
  );
301
304
  }
302
305
 
303
- export default function ViewList< Item extends AnyItem >(
304
- props: ViewListProps< Item >
305
- ) {
306
+ export default function ViewList< Item >( props: ViewListProps< Item > ) {
306
307
  const {
307
308
  actions,
308
309
  data,
@@ -315,27 +316,26 @@ export default function ViewList< Item extends AnyItem >(
315
316
  } = props;
316
317
  const baseId = useInstanceId( ViewList, 'view-list' );
317
318
  const selectedItem = data?.findLast( ( item ) =>
318
- selection.includes( item.id )
319
+ selection.includes( getItemId( item ) )
319
320
  );
320
321
 
321
322
  const mediaField = fields.find(
322
- ( field ) => field.id === view.layout.mediaField
323
+ ( field ) => field.id === view.layout?.mediaField
323
324
  );
324
325
  const primaryField = fields.find(
325
- ( field ) => field.id === view.layout.primaryField
326
+ ( field ) => field.id === view.layout?.primaryField
326
327
  );
328
+ const viewFields = view.fields || fields.map( ( field ) => field.id );
327
329
  const visibleFields = fields.filter(
328
330
  ( field ) =>
329
- ! view.hiddenFields.includes( field.id ) &&
330
- ! [ view.layout.primaryField, view.layout.mediaField ].includes(
331
+ viewFields.includes( field.id ) &&
332
+ ! [ view.layout?.primaryField, view.layout?.mediaField ].includes(
331
333
  field.id
332
334
  )
333
335
  );
334
336
 
335
- const onSelect = useCallback(
336
- ( item: Item ) => onSelectionChange( [ item ] ),
337
- [ onSelectionChange ]
338
- );
337
+ const onSelect = ( item: Item ) =>
338
+ onSelectionChange( [ getItemId( item ) ] );
339
339
 
340
340
  const getItemDomId = useCallback(
341
341
  ( item?: Item ) =>
@@ -46,12 +46,12 @@ import {
46
46
  } from './bulk-actions';
47
47
  import type {
48
48
  Action,
49
- AnyItem,
50
49
  NormalizedField,
51
50
  SortDirection,
52
51
  ViewTable as ViewTableType,
53
52
  ViewTableProps,
54
53
  } from './types';
54
+ import type { SetSelection } from './private-types';
55
55
 
56
56
  const {
57
57
  DropdownMenuV2: DropdownMenu,
@@ -62,22 +62,24 @@ const {
62
62
  DropdownMenuSeparatorV2: DropdownMenuSeparator,
63
63
  } = unlock( componentsPrivateApis );
64
64
 
65
- interface HeaderMenuProps< Item extends AnyItem > {
65
+ interface HeaderMenuProps< Item > {
66
66
  field: NormalizedField< Item >;
67
67
  view: ViewTableType;
68
+ fields: NormalizedField< Item >[];
68
69
  onChangeView: ( view: ViewTableType ) => void;
69
70
  onHide: ( field: NormalizedField< Item > ) => void;
70
71
  setOpenedFilter: ( fieldId: string ) => void;
71
72
  }
72
73
 
73
- interface BulkSelectionCheckboxProps< Item extends AnyItem > {
74
+ interface BulkSelectionCheckboxProps< Item > {
74
75
  selection: string[];
75
- onSelectionChange: ( items: Item[] ) => void;
76
+ onSelectionChange: SetSelection;
76
77
  data: Item[];
77
78
  actions: Action< Item >[];
79
+ getItemId: ( item: Item ) => string;
78
80
  }
79
81
 
80
- interface TableRowProps< Item extends AnyItem > {
82
+ interface TableRowProps< Item > {
81
83
  hasBulkActions: boolean;
82
84
  item: Item;
83
85
  actions: Action< Item >[];
@@ -86,8 +88,7 @@ interface TableRowProps< Item extends AnyItem > {
86
88
  primaryField?: NormalizedField< Item >;
87
89
  selection: string[];
88
90
  getItemId: ( item: Item ) => string;
89
- onSelectionChange: ( items: Item[] ) => void;
90
- data: Item[];
91
+ onSelectionChange: SetSelection;
91
92
  }
92
93
 
93
94
  function WithDropDownMenuSeparators( { children }: { children: ReactNode } ) {
@@ -101,10 +102,11 @@ function WithDropDownMenuSeparators( { children }: { children: ReactNode } ) {
101
102
  ) );
102
103
  }
103
104
 
104
- const _HeaderMenu = forwardRef( function HeaderMenu< Item extends AnyItem >(
105
+ const _HeaderMenu = forwardRef( function HeaderMenu< Item >(
105
106
  {
106
107
  field,
107
108
  view,
109
+ fields,
108
110
  onChangeView,
109
111
  onHide,
110
112
  setOpenedFilter,
@@ -219,11 +221,13 @@ const _HeaderMenu = forwardRef( function HeaderMenu< Item extends AnyItem >(
219
221
  <DropdownMenuItem
220
222
  prefix={ <Icon icon={ unseen } /> }
221
223
  onClick={ () => {
224
+ const viewFields =
225
+ view.fields || fields.map( ( f ) => f.id );
222
226
  onHide( field );
223
227
  onChangeView( {
224
228
  ...view,
225
- hiddenFields: view.hiddenFields.concat(
226
- field.id
229
+ fields: viewFields.filter(
230
+ ( fieldId ) => fieldId !== field.id
227
231
  ),
228
232
  } );
229
233
  } }
@@ -239,16 +243,17 @@ const _HeaderMenu = forwardRef( function HeaderMenu< Item extends AnyItem >(
239
243
  } );
240
244
 
241
245
  // @ts-expect-error Lift the `Item` type argument through the forwardRef.
242
- const HeaderMenu: < Item extends AnyItem >(
246
+ const HeaderMenu: < Item >(
243
247
  props: PropsWithoutRef< HeaderMenuProps< Item > > &
244
248
  RefAttributes< HTMLButtonElement >
245
249
  ) => ReturnType< typeof _HeaderMenu > = _HeaderMenu;
246
250
 
247
- function BulkSelectionCheckbox< Item extends AnyItem >( {
251
+ function BulkSelectionCheckbox< Item >( {
248
252
  selection,
249
253
  onSelectionChange,
250
254
  data,
251
255
  actions,
256
+ getItemId,
252
257
  }: BulkSelectionCheckboxProps< Item > ) {
253
258
  const selectableItems = useMemo( () => {
254
259
  return data.filter( ( item ) => {
@@ -259,18 +264,25 @@ function BulkSelectionCheckbox< Item extends AnyItem >( {
259
264
  );
260
265
  } );
261
266
  }, [ data, actions ] );
262
- const areAllSelected = selection.length === selectableItems.length;
267
+ const selectedItems = data.filter(
268
+ ( item ) =>
269
+ selection.includes( getItemId( item ) ) &&
270
+ selectableItems.includes( item )
271
+ );
272
+ const areAllSelected = selectedItems.length === selectableItems.length;
263
273
  return (
264
274
  <CheckboxControl
265
275
  className="dataviews-view-table-selection-checkbox"
266
276
  __nextHasNoMarginBottom
267
277
  checked={ areAllSelected }
268
- indeterminate={ ! areAllSelected && !! selection.length }
278
+ indeterminate={ ! areAllSelected && !! selectedItems.length }
269
279
  onChange={ () => {
270
280
  if ( areAllSelected ) {
271
281
  onSelectionChange( [] );
272
282
  } else {
273
- onSelectionChange( selectableItems );
283
+ onSelectionChange(
284
+ selectableItems.map( ( item ) => getItemId( item ) )
285
+ );
274
286
  }
275
287
  } }
276
288
  aria-label={
@@ -280,7 +292,7 @@ function BulkSelectionCheckbox< Item extends AnyItem >( {
280
292
  );
281
293
  }
282
294
 
283
- function TableRow< Item extends AnyItem >( {
295
+ function TableRow< Item >( {
284
296
  hasBulkActions,
285
297
  item,
286
298
  actions,
@@ -290,10 +302,9 @@ function TableRow< Item extends AnyItem >( {
290
302
  selection,
291
303
  getItemId,
292
304
  onSelectionChange,
293
- data,
294
305
  }: TableRowProps< Item > ) {
295
306
  const hasPossibleBulkAction = useHasAPossibleBulkAction( actions, item );
296
- const isSelected = selection.includes( id );
307
+ const isSelected = hasPossibleBulkAction && selection.includes( id );
297
308
 
298
309
  const [ isHovered, setIsHovered ] = useState( false );
299
310
 
@@ -323,31 +334,18 @@ function TableRow< Item extends AnyItem >( {
323
334
  isTouchDevice.current = true;
324
335
  } }
325
336
  onClick={ () => {
337
+ if ( ! hasPossibleBulkAction ) {
338
+ return;
339
+ }
326
340
  if (
327
341
  ! isTouchDevice.current &&
328
342
  document.getSelection()?.type !== 'Range'
329
343
  ) {
330
- if ( ! isSelected ) {
331
- onSelectionChange(
332
- data.filter( ( _item ) => {
333
- const itemId = getItemId?.( _item );
334
- return (
335
- itemId === id ||
336
- selection.includes( itemId )
337
- );
338
- } )
339
- );
340
- } else {
341
- onSelectionChange(
342
- data.filter( ( _item ) => {
343
- const itemId = getItemId?.( _item );
344
- return (
345
- itemId !== id &&
346
- selection.includes( itemId )
347
- );
348
- } )
349
- );
350
- }
344
+ onSelectionChange(
345
+ selection.includes( id )
346
+ ? selection.filter( ( itemId ) => id !== itemId )
347
+ : [ ...selection, id ]
348
+ );
351
349
  }
352
350
  } }
353
351
  >
@@ -364,7 +362,6 @@ function TableRow< Item extends AnyItem >( {
364
362
  selection={ selection }
365
363
  onSelectionChange={ onSelectionChange }
366
364
  getItemId={ getItemId }
367
- data={ data }
368
365
  primaryField={ primaryField }
369
366
  disabled={ ! hasPossibleBulkAction }
370
367
  />
@@ -415,7 +412,7 @@ function TableRow< Item extends AnyItem >( {
415
412
  );
416
413
  }
417
414
 
418
- function ViewTable< Item extends AnyItem >( {
415
+ function ViewTable< Item >( {
419
416
  actions,
420
417
  data,
421
418
  fields,
@@ -461,15 +458,17 @@ function ViewTable< Item extends AnyItem >( {
461
458
  : undefined;
462
459
  setNextHeaderMenuToFocus( fallback?.node );
463
460
  };
461
+
462
+ const viewFields = view.fields || fields.map( ( f ) => f.id );
464
463
  const visibleFields = fields.filter(
465
464
  ( field ) =>
466
- ! view.hiddenFields.includes( field.id ) &&
467
- ! [ view.layout.mediaField ].includes( field.id )
465
+ viewFields.includes( field.id ) ||
466
+ [ view.layout?.mediaField ].includes( field.id )
468
467
  );
469
468
  const hasData = !! data?.length;
470
469
 
471
470
  const primaryField = fields.find(
472
- ( field ) => field.id === view.layout.primaryField
471
+ ( field ) => field.id === view.layout?.primaryField
473
472
  );
474
473
 
475
474
  return (
@@ -495,6 +494,7 @@ function ViewTable< Item extends AnyItem >( {
495
494
  onSelectionChange={ onSelectionChange }
496
495
  data={ data }
497
496
  actions={ actions }
497
+ getItemId={ getItemId }
498
498
  />
499
499
  </th>
500
500
  ) }
@@ -537,6 +537,7 @@ function ViewTable< Item extends AnyItem >( {
537
537
  } }
538
538
  field={ field }
539
539
  view={ view }
540
+ fields={ fields }
540
541
  onChangeView={ onChangeView }
541
542
  onHide={ onHide }
542
543
  setOpenedFilter={ setOpenedFilter }
@@ -569,7 +570,6 @@ function ViewTable< Item extends AnyItem >( {
569
570
  selection={ selection }
570
571
  getItemId={ getItemId }
571
572
  onSelectionChange={ onSelectionChange }
572
- data={ data }
573
573
  />
574
574
  ) ) }
575
575
  </tbody>
package/tsconfig.json CHANGED
@@ -9,6 +9,7 @@
9
9
  "references": [
10
10
  { "path": "../components" },
11
11
  { "path": "../compose" },
12
+ { "path": "../data" },
12
13
  { "path": "../element" },
13
14
  { "path": "../i18n" },
14
15
  { "path": "../icons" },