@wordpress/dataviews 0.9.0 → 1.1.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 (109) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +0 -8
  3. package/build/add-filter.js.map +1 -1
  4. package/build/bulk-actions.js.map +1 -1
  5. package/build/constants.js +1 -26
  6. package/build/constants.js.map +1 -1
  7. package/build/dataviews.js +3 -6
  8. package/build/dataviews.js.map +1 -1
  9. package/build/dropdown-menu-helper.js.map +1 -1
  10. package/build/filter-and-sort-data-view.js +72 -65
  11. package/build/filter-and-sort-data-view.js.map +1 -1
  12. package/build/filter-summary.js +4 -2
  13. package/build/filter-summary.js.map +1 -1
  14. package/build/filters.js.map +1 -1
  15. package/build/index.js +2 -2
  16. package/build/index.js.map +1 -1
  17. package/build/item-actions.js.map +1 -1
  18. package/build/layouts.js +38 -0
  19. package/build/layouts.js.map +1 -0
  20. package/build/lock-unlock.js.map +1 -1
  21. package/build/normalize-fields.js +7 -2
  22. package/build/normalize-fields.js.map +1 -1
  23. package/build/pagination.js.map +1 -1
  24. package/build/reset-filters.js.map +1 -1
  25. package/build/search-widget.js +5 -4
  26. package/build/search-widget.js.map +1 -1
  27. package/build/search.js.map +1 -1
  28. package/build/single-selection-checkbox.js +1 -1
  29. package/build/single-selection-checkbox.js.map +1 -1
  30. package/build/types.js +6 -0
  31. package/build/types.js.map +1 -0
  32. package/build/utils.js.map +1 -1
  33. package/build/view-actions.js +2 -1
  34. package/build/view-actions.js.map +1 -1
  35. package/build/view-grid.js +43 -15
  36. package/build/view-grid.js.map +1 -1
  37. package/build/view-list.js +4 -22
  38. package/build/view-list.js.map +1 -1
  39. package/build/view-table.js +5 -11
  40. package/build/view-table.js.map +1 -1
  41. package/build-module/add-filter.js.map +1 -1
  42. package/build-module/bulk-actions.js.map +1 -1
  43. package/build-module/constants.js +1 -25
  44. package/build-module/constants.js.map +1 -1
  45. package/build-module/dataviews.js +3 -6
  46. package/build-module/dataviews.js.map +1 -1
  47. package/build-module/dropdown-menu-helper.js.map +1 -1
  48. package/build-module/filter-and-sort-data-view.js +72 -65
  49. package/build-module/filter-and-sort-data-view.js.map +1 -1
  50. package/build-module/filter-summary.js +3 -2
  51. package/build-module/filter-summary.js.map +1 -1
  52. package/build-module/filters.js.map +1 -1
  53. package/build-module/index.js +1 -1
  54. package/build-module/index.js.map +1 -1
  55. package/build-module/item-actions.js.map +1 -1
  56. package/build-module/layouts.js +30 -0
  57. package/build-module/layouts.js.map +1 -0
  58. package/build-module/lock-unlock.js.map +1 -1
  59. package/build-module/normalize-fields.js +7 -2
  60. package/build-module/normalize-fields.js.map +1 -1
  61. package/build-module/pagination.js.map +1 -1
  62. package/build-module/reset-filters.js.map +1 -1
  63. package/build-module/search-widget.js +4 -3
  64. package/build-module/search-widget.js.map +1 -1
  65. package/build-module/search.js.map +1 -1
  66. package/build-module/single-selection-checkbox.js +1 -1
  67. package/build-module/single-selection-checkbox.js.map +1 -1
  68. package/build-module/types.js +2 -0
  69. package/build-module/types.js.map +1 -0
  70. package/build-module/utils.js.map +1 -1
  71. package/build-module/view-actions.js +2 -1
  72. package/build-module/view-actions.js.map +1 -1
  73. package/build-module/view-grid.js +43 -15
  74. package/build-module/view-grid.js.map +1 -1
  75. package/build-module/view-list.js +6 -24
  76. package/build-module/view-list.js.map +1 -1
  77. package/build-module/view-table.js +5 -11
  78. package/build-module/view-table.js.map +1 -1
  79. package/build-style/style-rtl.css +60 -45
  80. package/build-style/style.css +60 -45
  81. package/build-types/constants.d.ts +45 -0
  82. package/build-types/constants.d.ts.map +1 -0
  83. package/build-types/filter-and-sort-data-view.d.ts +18 -0
  84. package/build-types/filter-and-sort-data-view.d.ts.map +1 -0
  85. package/build-types/normalize-fields.d.ts +12 -0
  86. package/build-types/normalize-fields.d.ts.map +1 -0
  87. package/build-types/types.d.ts +122 -0
  88. package/build-types/types.d.ts.map +1 -0
  89. package/package.json +11 -11
  90. package/src/{constants.js → constants.ts} +1 -35
  91. package/src/dataviews.js +2 -5
  92. package/src/filter-and-sort-data-view.ts +164 -0
  93. package/src/filter-summary.js +4 -4
  94. package/src/index.js +1 -1
  95. package/src/layouts.js +39 -0
  96. package/src/normalize-fields.ts +23 -0
  97. package/src/search-widget.js +4 -3
  98. package/src/single-selection-checkbox.js +1 -1
  99. package/src/stories/fixtures.js +0 -2
  100. package/src/style.scss +65 -51
  101. package/src/types.ts +144 -0
  102. package/src/view-actions.js +2 -1
  103. package/src/view-grid.js +91 -52
  104. package/src/view-list.js +4 -24
  105. package/src/view-table.js +7 -11
  106. package/tsconfig.json +20 -0
  107. package/tsconfig.tsbuildinfo +1 -0
  108. package/src/filter-and-sort-data-view.js +0 -154
  109. package/src/normalize-fields.js +0 -17
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Internal dependencies
3
+ */
4
+ import type { Field, NormalizedField } from './types';
5
+ /**
6
+ * Apply default values and normalize the fields config.
7
+ *
8
+ * @param fields Fields config.
9
+ * @return Normalized fields config.
10
+ */
11
+ export declare function normalizeFields(fields: Field[]): NormalizedField[];
12
+ //# sourceMappingURL=normalize-fields.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalize-fields.d.ts","sourceRoot":"","sources":["../src/normalize-fields.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAEtD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAE,MAAM,EAAE,KAAK,EAAE,GAAI,eAAe,EAAE,CAWpE"}
@@ -0,0 +1,122 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import type { ReactNode } from 'react';
5
+ type Item = Record<string, any>;
6
+ interface Option {
7
+ value: any;
8
+ label: string;
9
+ }
10
+ interface filterByConfig {
11
+ operators?: Operator[];
12
+ isPrimary?: boolean;
13
+ }
14
+ type Operator = 'is' | 'isNot' | 'isAny' | 'isNone' | 'isAll' | 'isNotAll';
15
+ export interface Field {
16
+ /**
17
+ * The unique identifier of the field.
18
+ */
19
+ id: string;
20
+ /**
21
+ * The label of the field. Defaults to the id.
22
+ */
23
+ header?: string;
24
+ /**
25
+ * Callback used to retrieve the value of the field from the item.
26
+ * Defaults to `item[ field.id ]`.
27
+ */
28
+ getValue?: ({ item }: {
29
+ item: Item;
30
+ }) => any;
31
+ /**
32
+ * Callback used to render the field. Defaults to `field.getValue`.
33
+ */
34
+ render?: ({ item }: {
35
+ item: Item;
36
+ }) => ReactNode;
37
+ /**
38
+ * The width of the field column.
39
+ */
40
+ width: string | number | undefined;
41
+ /**
42
+ * The minimum width of the field column.
43
+ */
44
+ maxWidth: string | number | undefined;
45
+ /**
46
+ * The maximum width of the field column.
47
+ */
48
+ minWidth: string | number | undefined;
49
+ /**
50
+ * Whether the field is sortable.
51
+ */
52
+ enableSorting: boolean | undefined;
53
+ /**
54
+ * Whether the field is searchable.
55
+ */
56
+ enableGlobalSearch: boolean | undefined;
57
+ /**
58
+ * Whether the field is filterable.
59
+ */
60
+ enableHiding: boolean | undefined;
61
+ /**
62
+ * The list of options to pick from when using the field as a filter.
63
+ */
64
+ elements: Option[] | undefined;
65
+ /**
66
+ * Filter config for the field.
67
+ */
68
+ filterBy: filterByConfig | undefined;
69
+ }
70
+ export type NormalizedField = Required<Field>;
71
+ export type Data = Item[];
72
+ export interface Filter {
73
+ /**
74
+ * The field to filter by.
75
+ */
76
+ field: string;
77
+ /**
78
+ * The operator to use.
79
+ */
80
+ operator: Operator;
81
+ /**
82
+ * The value to filter by.
83
+ */
84
+ value: any;
85
+ }
86
+ export interface View {
87
+ /**
88
+ * The layout of the view.
89
+ */
90
+ type: string;
91
+ /**
92
+ * The global search term.
93
+ */
94
+ search?: string;
95
+ /**
96
+ * The filters to apply.
97
+ */
98
+ filters: Filter[];
99
+ /**
100
+ * The sorting configuration.
101
+ */
102
+ sort?: {
103
+ /**
104
+ * The field to sort by.
105
+ */
106
+ field: string;
107
+ /**
108
+ * The direction to sort by.
109
+ */
110
+ direction: string;
111
+ };
112
+ /**
113
+ * The active page
114
+ */
115
+ page?: number;
116
+ /**
117
+ * The number of items per page
118
+ */
119
+ perPage?: number;
120
+ }
121
+ export {};
122
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,KAAK,IAAI,GAAG,MAAM,CAAE,MAAM,EAAE,GAAG,CAAE,CAAC;AAElC,UAAU,MAAM;IACf,KAAK,EAAE,GAAG,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;CACd;AAED,UAAU,cAAc;IACvB,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC;IACvB,SAAS,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,KAAK,QAAQ,GAAG,IAAI,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAG,UAAU,CAAC;AAE3E,MAAM,WAAW,KAAK;IACrB;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IAEX;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAE,EAAE,IAAI,EAAE,EAAE;QAAE,IAAI,EAAE,IAAI,CAAA;KAAE,KAAM,GAAG,CAAC;IAE/C;;OAEG;IACH,MAAM,CAAC,EAAE,CAAE,EAAE,IAAI,EAAE,EAAE;QAAE,IAAI,EAAE,IAAI,CAAA;KAAE,KAAM,SAAS,CAAC;IAEnD;;OAEG;IACH,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IAEnC;;OAEG;IACH,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IAEtC;;OAEG;IACH,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IAEtC;;OAEG;IACH,aAAa,EAAE,OAAO,GAAG,SAAS,CAAC;IAEnC;;OAEG;IACH,kBAAkB,EAAE,OAAO,GAAG,SAAS,CAAC;IAExC;;OAEG;IACH,YAAY,EAAE,OAAO,GAAG,SAAS,CAAC;IAElC;;OAEG;IACH,QAAQ,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IAE/B;;OAEG;IACH,QAAQ,EAAE,cAAc,GAAG,SAAS,CAAC;CACrC;AAED,MAAM,MAAM,eAAe,GAAG,QAAQ,CAAE,KAAK,CAAE,CAAC;AAEhD,MAAM,MAAM,IAAI,GAAG,IAAI,EAAE,CAAC;AAE1B,MAAM,WAAW,MAAM;IACtB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,QAAQ,EAAE,QAAQ,CAAC;IAEnB;;OAEG;IACH,KAAK,EAAE,GAAG,CAAC;CACX;AAED,MAAM,WAAW,IAAI;IACpB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,OAAO,EAAE,MAAM,EAAE,CAAC;IAElB;;OAEG;IACH,IAAI,CAAC,EAAE;QACN;;WAEG;QACH,KAAK,EAAE,MAAM,CAAC;QAEd;;WAEG;QACH,SAAS,EAAE,MAAM,CAAC;KAClB,CAAC;IAEF;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wordpress/dataviews",
3
- "version": "0.9.0",
3
+ "version": "1.1.0",
4
4
  "description": "DataViews is a component that provides an API to render datasets using different types of layouts (table, grid, list, etc.).",
5
5
  "author": "The WordPress Contributors",
6
6
  "license": "GPL-2.0-or-later",
@@ -29,15 +29,15 @@
29
29
  "dependencies": {
30
30
  "@ariakit/react": "^0.3.12",
31
31
  "@babel/runtime": "^7.16.0",
32
- "@wordpress/a11y": "^3.55.0",
33
- "@wordpress/components": "^27.3.0",
34
- "@wordpress/compose": "^6.32.0",
35
- "@wordpress/element": "^5.32.0",
36
- "@wordpress/i18n": "^4.55.0",
37
- "@wordpress/icons": "^9.46.0",
38
- "@wordpress/keycodes": "^3.55.0",
39
- "@wordpress/primitives": "^3.53.0",
40
- "@wordpress/private-apis": "^0.37.0",
32
+ "@wordpress/a11y": "^3.57.0",
33
+ "@wordpress/components": "^27.5.0",
34
+ "@wordpress/compose": "^6.34.0",
35
+ "@wordpress/element": "^5.34.0",
36
+ "@wordpress/i18n": "^4.57.0",
37
+ "@wordpress/icons": "^9.48.0",
38
+ "@wordpress/keycodes": "^3.57.0",
39
+ "@wordpress/primitives": "^3.55.0",
40
+ "@wordpress/private-apis": "^0.39.0",
41
41
  "classnames": "^2.3.1",
42
42
  "remove-accents": "^0.5.0"
43
43
  },
@@ -47,5 +47,5 @@
47
47
  "publishConfig": {
48
48
  "access": "public"
49
49
  },
50
- "gitHead": "ac2b13783c28f959770cf029a797a712f59e1958"
50
+ "gitHead": "581d8a5580dba8f600b7268d51eb554771ae482c"
51
51
  }
@@ -1,20 +1,7 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
- import { __, isRTL } from '@wordpress/i18n';
5
- import {
6
- blockTable,
7
- category,
8
- formatListBullets,
9
- formatListBulletsRTL,
10
- } from '@wordpress/icons';
11
-
12
- /**
13
- * Internal dependencies
14
- */
15
- import ViewTable from './view-table';
16
- import ViewGrid from './view-grid';
17
- import ViewList from './view-list';
4
+ import { __ } from '@wordpress/i18n';
18
5
 
19
6
  // Filter operators.
20
7
  export const OPERATOR_IS = 'is';
@@ -69,24 +56,3 @@ export const SORTING_DIRECTIONS = {
69
56
  export const LAYOUT_TABLE = 'table';
70
57
  export const LAYOUT_GRID = 'grid';
71
58
  export const LAYOUT_LIST = 'list';
72
-
73
- export const VIEW_LAYOUTS = [
74
- {
75
- type: LAYOUT_TABLE,
76
- label: __( 'Table' ),
77
- component: ViewTable,
78
- icon: blockTable,
79
- },
80
- {
81
- type: LAYOUT_GRID,
82
- label: __( 'Grid' ),
83
- component: ViewGrid,
84
- icon: category,
85
- },
86
- {
87
- type: LAYOUT_LIST,
88
- label: __( 'List' ),
89
- component: ViewList,
90
- icon: isRTL() ? formatListBulletsRTL : formatListBullets,
91
- },
92
- ];
package/src/dataviews.js CHANGED
@@ -11,7 +11,8 @@ import Pagination from './pagination';
11
11
  import ViewActions from './view-actions';
12
12
  import Filters from './filters';
13
13
  import Search from './search';
14
- import { VIEW_LAYOUTS, LAYOUT_TABLE, LAYOUT_GRID } from './constants';
14
+ import { LAYOUT_TABLE, LAYOUT_GRID } from './constants';
15
+ import { VIEW_LAYOUTS } from './layouts';
15
16
  import BulkActions from './bulk-actions';
16
17
  import { normalizeFields } from './normalize-fields';
17
18
 
@@ -41,8 +42,6 @@ export default function DataViews( {
41
42
  paginationInfo,
42
43
  supportedLayouts,
43
44
  onSelectionChange = defaultOnSelectionChange,
44
- onDetailsChange = null,
45
- deferredRendering = false,
46
45
  } ) {
47
46
  const [ selection, setSelection ] = useState( [] );
48
47
  const [ openedFilter, setOpenedFilter ] = useState( null );
@@ -136,9 +135,7 @@ export default function DataViews( {
136
135
  getItemId={ getItemId }
137
136
  isLoading={ isLoading }
138
137
  onSelectionChange={ onSetSelection }
139
- onDetailsChange={ onDetailsChange }
140
138
  selection={ selection }
141
- deferredRendering={ deferredRendering }
142
139
  setOpenedFilter={ setOpenedFilter }
143
140
  />
144
141
  <Pagination
@@ -0,0 +1,164 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import removeAccents from 'remove-accents';
5
+
6
+ /**
7
+ * Internal dependencies
8
+ */
9
+ import {
10
+ OPERATOR_IS,
11
+ OPERATOR_IS_NOT,
12
+ OPERATOR_IS_NONE,
13
+ OPERATOR_IS_ANY,
14
+ OPERATOR_IS_ALL,
15
+ OPERATOR_IS_NOT_ALL,
16
+ } from './constants';
17
+ import { normalizeFields } from './normalize-fields';
18
+ import type { Data, Field, View } from './types';
19
+
20
+ function normalizeSearchInput( input = '' ) {
21
+ return removeAccents( input.trim().toLowerCase() );
22
+ }
23
+
24
+ const EMPTY_ARRAY: Data = [];
25
+
26
+ /**
27
+ * Applies the filtering, sorting and pagination to the raw data based on the view configuration.
28
+ *
29
+ * @param data Raw data.
30
+ * @param view View config.
31
+ * @param fields Fields config.
32
+ *
33
+ * @return Filtered, sorted and paginated data.
34
+ */
35
+ export function filterSortAndPaginate(
36
+ data: Data,
37
+ view: View,
38
+ fields: Field[]
39
+ ): { data: Data; paginationInfo: { totalItems: number; totalPages: number } } {
40
+ if ( ! data ) {
41
+ return {
42
+ data: EMPTY_ARRAY,
43
+ paginationInfo: { totalItems: 0, totalPages: 0 },
44
+ };
45
+ }
46
+ const _fields = normalizeFields( fields );
47
+ let filteredData = [ ...data ];
48
+ // Handle global search.
49
+ if ( view.search ) {
50
+ const normalizedSearch = normalizeSearchInput( view.search );
51
+ filteredData = filteredData.filter( ( item ) => {
52
+ return _fields
53
+ .filter( ( field ) => field.enableGlobalSearch )
54
+ .map( ( field ) => {
55
+ return normalizeSearchInput( field.getValue( { item } ) );
56
+ } )
57
+ .some( ( field ) => field.includes( normalizedSearch ) );
58
+ } );
59
+ }
60
+
61
+ if ( view.filters.length > 0 ) {
62
+ view.filters.forEach( ( filter ) => {
63
+ const field = _fields.find(
64
+ ( _field ) => _field.id === filter.field
65
+ );
66
+ if ( field ) {
67
+ if (
68
+ filter.operator === OPERATOR_IS_ANY &&
69
+ filter?.value?.length > 0
70
+ ) {
71
+ filteredData = filteredData.filter( ( item ) => {
72
+ const fieldValue = field.getValue( { item } );
73
+ if ( Array.isArray( fieldValue ) ) {
74
+ return filter.value.some( ( filterValue: any ) =>
75
+ fieldValue.includes( filterValue )
76
+ );
77
+ } else if ( typeof fieldValue === 'string' ) {
78
+ return filter.value.includes( fieldValue );
79
+ }
80
+ return false;
81
+ } );
82
+ } else if (
83
+ filter.operator === OPERATOR_IS_NONE &&
84
+ filter?.value?.length > 0
85
+ ) {
86
+ filteredData = filteredData.filter( ( item ) => {
87
+ const fieldValue = field.getValue( { item } );
88
+ if ( Array.isArray( fieldValue ) ) {
89
+ return ! filter.value.some( ( filterValue: any ) =>
90
+ fieldValue.includes( filterValue )
91
+ );
92
+ } else if ( typeof fieldValue === 'string' ) {
93
+ return ! filter.value.includes( fieldValue );
94
+ }
95
+ return false;
96
+ } );
97
+ } else if (
98
+ filter.operator === OPERATOR_IS_ALL &&
99
+ filter?.value?.length > 0
100
+ ) {
101
+ filteredData = filteredData.filter( ( item ) => {
102
+ return filter.value.every( ( value: any ) => {
103
+ return field.getValue( { item } ).includes( value );
104
+ } );
105
+ } );
106
+ } else if (
107
+ filter.operator === OPERATOR_IS_NOT_ALL &&
108
+ filter?.value?.length > 0
109
+ ) {
110
+ filteredData = filteredData.filter( ( item ) => {
111
+ return filter.value.every( ( value: any ) => {
112
+ return ! field
113
+ .getValue( { item } )
114
+ .includes( value );
115
+ } );
116
+ } );
117
+ } else if ( filter.operator === OPERATOR_IS ) {
118
+ filteredData = filteredData.filter( ( item ) => {
119
+ return filter.value === field.getValue( { item } );
120
+ } );
121
+ } else if ( filter.operator === OPERATOR_IS_NOT ) {
122
+ filteredData = filteredData.filter( ( item ) => {
123
+ return filter.value !== field.getValue( { item } );
124
+ } );
125
+ }
126
+ }
127
+ } );
128
+ }
129
+
130
+ // Handle sorting.
131
+ if ( view.sort ) {
132
+ const fieldId = view.sort.field;
133
+ const fieldToSort = _fields.find( ( field ) => {
134
+ return field.id === fieldId;
135
+ } );
136
+ if ( fieldToSort ) {
137
+ filteredData.sort( ( a, b ) => {
138
+ const valueA = fieldToSort.getValue( { item: a } ) ?? '';
139
+ const valueB = fieldToSort.getValue( { item: b } ) ?? '';
140
+ return view.sort?.direction === 'asc'
141
+ ? valueA.localeCompare( valueB )
142
+ : valueB.localeCompare( valueA );
143
+ } );
144
+ }
145
+ }
146
+
147
+ // Handle pagination.
148
+ let totalItems = filteredData.length;
149
+ let totalPages = 1;
150
+ if ( view.page !== undefined && view.perPage !== undefined ) {
151
+ const start = ( view.page - 1 ) * view.perPage;
152
+ totalItems = filteredData?.length || 0;
153
+ totalPages = Math.ceil( totalItems / view.perPage );
154
+ filteredData = filteredData?.slice( start, start + view.perPage );
155
+ }
156
+
157
+ return {
158
+ data: filteredData,
159
+ paginationInfo: {
160
+ totalItems,
161
+ totalPages,
162
+ },
163
+ };
164
+ }
@@ -18,7 +18,9 @@ import {
18
18
  import { __, sprintf } from '@wordpress/i18n';
19
19
  import { useRef, createInterpolateElement } from '@wordpress/element';
20
20
  import { closeSmall } from '@wordpress/icons';
21
- import { ENTER, SPACE } from '@wordpress/keycodes';
21
+
22
+ const ENTER = 'Enter';
23
+ const SPACE = ' ';
22
24
 
23
25
  /**
24
26
  * Internal dependencies
@@ -229,9 +231,7 @@ export default function FilterSummary( {
229
231
  tabIndex={ 0 }
230
232
  onClick={ onToggle }
231
233
  onKeyDown={ ( event ) => {
232
- if (
233
- [ ENTER, SPACE ].includes( event.keyCode )
234
- ) {
234
+ if ( [ ENTER, SPACE ].includes( event.key ) ) {
235
235
  onToggle();
236
236
  event.preventDefault();
237
237
  }
package/src/index.js CHANGED
@@ -1,3 +1,3 @@
1
1
  export { default as DataViews } from './dataviews';
2
- export { VIEW_LAYOUTS } from './constants';
2
+ export { VIEW_LAYOUTS } from './layouts';
3
3
  export { filterSortAndPaginate } from './filter-and-sort-data-view';
package/src/layouts.js ADDED
@@ -0,0 +1,39 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { __, isRTL } from '@wordpress/i18n';
5
+ import {
6
+ blockTable,
7
+ category,
8
+ formatListBullets,
9
+ formatListBulletsRTL,
10
+ } from '@wordpress/icons';
11
+
12
+ /**
13
+ * Internal dependencies
14
+ */
15
+ import ViewTable from './view-table';
16
+ import ViewGrid from './view-grid';
17
+ import ViewList from './view-list';
18
+ import { LAYOUT_GRID, LAYOUT_LIST, LAYOUT_TABLE } from './constants';
19
+
20
+ export const VIEW_LAYOUTS = [
21
+ {
22
+ type: LAYOUT_TABLE,
23
+ label: __( 'Table' ),
24
+ component: ViewTable,
25
+ icon: blockTable,
26
+ },
27
+ {
28
+ type: LAYOUT_GRID,
29
+ label: __( 'Grid' ),
30
+ component: ViewGrid,
31
+ icon: category,
32
+ },
33
+ {
34
+ type: LAYOUT_LIST,
35
+ label: __( 'List' ),
36
+ component: ViewList,
37
+ icon: isRTL() ? formatListBulletsRTL : formatListBullets,
38
+ },
39
+ ];
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Internal dependencies
3
+ */
4
+ import type { Field, NormalizedField } from './types';
5
+
6
+ /**
7
+ * Apply default values and normalize the fields config.
8
+ *
9
+ * @param fields Fields config.
10
+ * @return Normalized fields config.
11
+ */
12
+ export function normalizeFields( fields: Field[] ): NormalizedField[] {
13
+ return fields.map( ( field ) => {
14
+ const getValue = field.getValue || ( ( { item } ) => item[ field.id ] );
15
+
16
+ return {
17
+ ...field,
18
+ header: field.header || field.id,
19
+ getValue,
20
+ render: field.render || getValue,
21
+ };
22
+ } );
23
+ }
@@ -39,6 +39,7 @@ function normalizeSearchInput( input = '' ) {
39
39
  return removeAccents( input.trim().toLowerCase() );
40
40
  }
41
41
 
42
+ const EMPTY_ARRAY = [];
42
43
  const getCurrentValue = ( filterDefinition, currentFilter ) => {
43
44
  if ( filterDefinition.singleSelection ) {
44
45
  return currentFilter?.value;
@@ -52,7 +53,7 @@ const getCurrentValue = ( filterDefinition, currentFilter ) => {
52
53
  return [ currentFilter.value ];
53
54
  }
54
55
 
55
- return [];
56
+ return EMPTY_ARRAY;
56
57
  };
57
58
 
58
59
  const getNewValue = ( filterDefinition, currentFilter, value ) => {
@@ -73,7 +74,7 @@ function ListBox( { view, filter, onChangeView } ) {
73
74
  const compositeStore = useCompositeStore( {
74
75
  virtualFocus: true,
75
76
  focusLoop: true,
76
- // When we have no or just one operators, we can set the first item as active.
77
+ // When we have no or just one operator, we can set the first item as active.
77
78
  // We do that by passing `undefined` to `defaultActiveId`. Otherwise, we set it to `null`,
78
79
  // so the first item is not selected, since the focus is on the operators control.
79
80
  defaultActiveId: filter.operators?.length === 1 ? undefined : null,
@@ -198,7 +199,7 @@ function ComboboxList( { view, filter, onChangeView } ) {
198
199
  }, [ filter.elements, deferredSearchValue ] );
199
200
  return (
200
201
  <Ariakit.ComboboxProvider
201
- value={ searchValue }
202
+ resetValueOnSelect={ false }
202
203
  selectedValue={ currentValue }
203
204
  setSelectedValue={ ( value ) => {
204
205
  const newFilters = currentFilter
@@ -32,7 +32,7 @@ export default function SingleSelectionCheckbox( {
32
32
  <CheckboxControl
33
33
  className="dataviews-view-table-selection-checkbox"
34
34
  __nextHasNoMarginBottom
35
- label={ selectionLabel }
35
+ aria-label={ selectionLabel }
36
36
  aria-disabled={ disabled }
37
37
  checked={ isSelected }
38
38
  onChange={ () => {
@@ -171,7 +171,6 @@ export const fields = [
171
171
  id: 'type',
172
172
  maxWidth: 400,
173
173
  enableHiding: false,
174
- type: 'enumeration',
175
174
  elements: [
176
175
  { value: 'Not a planet', label: 'Not a planet' },
177
176
  { value: 'Ice giant', label: 'Ice giant' },
@@ -189,7 +188,6 @@ export const fields = [
189
188
  {
190
189
  header: 'Categories',
191
190
  id: 'categories',
192
- type: 'enumeration',
193
191
  elements: [
194
192
  { value: 'Space', label: 'Space' },
195
193
  { value: 'NASA', label: 'NASA' },