@wordpress/dataviews 2.2.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 (153) hide show
  1. package/CHANGELOG.md +16 -0
  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 +0 -1
  6. package/build/bulk-actions-toolbar.js.map +1 -1
  7. package/build/bulk-actions.js +1 -1
  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 +17 -28
  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 +1 -1
  22. package/build/item-actions.js.map +1 -1
  23. package/build/normalize-fields.js.map +1 -1
  24. package/build/pagination.js +2 -2
  25. package/build/pagination.js.map +1 -1
  26. package/build/private-types.js +6 -0
  27. package/build/private-types.js.map +1 -0
  28. package/build/reset-filters.js +1 -1
  29. package/build/reset-filters.js.map +1 -1
  30. package/build/search-widget.js +8 -6
  31. package/build/search-widget.js.map +1 -1
  32. package/build/single-selection-checkbox.js +5 -16
  33. package/build/single-selection-checkbox.js.map +1 -1
  34. package/build/types.js.map +1 -1
  35. package/build/utils.js.map +1 -1
  36. package/build/view-actions.js +76 -65
  37. package/build/view-actions.js.map +1 -1
  38. package/build/view-grid.js +7 -19
  39. package/build/view-grid.js.map +1 -1
  40. package/build/view-list.js +6 -5
  41. package/build/view-list.js.map +1 -1
  42. package/build/view-table.js +11 -20
  43. package/build/view-table.js.map +1 -1
  44. package/build-module/add-filter.js +1 -1
  45. package/build-module/add-filter.js.map +1 -1
  46. package/build-module/bulk-actions-toolbar.js +0 -1
  47. package/build-module/bulk-actions-toolbar.js.map +1 -1
  48. package/build-module/bulk-actions.js +1 -1
  49. package/build-module/bulk-actions.js.map +1 -1
  50. package/build-module/dataform.js +72 -0
  51. package/build-module/dataform.js.map +1 -0
  52. package/build-module/dataviews.js +15 -28
  53. package/build-module/dataviews.js.map +1 -1
  54. package/build-module/filter-and-sort-data-view.js +4 -1
  55. package/build-module/filter-and-sort-data-view.js.map +1 -1
  56. package/build-module/filter-summary.js +6 -5
  57. package/build-module/filter-summary.js.map +1 -1
  58. package/build-module/filters.js +1 -1
  59. package/build-module/filters.js.map +1 -1
  60. package/build-module/index.js +1 -0
  61. package/build-module/index.js.map +1 -1
  62. package/build-module/item-actions.js +1 -1
  63. package/build-module/item-actions.js.map +1 -1
  64. package/build-module/normalize-fields.js.map +1 -1
  65. package/build-module/pagination.js +2 -2
  66. package/build-module/pagination.js.map +1 -1
  67. package/build-module/private-types.js +2 -0
  68. package/build-module/private-types.js.map +1 -0
  69. package/build-module/reset-filters.js +1 -1
  70. package/build-module/reset-filters.js.map +1 -1
  71. package/build-module/search-widget.js +8 -6
  72. package/build-module/search-widget.js.map +1 -1
  73. package/build-module/single-selection-checkbox.js +5 -16
  74. package/build-module/single-selection-checkbox.js.map +1 -1
  75. package/build-module/types.js.map +1 -1
  76. package/build-module/utils.js.map +1 -1
  77. package/build-module/view-actions.js +80 -68
  78. package/build-module/view-actions.js.map +1 -1
  79. package/build-module/view-grid.js +7 -19
  80. package/build-module/view-grid.js.map +1 -1
  81. package/build-module/view-list.js +6 -5
  82. package/build-module/view-list.js.map +1 -1
  83. package/build-module/view-table.js +11 -20
  84. package/build-module/view-table.js.map +1 -1
  85. package/build-style/style-rtl.css +8 -24
  86. package/build-style/style.css +8 -24
  87. package/build-types/bulk-actions-toolbar.d.ts +5 -4
  88. package/build-types/bulk-actions-toolbar.d.ts.map +1 -1
  89. package/build-types/bulk-actions.d.ts +7 -6
  90. package/build-types/bulk-actions.d.ts.map +1 -1
  91. package/build-types/dataform.d.ts +17 -0
  92. package/build-types/dataform.d.ts.map +1 -0
  93. package/build-types/dataviews.d.ts +14 -7
  94. package/build-types/dataviews.d.ts.map +1 -1
  95. package/build-types/filter-and-sort-data-view.d.ts +2 -2
  96. package/build-types/filter-and-sort-data-view.d.ts.map +1 -1
  97. package/build-types/filter-summary.d.ts.map +1 -1
  98. package/build-types/filters.d.ts +3 -3
  99. package/build-types/filters.d.ts.map +1 -1
  100. package/build-types/index.d.ts +1 -0
  101. package/build-types/index.d.ts.map +1 -1
  102. package/build-types/item-actions.d.ts +10 -10
  103. package/build-types/item-actions.d.ts.map +1 -1
  104. package/build-types/normalize-fields.d.ts +2 -2
  105. package/build-types/normalize-fields.d.ts.map +1 -1
  106. package/build-types/private-types.d.ts +3 -0
  107. package/build-types/private-types.d.ts.map +1 -0
  108. package/build-types/single-selection-checkbox.d.ts +5 -5
  109. package/build-types/single-selection-checkbox.d.ts.map +1 -1
  110. package/build-types/stories/fixtures.d.ts +14 -1
  111. package/build-types/stories/fixtures.d.ts.map +1 -1
  112. package/build-types/stories/index.story.d.ts +15 -1
  113. package/build-types/stories/index.story.d.ts.map +1 -1
  114. package/build-types/types.d.ts +68 -27
  115. package/build-types/types.d.ts.map +1 -1
  116. package/build-types/utils.d.ts +2 -2
  117. package/build-types/utils.d.ts.map +1 -1
  118. package/build-types/view-actions.d.ts +4 -4
  119. package/build-types/view-actions.d.ts.map +1 -1
  120. package/build-types/view-grid.d.ts +2 -2
  121. package/build-types/view-grid.d.ts.map +1 -1
  122. package/build-types/view-list.d.ts +2 -2
  123. package/build-types/view-list.d.ts.map +1 -1
  124. package/build-types/view-table.d.ts +2 -2
  125. package/build-types/view-table.d.ts.map +1 -1
  126. package/package.json +10 -10
  127. package/src/add-filter.tsx +1 -1
  128. package/src/bulk-actions-toolbar.tsx +13 -13
  129. package/src/bulk-actions.tsx +18 -13
  130. package/src/dataform.tsx +106 -0
  131. package/src/dataviews.tsx +43 -49
  132. package/src/filter-and-sort-data-view.ts +13 -3
  133. package/src/filter-summary.tsx +18 -12
  134. package/src/filters.tsx +4 -4
  135. package/src/index.ts +1 -0
  136. package/src/item-actions.tsx +15 -16
  137. package/src/normalize-fields.ts +5 -3
  138. package/src/pagination.tsx +2 -2
  139. package/src/private-types.tsx +2 -0
  140. package/src/reset-filters.tsx +1 -1
  141. package/src/search-widget.tsx +6 -6
  142. package/src/single-selection-checkbox.tsx +14 -29
  143. package/src/stories/fixtures.js +17 -1
  144. package/src/stories/index.story.js +15 -28
  145. package/src/style.scss +10 -22
  146. package/src/test/filter-and-sort-data-view.js +16 -1
  147. package/src/types.ts +68 -34
  148. package/src/utils.ts +2 -4
  149. package/src/view-actions.tsx +105 -102
  150. package/src/view-grid.tsx +21 -38
  151. package/src/view-list.tsx +12 -15
  152. package/src/view-table.tsx +31 -42
  153. package/tsconfig.tsbuildinfo +1 -1
@@ -33,7 +33,7 @@ export default function ResetFilter( {
33
33
  return (
34
34
  <Button
35
35
  disabled={ isDisabled }
36
- __experimentalIsFocusable
36
+ accessibleWhenDisabled
37
37
  size="compact"
38
38
  variant="tertiary"
39
39
  className="dataviews-filters__reset-button"
@@ -93,7 +93,7 @@ function ListBox( { view, filter, onChangeView }: SearchWidgetProps ) {
93
93
  // so the first item is not selected, since the focus is on the operators control.
94
94
  defaultActiveId: filter.operators?.length === 1 ? undefined : null,
95
95
  } );
96
- const currentFilter = view.filters.find(
96
+ const currentFilter = view.filters?.find(
97
97
  ( f ) => f.field === filter.field
98
98
  );
99
99
  const currentValue = getCurrentValue( filter, currentFilter );
@@ -130,7 +130,7 @@ function ListBox( { view, filter, onChangeView }: SearchWidgetProps ) {
130
130
  onClick={ () => {
131
131
  const newFilters = currentFilter
132
132
  ? [
133
- ...view.filters.map(
133
+ ...( view.filters ?? [] ).map(
134
134
  ( _filter ) => {
135
135
  if (
136
136
  _filter.field ===
@@ -154,7 +154,7 @@ function ListBox( { view, filter, onChangeView }: SearchWidgetProps ) {
154
154
  ),
155
155
  ]
156
156
  : [
157
- ...view.filters,
157
+ ...( view.filters ?? [] ),
158
158
  {
159
159
  field: filter.field,
160
160
  operator: filter.operators[ 0 ],
@@ -201,7 +201,7 @@ function ListBox( { view, filter, onChangeView }: SearchWidgetProps ) {
201
201
  function ComboboxList( { view, filter, onChangeView }: SearchWidgetProps ) {
202
202
  const [ searchValue, setSearchValue ] = useState( '' );
203
203
  const deferredSearchValue = useDeferredValue( searchValue );
204
- const currentFilter = view.filters.find(
204
+ const currentFilter = view.filters?.find(
205
205
  ( _filter ) => _filter.field === filter.field
206
206
  );
207
207
  const currentValue = getCurrentValue( filter, currentFilter );
@@ -218,7 +218,7 @@ function ComboboxList( { view, filter, onChangeView }: SearchWidgetProps ) {
218
218
  setSelectedValue={ ( value ) => {
219
219
  const newFilters = currentFilter
220
220
  ? [
221
- ...view.filters.map( ( _filter ) => {
221
+ ...( view.filters ?? [] ).map( ( _filter ) => {
222
222
  if ( _filter.field === filter.field ) {
223
223
  return {
224
224
  ..._filter,
@@ -232,7 +232,7 @@ function ComboboxList( { view, filter, onChangeView }: SearchWidgetProps ) {
232
232
  } ),
233
233
  ]
234
234
  : [
235
- ...view.filters,
235
+ ...( view.filters ?? [] ),
236
236
  {
237
237
  field: filter.field,
238
238
  operator: filter.operators[ 0 ],
@@ -7,39 +7,38 @@ import { CheckboxControl } from '@wordpress/components';
7
7
  /**
8
8
  * Internal dependencies
9
9
  */
10
- import type { Field, AnyItem } from './types';
10
+ import type { Field } from './types';
11
+ import type { SetSelection } from './private-types';
11
12
 
12
- interface SingleSelectionCheckboxProps< Item extends AnyItem > {
13
+ interface SingleSelectionCheckboxProps< Item > {
13
14
  selection: string[];
14
- onSelectionChange: ( selection: Item[] ) => void;
15
+ onSelectionChange: SetSelection;
15
16
  item: Item;
16
- data: Item[];
17
17
  getItemId: ( item: Item ) => string;
18
18
  primaryField?: Field< Item >;
19
19
  disabled: boolean;
20
20
  }
21
21
 
22
- export default function SingleSelectionCheckbox< Item extends AnyItem >( {
22
+ export default function SingleSelectionCheckbox< Item >( {
23
23
  selection,
24
24
  onSelectionChange,
25
25
  item,
26
- data,
27
26
  getItemId,
28
27
  primaryField,
29
28
  disabled,
30
29
  }: SingleSelectionCheckboxProps< Item > ) {
31
30
  const id = getItemId( item );
32
- const isSelected = ! disabled && selection.includes( id );
31
+ const checked = ! disabled && selection.includes( id );
33
32
  let selectionLabel;
34
33
  if ( primaryField?.getValue && item ) {
35
34
  // eslint-disable-next-line @wordpress/valid-sprintf
36
35
  selectionLabel = sprintf(
37
36
  /* translators: %s: item title. */
38
- isSelected ? __( 'Deselect item: %s' ) : __( 'Select item: %s' ),
37
+ checked ? __( 'Deselect item: %s' ) : __( 'Select item: %s' ),
39
38
  primaryField.getValue( { item } )
40
39
  );
41
40
  } else {
42
- selectionLabel = isSelected
41
+ selectionLabel = checked
43
42
  ? __( 'Select a new item' )
44
43
  : __( 'Deselect item' );
45
44
  }
@@ -49,31 +48,17 @@ export default function SingleSelectionCheckbox< Item extends AnyItem >( {
49
48
  __nextHasNoMarginBottom
50
49
  aria-label={ selectionLabel }
51
50
  aria-disabled={ disabled }
52
- checked={ isSelected }
51
+ checked={ checked }
53
52
  onChange={ () => {
54
53
  if ( disabled ) {
55
54
  return;
56
55
  }
57
56
 
58
- if ( ! isSelected ) {
59
- onSelectionChange(
60
- data.filter( ( _item ) => {
61
- const itemId = getItemId?.( _item );
62
- return (
63
- itemId === id || selection.includes( itemId )
64
- );
65
- } )
66
- );
67
- } else {
68
- onSelectionChange(
69
- data.filter( ( _item ) => {
70
- const itemId = getItemId?.( _item );
71
- return (
72
- itemId !== id && selection.includes( itemId )
73
- );
74
- } )
75
- );
76
- }
57
+ onSelectionChange(
58
+ selection.includes( id )
59
+ ? selection.filter( ( itemId ) => id !== itemId )
60
+ : [ ...selection, id ]
61
+ );
77
62
  } }
78
63
  />
79
64
  );
@@ -22,6 +22,7 @@ export const data = [
22
22
  image: 'https://live.staticflickr.com/5725/21726228300_51333bd62c_b.jpg',
23
23
  type: 'Not a planet',
24
24
  categories: [ 'Space', 'NASA' ],
25
+ satellites: 0,
25
26
  },
26
27
  {
27
28
  id: 2,
@@ -30,6 +31,7 @@ export const data = [
30
31
  image: 'https://live.staticflickr.com/5678/21911065441_92e2d44708_b.jpg',
31
32
  type: 'Not a planet',
32
33
  categories: [ 'Space' ],
34
+ satellites: 0,
33
35
  },
34
36
  {
35
37
  id: 3,
@@ -38,6 +40,7 @@ export const data = [
38
40
  image: 'https://live.staticflickr.com/742/21712365770_8f70a2c91e_b.jpg',
39
41
  type: 'Not a planet',
40
42
  categories: [ 'NASA' ],
43
+ satellites: 0,
41
44
  },
42
45
  {
43
46
  id: 4,
@@ -46,6 +49,7 @@ export const data = [
46
49
  image: 'https://live.staticflickr.com/5725/21726228300_51333bd62c_b.jpg',
47
50
  type: 'Ice giant',
48
51
  categories: [ 'Space', 'Planet', 'Solar system' ],
52
+ satellites: 14,
49
53
  },
50
54
  {
51
55
  id: 5,
@@ -54,6 +58,7 @@ export const data = [
54
58
  image: 'https://live.staticflickr.com/5725/21726228300_51333bd62c_b.jpg',
55
59
  type: 'Terrestrial',
56
60
  categories: [ 'Space', 'Planet', 'Solar system' ],
61
+ satellites: 0,
57
62
  },
58
63
  {
59
64
  id: 6,
@@ -62,6 +67,7 @@ export const data = [
62
67
  image: 'https://live.staticflickr.com/5725/21726228300_51333bd62c_b.jpg',
63
68
  type: 'Terrestrial',
64
69
  categories: [ 'Space', 'Planet', 'Solar system' ],
70
+ satellites: 0,
65
71
  },
66
72
  {
67
73
  id: 7,
@@ -70,6 +76,7 @@ export const data = [
70
76
  image: 'https://live.staticflickr.com/5725/21726228300_51333bd62c_b.jpg',
71
77
  type: 'Terrestrial',
72
78
  categories: [ 'Space', 'Planet', 'Solar system' ],
79
+ satellites: 1,
73
80
  },
74
81
  {
75
82
  id: 8,
@@ -78,6 +85,7 @@ export const data = [
78
85
  image: 'https://live.staticflickr.com/5725/21726228300_51333bd62c_b.jpg',
79
86
  type: 'Terrestrial',
80
87
  categories: [ 'Space', 'Planet', 'Solar system' ],
88
+ satellites: 2,
81
89
  },
82
90
  {
83
91
  id: 9,
@@ -86,6 +94,7 @@ export const data = [
86
94
  image: 'https://live.staticflickr.com/5725/21726228300_51333bd62c_b.jpg',
87
95
  type: 'Gas giant',
88
96
  categories: [ 'Space', 'Planet', 'Solar system' ],
97
+ satellites: 95,
89
98
  },
90
99
  {
91
100
  id: 10,
@@ -94,6 +103,7 @@ export const data = [
94
103
  image: 'https://live.staticflickr.com/5725/21726228300_51333bd62c_b.jpg',
95
104
  type: 'Gas giant',
96
105
  categories: [ 'Space', 'Planet', 'Solar system' ],
106
+ satellites: 146,
97
107
  },
98
108
  {
99
109
  id: 11,
@@ -102,6 +112,7 @@ export const data = [
102
112
  image: 'https://live.staticflickr.com/5725/21726228300_51333bd62c_b.jpg',
103
113
  type: 'Ice giant',
104
114
  categories: [ 'Space', 'Ice giant', 'Solar system' ],
115
+ satellites: 28,
105
116
  },
106
117
  ];
107
118
 
@@ -110,7 +121,7 @@ export const DEFAULT_VIEW = {
110
121
  search: '',
111
122
  page: 1,
112
123
  perPage: 10,
113
- hiddenFields: [ 'image', 'type' ],
124
+ fields: [ 'title', 'description', 'categories' ],
114
125
  layout: {},
115
126
  filters: [],
116
127
  };
@@ -178,6 +189,11 @@ export const fields = [
178
189
  { value: 'Gas giant', label: 'Gas giant' },
179
190
  ],
180
191
  },
192
+ {
193
+ header: 'Satellites',
194
+ id: 'satellites',
195
+ enableSorting: true,
196
+ },
181
197
  {
182
198
  header: 'Description',
183
199
  id: 'description',
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
- import { useState, useMemo, useCallback } from '@wordpress/element';
4
+ import { useState, useMemo } from '@wordpress/element';
5
5
 
6
6
  /**
7
7
  * Internal dependencies
@@ -17,36 +17,11 @@ const meta = {
17
17
  };
18
18
  export default meta;
19
19
 
20
- const defaultConfigPerViewType = {
21
- [ LAYOUT_TABLE ]: {
22
- primaryField: 'title',
23
- },
24
- [ LAYOUT_GRID ]: {
25
- mediaField: 'image',
26
- primaryField: 'title',
27
- },
28
- };
29
-
30
20
  export const Default = ( props ) => {
31
21
  const [ view, setView ] = useState( DEFAULT_VIEW );
32
22
  const { data: shownData, paginationInfo } = useMemo( () => {
33
23
  return filterSortAndPaginate( data, view, fields );
34
24
  }, [ view ] );
35
- const onChangeView = useCallback(
36
- ( newView ) => {
37
- if ( newView.type !== view.type ) {
38
- newView = {
39
- ...newView,
40
- layout: {
41
- ...defaultConfigPerViewType[ newView.type ],
42
- },
43
- };
44
- }
45
-
46
- setView( newView );
47
- },
48
- [ view.type, setView ]
49
- );
50
25
  return (
51
26
  <DataViews
52
27
  { ...props }
@@ -54,11 +29,23 @@ export const Default = ( props ) => {
54
29
  data={ shownData }
55
30
  view={ view }
56
31
  fields={ fields }
57
- onChangeView={ onChangeView }
32
+ onChangeView={ setView }
58
33
  />
59
34
  );
60
35
  };
61
36
  Default.args = {
62
37
  actions,
63
- supportedLayouts: [ LAYOUT_TABLE, LAYOUT_GRID ],
38
+ defaultLayouts: {
39
+ [ LAYOUT_TABLE ]: {
40
+ layout: {
41
+ primaryField: 'title',
42
+ },
43
+ },
44
+ [ LAYOUT_GRID ]: {
45
+ layout: {
46
+ mediaField: 'image',
47
+ primaryField: 'title',
48
+ },
49
+ },
50
+ },
64
51
  };
package/src/style.scss CHANGED
@@ -106,15 +106,6 @@
106
106
  gap: $grid-unit-05;
107
107
  }
108
108
 
109
- th,
110
- td {
111
- &:first-child,
112
- &:last-child {
113
- transition: padding ease-out 0.1s;
114
- @include reduce-motion("transition");
115
- }
116
- }
117
-
118
109
  td:first-child,
119
110
  th:first-child {
120
111
  padding-left: $grid-unit-60;
@@ -191,10 +182,14 @@
191
182
  box-shadow: inset 0 -#{$border-width} 0 $gray-100;
192
183
  padding-top: $grid-unit-10;
193
184
  padding-bottom: $grid-unit-10;
185
+ padding-left: $grid-unit-15;
194
186
  font-size: 11px;
195
187
  text-transform: uppercase;
196
188
  font-weight: 500;
197
- padding-left: $grid-unit-05;
189
+
190
+ &:has(.dataviews-view-table-header-button):not(:first-child) {
191
+ padding-left: $grid-unit-05;
192
+ }
198
193
  }
199
194
  }
200
195
  tbody {
@@ -259,7 +254,6 @@
259
254
  color: $gray-700;
260
255
  text-overflow: ellipsis;
261
256
  white-space: nowrap;
262
- display: block;
263
257
  width: 100%;
264
258
 
265
259
  a {
@@ -328,11 +322,6 @@
328
322
  .dataviews-view-grid__fields .dataviews-view-grid__field .dataviews-view-grid__field-value {
329
323
  color: $gray-900;
330
324
  }
331
-
332
- .page-pages-preview-field__button::after {
333
- box-shadow: inset 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color);
334
- background: rgba(var(--wp-admin-theme-color--rgb), 0.04);
335
- }
336
325
  }
337
326
  }
338
327
 
@@ -342,7 +331,6 @@
342
331
  aspect-ratio: 1/1;
343
332
  background-color: $gray-100;
344
333
  border-radius: $grid-unit-05;
345
- overflow: hidden;
346
334
  position: relative;
347
335
 
348
336
  img {
@@ -444,7 +432,7 @@
444
432
  &.is-hovered,
445
433
  &:focus-within {
446
434
  .dataviews-view-list__item-actions {
447
- padding-right: $grid-unit-40;
435
+ padding-right: $grid-unit-30;
448
436
 
449
437
  .components-button {
450
438
  opacity: 1;
@@ -559,7 +547,7 @@
559
547
  }
560
548
 
561
549
  .dataviews-view-list__field-value {
562
- line-height: $grid-unit-05 * 5;
550
+ line-height: $grid-unit-05 * 6;
563
551
  display: inline-flex;
564
552
  }
565
553
  }
@@ -756,10 +744,10 @@
756
744
  border-radius: $grid-unit-20;
757
745
  border: 1px solid transparent;
758
746
  cursor: pointer;
759
- padding: 0 $grid-unit-15;
760
- height: $grid-unit-40;
747
+ padding: $grid-unit-05 $grid-unit-15;
748
+ min-height: $grid-unit-40;
761
749
  background: $gray-100;
762
- color: $gray-700;
750
+ color: $gray-800;
763
751
  position: relative;
764
752
  display: flex;
765
753
  align-items: center;
@@ -233,7 +233,7 @@ describe( 'filters', () => {
233
233
  } );
234
234
 
235
235
  describe( 'sorting', () => {
236
- it( 'should sort', () => {
236
+ it( 'should sort by string', () => {
237
237
  const { data: result } = filterSortAndPaginate(
238
238
  data,
239
239
  {
@@ -252,6 +252,21 @@ describe( 'sorting', () => {
252
252
  expect( result[ 0 ].title ).toBe( 'Uranus' );
253
253
  expect( result[ 1 ].title ).toBe( 'Neptune' );
254
254
  } );
255
+
256
+ it( 'should sort by number', () => {
257
+ const { data: result } = filterSortAndPaginate(
258
+ data,
259
+ {
260
+ sort: { field: 'satellites', direction: 'desc' },
261
+ },
262
+ fields
263
+ );
264
+
265
+ expect( result ).toHaveLength( 11 );
266
+ expect( result[ 0 ].title ).toBe( 'Saturn' );
267
+ expect( result[ 1 ].title ).toBe( 'Jupiter' );
268
+ expect( result[ 2 ].title ).toBe( 'Uranus' );
269
+ } );
255
270
  } );
256
271
 
257
272
  describe( 'pagination', () => {
package/src/types.ts CHANGED
@@ -3,6 +3,11 @@
3
3
  */
4
4
  import type { ReactElement, ReactNode } from 'react';
5
5
 
6
+ /**
7
+ * Internal dependencies
8
+ */
9
+ import type { SetSelection } from './private-types';
10
+
6
11
  export type SortDirection = 'asc' | 'desc';
7
12
 
8
13
  /**
@@ -37,12 +42,19 @@ export type Operator =
37
42
  | 'isAll'
38
43
  | 'isNotAll';
39
44
 
40
- export type AnyItem = Record< string, any >;
45
+ export type ItemRecord = Record< string, unknown >;
46
+
47
+ export type FieldType = 'text';
41
48
 
42
49
  /**
43
50
  * A dataview field for a specific property of a data type.
44
51
  */
45
- export interface Field< Item extends AnyItem > {
52
+ export type Field< Item > = {
53
+ /**
54
+ * Type of the fields.
55
+ */
56
+ type?: FieldType;
57
+
46
58
  /**
47
59
  * The unique identifier of the field.
48
60
  */
@@ -54,10 +66,9 @@ export interface Field< Item extends AnyItem > {
54
66
  header?: string;
55
67
 
56
68
  /**
57
- * Callback used to retrieve the value of the field from the item.
58
- * Defaults to `item[ field.id ]`.
69
+ * Placeholder for the field.
59
70
  */
60
- getValue?: ( args: { item: Item } ) => any;
71
+ placeholder?: string;
61
72
 
62
73
  /**
63
74
  * Callback used to render the field. Defaults to `field.getValue`.
@@ -103,17 +114,41 @@ export interface Field< Item extends AnyItem > {
103
114
  * Filter config for the field.
104
115
  */
105
116
  filterBy?: FilterByConfig | undefined;
106
- }
107
-
108
- export type NormalizedField< Item extends AnyItem > = Field< Item > &
109
- Required< Pick< Field< Item >, 'header' | 'getValue' | 'render' > >;
117
+ } & ( Item extends ItemRecord
118
+ ? {
119
+ /**
120
+ * Callback used to retrieve the value of the field from the item.
121
+ * Defaults to `item[ field.id ]`.
122
+ */
123
+ getValue?: ( args: { item: Item } ) => any;
124
+ }
125
+ : {
126
+ /**
127
+ * Callback used to retrieve the value of the field from the item.
128
+ * Defaults to `item[ field.id ]`.
129
+ */
130
+ getValue: ( args: { item: Item } ) => any;
131
+ } );
132
+
133
+ export type NormalizedField< Item > = Field< Item > & {
134
+ header: string;
135
+ getValue: ( args: { item: Item } ) => any;
136
+ render: ( args: { item: Item } ) => ReactNode;
137
+ };
110
138
 
111
139
  /**
112
140
  * A collection of dataview fields for a data type.
113
141
  */
114
- export type Fields< Item extends AnyItem > = Field< Item >[];
142
+ export type Fields< Item > = Field< Item >[];
115
143
 
116
- export type Data< Item extends AnyItem > = Item[];
144
+ export type Data< Item > = Item[];
145
+
146
+ /**
147
+ * The form configuration.
148
+ */
149
+ export type Form = {
150
+ visibleFields?: string[];
151
+ };
117
152
 
118
153
  /**
119
154
  * The filters applied to the dataset.
@@ -186,7 +221,7 @@ interface ViewBase {
186
221
  /**
187
222
  * The filters to apply.
188
223
  */
189
- filters: Filter[];
224
+ filters?: Filter[];
190
225
 
191
226
  /**
192
227
  * The sorting configuration.
@@ -216,13 +251,13 @@ interface ViewBase {
216
251
  /**
217
252
  * The hidden fields.
218
253
  */
219
- hiddenFields: string[];
254
+ fields?: string[];
220
255
  }
221
256
 
222
257
  export interface ViewTable extends ViewBase {
223
258
  type: 'table';
224
259
 
225
- layout: {
260
+ layout?: {
226
261
  /**
227
262
  * The field to use as the primary field.
228
263
  */
@@ -238,7 +273,7 @@ export interface ViewTable extends ViewBase {
238
273
  export interface ViewList extends ViewBase {
239
274
  type: 'list';
240
275
 
241
- layout: {
276
+ layout?: {
242
277
  /**
243
278
  * The field to use as the primary field.
244
279
  */
@@ -254,7 +289,7 @@ export interface ViewList extends ViewBase {
254
289
  export interface ViewGrid extends ViewBase {
255
290
  type: 'grid';
256
291
 
257
- layout: {
292
+ layout?: {
258
293
  /**
259
294
  * The field to use as the primary field.
260
295
  */
@@ -279,7 +314,7 @@ export interface ViewGrid extends ViewBase {
279
314
 
280
315
  export type View = ViewList | ViewGrid | ViewTable;
281
316
 
282
- interface ActionBase< Item extends AnyItem > {
317
+ interface ActionBase< Item > {
283
318
  /**
284
319
  * The unique identifier of the action.
285
320
  */
@@ -325,8 +360,7 @@ interface ActionBase< Item extends AnyItem > {
325
360
  supportsBulk?: boolean;
326
361
  }
327
362
 
328
- export interface ActionModal< Item extends AnyItem >
329
- extends ActionBase< Item > {
363
+ export interface ActionModal< Item > extends ActionBase< Item > {
330
364
  /**
331
365
  * Modal to render when the action is triggered.
332
366
  */
@@ -351,8 +385,7 @@ export interface ActionModal< Item extends AnyItem >
351
385
  modalHeader?: string;
352
386
  }
353
387
 
354
- export interface ActionButton< Item extends AnyItem >
355
- extends ActionBase< AnyItem > {
388
+ export interface ActionButton< Item > extends ActionBase< Item > {
356
389
  /**
357
390
  * The callback to execute when the action is triggered.
358
391
  */
@@ -365,39 +398,40 @@ export interface ActionButton< Item extends AnyItem >
365
398
  ) => void;
366
399
  }
367
400
 
368
- export type Action< Item extends AnyItem > =
369
- | ActionModal< Item >
370
- | ActionButton< Item >;
401
+ export type Action< Item > = ActionModal< Item > | ActionButton< Item >;
371
402
 
372
- export interface ViewBaseProps< Item extends AnyItem > {
403
+ export interface ViewBaseProps< Item > {
373
404
  actions: Action< Item >[];
374
405
  data: Item[];
375
406
  fields: NormalizedField< Item >[];
376
407
  getItemId: ( item: Item ) => string;
377
408
  isLoading?: boolean;
378
- onChangeView( view: View ): void;
379
- onSelectionChange: ( items: Item[] ) => void;
409
+ onChangeView: ( view: View ) => void;
410
+ onSelectionChange: SetSelection;
380
411
  selection: string[];
381
412
  setOpenedFilter: ( fieldId: string ) => void;
382
413
  view: View;
383
414
  }
384
415
 
385
- export interface ViewTableProps< Item extends AnyItem >
386
- extends ViewBaseProps< Item > {
416
+ export interface ViewTableProps< Item > extends ViewBaseProps< Item > {
387
417
  view: ViewTable;
388
418
  }
389
419
 
390
- export interface ViewListProps< Item extends AnyItem >
391
- extends ViewBaseProps< Item > {
420
+ export interface ViewListProps< Item > extends ViewBaseProps< Item > {
392
421
  view: ViewList;
393
422
  }
394
423
 
395
- export interface ViewGridProps< Item extends AnyItem >
396
- extends ViewBaseProps< Item > {
424
+ export interface ViewGridProps< Item > extends ViewBaseProps< Item > {
397
425
  view: ViewGrid;
398
426
  }
399
427
 
400
- export type ViewProps< Item extends AnyItem > =
428
+ export type ViewProps< Item > =
401
429
  | ViewTableProps< Item >
402
430
  | ViewGridProps< Item >
403
431
  | ViewListProps< Item >;
432
+
433
+ export interface SupportedLayouts {
434
+ list?: Omit< ViewList, 'type' >;
435
+ grid?: Omit< ViewGrid, 'type' >;
436
+ table?: Omit< ViewTable, 'type' >;
437
+ }
package/src/utils.ts CHANGED
@@ -8,11 +8,9 @@ import {
8
8
  OPERATOR_IS_ANY,
9
9
  OPERATOR_IS_NONE,
10
10
  } from './constants';
11
- import type { AnyItem, NormalizedField } from './types';
11
+ import type { NormalizedField } from './types';
12
12
 
13
- export function sanitizeOperators< Item extends AnyItem >(
14
- field: NormalizedField< Item >
15
- ) {
13
+ export function sanitizeOperators< Item >( field: NormalizedField< Item > ) {
16
14
  let operators = field.filterBy?.operators;
17
15
 
18
16
  // Assign default values.