@wordpress/dataviews 1.1.0 → 2.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 (176) hide show
  1. package/CHANGELOG.md +27 -5
  2. package/README.md +33 -30
  3. package/build/add-filter.js +30 -22
  4. package/build/add-filter.js.map +1 -1
  5. package/build/bulk-actions-toolbar.js +187 -0
  6. package/build/bulk-actions-toolbar.js.map +1 -0
  7. package/build/bulk-actions.js +75 -62
  8. package/build/bulk-actions.js.map +1 -1
  9. package/build/constants.js +17 -10
  10. package/build/constants.js.map +1 -1
  11. package/build/dataviews.js +64 -50
  12. package/build/dataviews.js.map +1 -1
  13. package/build/filter-and-sort-data-view.js +2 -2
  14. package/build/filter-and-sort-data-view.js.map +1 -1
  15. package/build/filter-summary.js +106 -96
  16. package/build/filter-summary.js.map +1 -1
  17. package/build/filters.js +18 -17
  18. package/build/filters.js.map +1 -1
  19. package/build/index.js.map +1 -1
  20. package/build/item-actions.js +101 -69
  21. package/build/item-actions.js.map +1 -1
  22. package/build/layouts.js.map +1 -1
  23. package/build/lock-unlock.js.map +1 -1
  24. package/build/normalize-fields.js.map +1 -1
  25. package/build/pagination.js +66 -57
  26. package/build/pagination.js.map +1 -1
  27. package/build/reset-filters.js +9 -4
  28. package/build/reset-filters.js.map +1 -1
  29. package/build/search-widget.js +108 -89
  30. package/build/search-widget.js.map +1 -1
  31. package/build/search.js +13 -6
  32. package/build/search.js.map +1 -1
  33. package/build/single-selection-checkbox.js +6 -2
  34. package/build/single-selection-checkbox.js.map +1 -1
  35. package/build/types.js.map +1 -1
  36. package/build/utils.js +3 -15
  37. package/build/utils.js.map +1 -1
  38. package/build/view-actions.js +168 -120
  39. package/build/view-actions.js.map +1 -1
  40. package/build/view-grid.js +119 -106
  41. package/build/view-grid.js.map +1 -1
  42. package/build/view-list.js +217 -83
  43. package/build/view-list.js.map +1 -1
  44. package/build/view-table.js +227 -199
  45. package/build/view-table.js.map +1 -1
  46. package/build-module/add-filter.js +30 -22
  47. package/build-module/add-filter.js.map +1 -1
  48. package/build-module/bulk-actions-toolbar.js +182 -0
  49. package/build-module/bulk-actions-toolbar.js.map +1 -0
  50. package/build-module/bulk-actions.js +77 -62
  51. package/build-module/bulk-actions.js.map +1 -1
  52. package/build-module/constants.js +16 -9
  53. package/build-module/constants.js.map +1 -1
  54. package/build-module/dataviews.js +65 -50
  55. package/build-module/dataviews.js.map +1 -1
  56. package/build-module/filter-and-sort-data-view.js +2 -2
  57. package/build-module/filter-and-sort-data-view.js.map +1 -1
  58. package/build-module/filter-summary.js +107 -97
  59. package/build-module/filter-summary.js.map +1 -1
  60. package/build-module/filters.js +18 -17
  61. package/build-module/filters.js.map +1 -1
  62. package/build-module/index.js.map +1 -1
  63. package/build-module/item-actions.js +102 -71
  64. package/build-module/item-actions.js.map +1 -1
  65. package/build-module/layouts.js.map +1 -1
  66. package/build-module/lock-unlock.js.map +1 -1
  67. package/build-module/normalize-fields.js.map +1 -1
  68. package/build-module/pagination.js +67 -57
  69. package/build-module/pagination.js.map +1 -1
  70. package/build-module/reset-filters.js +9 -4
  71. package/build-module/reset-filters.js.map +1 -1
  72. package/build-module/search-widget.js +109 -89
  73. package/build-module/search-widget.js.map +1 -1
  74. package/build-module/search.js +13 -6
  75. package/build-module/search.js.map +1 -1
  76. package/build-module/single-selection-checkbox.js +6 -2
  77. package/build-module/single-selection-checkbox.js.map +1 -1
  78. package/build-module/types.js.map +1 -1
  79. package/build-module/utils.js +2 -13
  80. package/build-module/utils.js.map +1 -1
  81. package/build-module/view-actions.js +170 -121
  82. package/build-module/view-actions.js.map +1 -1
  83. package/build-module/view-grid.js +121 -106
  84. package/build-module/view-grid.js.map +1 -1
  85. package/build-module/view-list.js +219 -85
  86. package/build-module/view-list.js.map +1 -1
  87. package/build-module/view-table.js +230 -201
  88. package/build-module/view-table.js.map +1 -1
  89. package/build-style/style-rtl.css +168 -44
  90. package/build-style/style.css +168 -44
  91. package/build-types/add-filter.d.ts +11 -0
  92. package/build-types/add-filter.d.ts.map +1 -0
  93. package/build-types/bulk-actions-toolbar.d.ts +12 -0
  94. package/build-types/bulk-actions-toolbar.d.ts.map +1 -0
  95. package/build-types/bulk-actions.d.ts +14 -0
  96. package/build-types/bulk-actions.d.ts.map +1 -0
  97. package/build-types/constants.d.ts +19 -32
  98. package/build-types/constants.d.ts.map +1 -1
  99. package/build-types/dataviews.d.ts +22 -0
  100. package/build-types/dataviews.d.ts.map +1 -0
  101. package/build-types/filter-and-sort-data-view.d.ts +3 -3
  102. package/build-types/filter-and-sort-data-view.d.ts.map +1 -1
  103. package/build-types/filter-summary.d.ts +14 -0
  104. package/build-types/filter-summary.d.ts.map +1 -0
  105. package/build-types/filters.d.ts +13 -0
  106. package/build-types/filters.d.ts.map +1 -0
  107. package/build-types/index.d.ts +4 -0
  108. package/build-types/index.d.ts.map +1 -0
  109. package/build-types/item-actions.d.ts +35 -0
  110. package/build-types/item-actions.d.ts.map +1 -0
  111. package/build-types/layouts.d.ts +24 -0
  112. package/build-types/layouts.d.ts.map +1 -0
  113. package/build-types/lock-unlock.d.ts +2 -0
  114. package/build-types/lock-unlock.d.ts.map +1 -0
  115. package/build-types/normalize-fields.d.ts +2 -2
  116. package/build-types/normalize-fields.d.ts.map +1 -1
  117. package/build-types/pagination.d.ts +16 -0
  118. package/build-types/pagination.d.ts.map +1 -0
  119. package/build-types/reset-filters.d.ts +13 -0
  120. package/build-types/reset-filters.d.ts.map +1 -0
  121. package/build-types/search-widget.d.ts +10 -0
  122. package/build-types/search-widget.d.ts.map +1 -0
  123. package/build-types/search.d.ts +13 -0
  124. package/build-types/search.d.ts.map +1 -0
  125. package/build-types/single-selection-checkbox.d.ts +17 -0
  126. package/build-types/single-selection-checkbox.d.ts.map +1 -0
  127. package/build-types/stories/fixtures.d.ts +114 -0
  128. package/build-types/stories/fixtures.d.ts.map +1 -0
  129. package/build-types/stories/index.story.d.ts +15 -0
  130. package/build-types/stories/index.story.d.ts.map +1 -0
  131. package/build-types/types.d.ts +221 -21
  132. package/build-types/types.d.ts.map +1 -1
  133. package/build-types/utils.d.ts +3 -0
  134. package/build-types/utils.d.ts.map +1 -0
  135. package/build-types/view-actions.d.ts +12 -0
  136. package/build-types/view-actions.d.ts.map +1 -0
  137. package/build-types/view-grid.d.ts +4 -0
  138. package/build-types/view-grid.d.ts.map +1 -0
  139. package/build-types/view-list.d.ts +4 -0
  140. package/build-types/view-list.d.ts.map +1 -0
  141. package/build-types/view-table.d.ts +5 -0
  142. package/build-types/view-table.d.ts.map +1 -0
  143. package/package.json +12 -13
  144. package/src/{add-filter.js → add-filter.tsx} +17 -1
  145. package/src/bulk-actions-toolbar.tsx +272 -0
  146. package/src/{bulk-actions.js → bulk-actions.tsx} +77 -17
  147. package/src/constants.ts +12 -5
  148. package/src/{dataviews.js → dataviews.tsx} +54 -14
  149. package/src/filter-and-sort-data-view.ts +13 -8
  150. package/src/{filter-summary.js → filter-summary.tsx} +38 -9
  151. package/src/{filters.js → filters.tsx} +18 -6
  152. package/src/{item-actions.js → item-actions.tsx} +119 -30
  153. package/src/normalize-fields.ts +4 -2
  154. package/src/{pagination.js → pagination.tsx} +29 -8
  155. package/src/{reset-filters.js → reset-filters.tsx} +17 -2
  156. package/src/{search-widget.js → search-widget.tsx} +27 -7
  157. package/src/{search.js → search.tsx} +22 -5
  158. package/src/{single-selection-checkbox.js → single-selection-checkbox.tsx} +17 -2
  159. package/src/style.scss +166 -43
  160. package/src/types.ts +286 -21
  161. package/src/{utils.js → utils.ts} +5 -13
  162. package/src/{view-actions.js → view-actions.tsx} +105 -49
  163. package/src/{view-grid.js → view-grid.tsx} +31 -18
  164. package/src/view-list.tsx +410 -0
  165. package/src/{view-table.js → view-table.tsx} +99 -40
  166. package/tsconfig.json +3 -4
  167. package/tsconfig.tsbuildinfo +1 -1
  168. package/build/dropdown-menu-helper.js +0 -71
  169. package/build/dropdown-menu-helper.js.map +0 -1
  170. package/build-module/dropdown-menu-helper.js +0 -64
  171. package/build-module/dropdown-menu-helper.js.map +0 -1
  172. package/src/dropdown-menu-helper.js +0 -61
  173. package/src/view-list.js +0 -207
  174. /package/src/{index.js → index.ts} +0 -0
  175. /package/src/{layouts.js → layouts.ts} +0 -0
  176. /package/src/{lock-unlock.js → lock-unlock.ts} +0 -0
@@ -1,7 +1,8 @@
1
1
  /**
2
2
  * External dependencies
3
3
  */
4
- import classnames from 'classnames';
4
+ import clsx from 'clsx';
5
+ import type { ReactNode, Ref, PropsWithoutRef, RefAttributes } from 'react';
5
6
 
6
7
  /**
7
8
  * WordPress dependencies
@@ -33,11 +34,24 @@ import SingleSelectionCheckbox from './single-selection-checkbox';
33
34
  import { unlock } from './lock-unlock';
34
35
  import ItemActions from './item-actions';
35
36
  import { sanitizeOperators } from './utils';
36
- import { SORTING_DIRECTIONS } from './constants';
37
+ import {
38
+ SORTING_DIRECTIONS,
39
+ sortArrows,
40
+ sortLabels,
41
+ sortValues,
42
+ } from './constants';
37
43
  import {
38
44
  useSomeItemHasAPossibleBulkAction,
39
45
  useHasAPossibleBulkAction,
40
46
  } from './bulk-actions';
47
+ import type {
48
+ Action,
49
+ AnyItem,
50
+ NormalizedField,
51
+ SortDirection,
52
+ ViewTable as ViewTableType,
53
+ ViewTableProps,
54
+ } from './types';
41
55
 
42
56
  const {
43
57
  DropdownMenuV2: DropdownMenu,
@@ -48,7 +62,35 @@ const {
48
62
  DropdownMenuSeparatorV2: DropdownMenuSeparator,
49
63
  } = unlock( componentsPrivateApis );
50
64
 
51
- function WithDropDownMenuSeparators( { children } ) {
65
+ interface HeaderMenuProps< Item extends AnyItem > {
66
+ field: NormalizedField< Item >;
67
+ view: ViewTableType;
68
+ onChangeView: ( view: ViewTableType ) => void;
69
+ onHide: ( field: NormalizedField< Item > ) => void;
70
+ setOpenedFilter: ( fieldId: string ) => void;
71
+ }
72
+
73
+ interface BulkSelectionCheckboxProps< Item extends AnyItem > {
74
+ selection: string[];
75
+ onSelectionChange: ( items: Item[] ) => void;
76
+ data: Item[];
77
+ actions: Action< Item >[];
78
+ }
79
+
80
+ interface TableRowProps< Item extends AnyItem > {
81
+ hasBulkActions: boolean;
82
+ item: Item;
83
+ actions: Action< Item >[];
84
+ id: string;
85
+ visibleFields: NormalizedField< Item >[];
86
+ primaryField?: NormalizedField< Item >;
87
+ selection: string[];
88
+ getItemId: ( item: Item ) => string;
89
+ onSelectionChange: ( items: Item[] ) => void;
90
+ data: Item[];
91
+ }
92
+
93
+ function WithDropDownMenuSeparators( { children }: { children: ReactNode } ) {
52
94
  return Children.toArray( children )
53
95
  .filter( Boolean )
54
96
  .map( ( child, i ) => (
@@ -59,11 +101,15 @@ function WithDropDownMenuSeparators( { children } ) {
59
101
  ) );
60
102
  }
61
103
 
62
- const sortArrows = { asc: '↑', desc: '↓' };
63
-
64
- const HeaderMenu = forwardRef( function HeaderMenu(
65
- { field, view, onChangeView, onHide, setOpenedFilter },
66
- ref
104
+ const _HeaderMenu = forwardRef( function HeaderMenu< Item extends AnyItem >(
105
+ {
106
+ field,
107
+ view,
108
+ onChangeView,
109
+ onHide,
110
+ setOpenedFilter,
111
+ }: HeaderMenuProps< Item >,
112
+ ref: Ref< HTMLButtonElement >
67
113
  ) {
68
114
  const isHidable = field.enableHiding !== false;
69
115
  const isSortable = field.enableSorting !== false;
@@ -92,9 +138,9 @@ const HeaderMenu = forwardRef( function HeaderMenu(
92
138
  variant="tertiary"
93
139
  >
94
140
  { field.header }
95
- { isSorted && (
141
+ { view.sort && isSorted && (
96
142
  <span aria-hidden="true">
97
- { isSorted && sortArrows[ view.sort.direction ] }
143
+ { sortArrows[ view.sort.direction ] }
98
144
  </span>
99
145
  ) }
100
146
  </Button>
@@ -104,9 +150,10 @@ const HeaderMenu = forwardRef( function HeaderMenu(
104
150
  <WithDropDownMenuSeparators>
105
151
  { isSortable && (
106
152
  <DropdownMenuGroup>
107
- { Object.entries( SORTING_DIRECTIONS ).map(
108
- ( [ direction, info ] ) => {
153
+ { SORTING_DIRECTIONS.map(
154
+ ( direction: SortDirection ) => {
109
155
  const isChecked =
156
+ view.sort &&
110
157
  isSorted &&
111
158
  view.sort.direction === direction;
112
159
 
@@ -134,7 +181,7 @@ const HeaderMenu = forwardRef( function HeaderMenu(
134
181
  } }
135
182
  >
136
183
  <DropdownMenuItemLabel>
137
- { info.label }
184
+ { sortLabels[ direction ] }
138
185
  </DropdownMenuItemLabel>
139
186
  </DropdownMenuRadioItem>
140
187
  );
@@ -191,16 +238,24 @@ const HeaderMenu = forwardRef( function HeaderMenu(
191
238
  );
192
239
  } );
193
240
 
194
- function BulkSelectionCheckbox( {
241
+ // @ts-expect-error Lift the `Item` type argument through the forwardRef.
242
+ const HeaderMenu: < Item extends AnyItem >(
243
+ props: PropsWithoutRef< HeaderMenuProps< Item > > &
244
+ RefAttributes< HTMLButtonElement >
245
+ ) => ReturnType< typeof _HeaderMenu > = _HeaderMenu;
246
+
247
+ function BulkSelectionCheckbox< Item extends AnyItem >( {
195
248
  selection,
196
249
  onSelectionChange,
197
250
  data,
198
251
  actions,
199
- } ) {
252
+ }: BulkSelectionCheckboxProps< Item > ) {
200
253
  const selectableItems = useMemo( () => {
201
254
  return data.filter( ( item ) => {
202
255
  return actions.some(
203
- ( action ) => action.supportsBulk && action.isEligible( item )
256
+ ( action ) =>
257
+ action.supportsBulk &&
258
+ ( ! action.isEligible || action.isEligible( item ) )
204
259
  );
205
260
  } );
206
261
  }, [ data, actions ] );
@@ -210,7 +265,7 @@ function BulkSelectionCheckbox( {
210
265
  className="dataviews-view-table-selection-checkbox"
211
266
  __nextHasNoMarginBottom
212
267
  checked={ areAllSelected }
213
- indeterminate={ ! areAllSelected && selection.length }
268
+ indeterminate={ ! areAllSelected && !! selection.length }
214
269
  onChange={ () => {
215
270
  if ( areAllSelected ) {
216
271
  onSelectionChange( [] );
@@ -225,7 +280,7 @@ function BulkSelectionCheckbox( {
225
280
  );
226
281
  }
227
282
 
228
- function TableRow( {
283
+ function TableRow< Item extends AnyItem >( {
229
284
  hasBulkActions,
230
285
  item,
231
286
  actions,
@@ -236,7 +291,7 @@ function TableRow( {
236
291
  getItemId,
237
292
  onSelectionChange,
238
293
  data,
239
- } ) {
294
+ }: TableRowProps< Item > ) {
240
295
  const hasPossibleBulkAction = useHasAPossibleBulkAction( actions, item );
241
296
  const isSelected = selection.includes( id );
242
297
 
@@ -257,7 +312,7 @@ function TableRow( {
257
312
 
258
313
  return (
259
314
  <tr
260
- className={ classnames( 'dataviews-view-table__row', {
315
+ className={ clsx( 'dataviews-view-table__row', {
261
316
  'is-selected': hasPossibleBulkAction && isSelected,
262
317
  'is-hovered': isHovered,
263
318
  'has-bulk-actions': hasPossibleBulkAction,
@@ -270,7 +325,7 @@ function TableRow( {
270
325
  onClick={ () => {
271
326
  if (
272
327
  ! isTouchDevice.current &&
273
- document.getSelection().type !== 'Range'
328
+ document.getSelection()?.type !== 'Range'
274
329
  ) {
275
330
  if ( ! isSelected ) {
276
331
  onSelectionChange(
@@ -305,7 +360,6 @@ function TableRow( {
305
360
  >
306
361
  <div className="dataviews-view-table__cell-content-wrapper">
307
362
  <SingleSelectionCheckbox
308
- id={ id }
309
363
  item={ item }
310
364
  selection={ selection }
311
365
  onSelectionChange={ onSelectionChange }
@@ -327,7 +381,7 @@ function TableRow( {
327
381
  } }
328
382
  >
329
383
  <div
330
- className={ classnames(
384
+ className={ clsx(
331
385
  'dataviews-view-table__cell-content-wrapper',
332
386
  {
333
387
  'dataviews-view-table__primary-field':
@@ -361,21 +415,24 @@ function TableRow( {
361
415
  );
362
416
  }
363
417
 
364
- function ViewTable( {
365
- view,
366
- onChangeView,
367
- fields,
418
+ function ViewTable< Item extends AnyItem >( {
368
419
  actions,
369
420
  data,
421
+ fields,
370
422
  getItemId,
371
423
  isLoading = false,
372
- selection,
424
+ onChangeView,
373
425
  onSelectionChange,
426
+ selection,
374
427
  setOpenedFilter,
375
- } ) {
376
- const headerMenuRefs = useRef( new Map() );
377
- const headerMenuToFocusRef = useRef();
378
- const [ nextHeaderMenuToFocus, setNextHeaderMenuToFocus ] = useState();
428
+ view,
429
+ }: ViewTableProps< Item > ) {
430
+ const headerMenuRefs = useRef<
431
+ Map< string, { node: HTMLButtonElement; fallback: string } >
432
+ >( new Map() );
433
+ const headerMenuToFocusRef = useRef< HTMLButtonElement >();
434
+ const [ nextHeaderMenuToFocus, setNextHeaderMenuToFocus ] =
435
+ useState< HTMLButtonElement >();
379
436
  const hasBulkActions = useSomeItemHasAPossibleBulkAction( actions, data );
380
437
 
381
438
  useEffect( () => {
@@ -393,13 +450,15 @@ function ViewTable( {
393
450
  // Clearing out the focus directive is necessary to make sure
394
451
  // future renders don't cause unexpected focus jumps.
395
452
  headerMenuToFocusRef.current = nextHeaderMenuToFocus;
396
- setNextHeaderMenuToFocus();
453
+ setNextHeaderMenuToFocus( undefined );
397
454
  return;
398
455
  }
399
456
 
400
- const onHide = ( field ) => {
457
+ const onHide = ( field: NormalizedField< Item > ) => {
401
458
  const hidden = headerMenuRefs.current.get( field.id );
402
- const fallback = headerMenuRefs.current.get( hidden.fallback );
459
+ const fallback = hidden
460
+ ? headerMenuRefs.current.get( hidden.fallback )
461
+ : undefined;
403
462
  setNextHeaderMenuToFocus( fallback?.node );
404
463
  };
405
464
  const visibleFields = fields.filter(
@@ -408,7 +467,6 @@ function ViewTable( {
408
467
  ! [ view.layout.mediaField ].includes( field.id )
409
468
  );
410
469
  const hasData = !! data?.length;
411
- const sortValues = { asc: 'ascending', desc: 'descending' };
412
470
 
413
471
  const primaryField = fields.find(
414
472
  ( field ) => field.id === view.layout.primaryField
@@ -450,8 +508,9 @@ function ViewTable( {
450
508
  } }
451
509
  data-field-id={ field.id }
452
510
  aria-sort={
453
- view.sort?.field === field.id &&
454
- sortValues[ view.sort.direction ]
511
+ view.sort?.field === field.id
512
+ ? sortValues[ view.sort.direction ]
513
+ : undefined
455
514
  }
456
515
  scope="col"
457
516
  >
@@ -504,7 +563,7 @@ function ViewTable( {
504
563
  item={ item }
505
564
  hasBulkActions={ hasBulkActions }
506
565
  actions={ actions }
507
- id={ getItemId( item ) || index }
566
+ id={ getItemId( item ) || index.toString() }
508
567
  visibleFields={ visibleFields }
509
568
  primaryField={ primaryField }
510
569
  selection={ selection }
@@ -516,7 +575,7 @@ function ViewTable( {
516
575
  </tbody>
517
576
  </table>
518
577
  <div
519
- className={ classnames( {
578
+ className={ clsx( {
520
579
  'dataviews-loading': isLoading,
521
580
  'dataviews-no-results': ! hasData && ! isLoading,
522
581
  } ) }
package/tsconfig.json CHANGED
@@ -3,18 +3,17 @@
3
3
  "extends": "../../tsconfig.base.json",
4
4
  "compilerOptions": {
5
5
  "rootDir": "src",
6
- "declarationDir": "build-types"
6
+ "declarationDir": "build-types",
7
+ "checkJs": false
7
8
  },
8
9
  "references": [
9
- { "path": "../a11y" },
10
10
  { "path": "../components" },
11
11
  { "path": "../compose" },
12
12
  { "path": "../element" },
13
13
  { "path": "../i18n" },
14
14
  { "path": "../icons" },
15
- { "path": "../keycodes" },
16
15
  { "path": "../primitives" },
17
16
  { "path": "../private-apis" }
18
17
  ],
19
- "include": [ "src/**/*.ts", "src/**/*.tsx" ]
18
+ "include": [ "src" ]
20
19
  }