@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
@@ -15,12 +15,13 @@ import {
15
15
  import { __ } from '@wordpress/i18n';
16
16
  import { useMemo, useState } from '@wordpress/element';
17
17
  import { moreVertical } from '@wordpress/icons';
18
+ import { useRegistry } from '@wordpress/data';
18
19
 
19
20
  /**
20
21
  * Internal dependencies
21
22
  */
22
23
  import { unlock } from './lock-unlock';
23
- import type { Action, ActionModal as ActionModalType, AnyItem } from './types';
24
+ import type { Action, ActionModal as ActionModalType } from './types';
24
25
 
25
26
  const {
26
27
  DropdownMenuV2: DropdownMenu,
@@ -30,42 +31,41 @@ const {
30
31
  kebabCase,
31
32
  } = unlock( componentsPrivateApis );
32
33
 
33
- export interface ActionTriggerProps< Item extends AnyItem > {
34
+ export interface ActionTriggerProps< Item > {
34
35
  action: Action< Item >;
35
36
  onClick: MouseEventHandler;
36
37
  isBusy?: boolean;
37
38
  items: Item[];
38
39
  }
39
40
 
40
- interface ActionModalProps< Item extends AnyItem > {
41
+ interface ActionModalProps< Item > {
41
42
  action: ActionModalType< Item >;
42
43
  items: Item[];
43
44
  closeModal?: () => void;
44
45
  }
45
46
 
46
- interface ActionWithModalProps< Item extends AnyItem >
47
- extends ActionModalProps< Item > {
47
+ interface ActionWithModalProps< Item > extends ActionModalProps< Item > {
48
48
  ActionTrigger: ( props: ActionTriggerProps< Item > ) => ReactElement;
49
49
  isBusy?: boolean;
50
50
  }
51
51
 
52
- interface ActionsDropdownMenuGroupProps< Item extends AnyItem > {
52
+ interface ActionsDropdownMenuGroupProps< Item > {
53
53
  actions: Action< Item >[];
54
54
  item: Item;
55
55
  }
56
56
 
57
- interface ItemActionsProps< Item extends AnyItem > {
57
+ interface ItemActionsProps< Item > {
58
58
  item: Item;
59
59
  actions: Action< Item >[];
60
60
  isCompact?: boolean;
61
61
  }
62
62
 
63
- interface CompactItemActionsProps< Item extends AnyItem > {
63
+ interface CompactItemActionsProps< Item > {
64
64
  item: Item;
65
65
  actions: Action< Item >[];
66
66
  }
67
67
 
68
- function ButtonTrigger< Item extends AnyItem >( {
68
+ function ButtonTrigger< Item >( {
69
69
  action,
70
70
  onClick,
71
71
  items,
@@ -83,7 +83,7 @@ function ButtonTrigger< Item extends AnyItem >( {
83
83
  );
84
84
  }
85
85
 
86
- function DropdownMenuItemTrigger< Item extends AnyItem >( {
86
+ function DropdownMenuItemTrigger< Item >( {
87
87
  action,
88
88
  onClick,
89
89
  items,
@@ -100,7 +100,7 @@ function DropdownMenuItemTrigger< Item extends AnyItem >( {
100
100
  );
101
101
  }
102
102
 
103
- export function ActionModal< Item extends AnyItem >( {
103
+ export function ActionModal< Item >( {
104
104
  action,
105
105
  items,
106
106
  closeModal,
@@ -112,21 +112,18 @@ export function ActionModal< Item extends AnyItem >( {
112
112
  title={ action.modalHeader || label }
113
113
  __experimentalHideHeader={ !! action.hideModalHeader }
114
114
  onRequestClose={ closeModal ?? ( () => {} ) }
115
+ focusOnMount="firstContentElement"
116
+ size="small"
115
117
  overlayClassName={ `dataviews-action-modal dataviews-action-modal__${ kebabCase(
116
118
  action.id
117
119
  ) }` }
118
120
  >
119
- <action.RenderModal
120
- items={ items }
121
- closeModal={ closeModal }
122
- onActionStart={ action.onActionStart }
123
- onActionPerformed={ action.onActionPerformed }
124
- />
121
+ <action.RenderModal items={ items } closeModal={ closeModal } />
125
122
  </Modal>
126
123
  );
127
124
  }
128
125
 
129
- export function ActionWithModal< Item extends AnyItem >( {
126
+ export function ActionWithModal< Item >( {
130
127
  action,
131
128
  items,
132
129
  ActionTrigger,
@@ -155,10 +152,11 @@ export function ActionWithModal< Item extends AnyItem >( {
155
152
  );
156
153
  }
157
154
 
158
- export function ActionsDropdownMenuGroup< Item extends AnyItem >( {
155
+ export function ActionsDropdownMenuGroup< Item >( {
159
156
  actions,
160
157
  item,
161
158
  }: ActionsDropdownMenuGroupProps< Item > ) {
159
+ const registry = useRegistry();
162
160
  return (
163
161
  <DropdownMenuGroup>
164
162
  { actions.map( ( action ) => {
@@ -176,7 +174,9 @@ export function ActionsDropdownMenuGroup< Item extends AnyItem >( {
176
174
  <DropdownMenuItemTrigger
177
175
  key={ action.id }
178
176
  action={ action }
179
- onClick={ () => action.callback( [ item ] ) }
177
+ onClick={ () => {
178
+ action.callback( [ item ], { registry } );
179
+ } }
180
180
  items={ [ item ] }
181
181
  />
182
182
  );
@@ -185,11 +185,12 @@ export function ActionsDropdownMenuGroup< Item extends AnyItem >( {
185
185
  );
186
186
  }
187
187
 
188
- export default function ItemActions< Item extends AnyItem >( {
188
+ export default function ItemActions< Item >( {
189
189
  item,
190
190
  actions,
191
191
  isCompact,
192
192
  }: ItemActionsProps< Item > ) {
193
+ const registry = useRegistry();
193
194
  const { primaryActions, eligibleActions } = useMemo( () => {
194
195
  // If an action is eligible for all items, doesn't need
195
196
  // to provide the `isEligible` function.
@@ -233,7 +234,9 @@ export default function ItemActions< Item extends AnyItem >( {
233
234
  <ButtonTrigger
234
235
  key={ action.id }
235
236
  action={ action }
236
- onClick={ () => action.callback( [ item ] ) }
237
+ onClick={ () => {
238
+ action.callback( [ item ], { registry } );
239
+ } }
237
240
  items={ [ item ] }
238
241
  />
239
242
  );
@@ -243,7 +246,7 @@ export default function ItemActions< Item extends AnyItem >( {
243
246
  );
244
247
  }
245
248
 
246
- function CompactItemActions< Item extends AnyItem >( {
249
+ function CompactItemActions< Item >( {
247
250
  item,
248
251
  actions,
249
252
  }: CompactItemActionsProps< Item > ) {
@@ -254,7 +257,7 @@ function CompactItemActions< Item extends AnyItem >( {
254
257
  size="compact"
255
258
  icon={ moreVertical }
256
259
  label={ __( 'Actions' ) }
257
- __experimentalIsFocusable
260
+ accessibleWhenDisabled
258
261
  disabled={ ! actions.length }
259
262
  className="dataviews-all-actions-button"
260
263
  />
@@ -5,6 +5,6 @@ import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/pri
5
5
 
6
6
  export const { lock, unlock } =
7
7
  __dangerousOptInToUnstableAPIsOnlyForCoreModules(
8
- 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.',
8
+ 'I acknowledge private features are not for use in themes or plugins and doing so will break in the next version of WordPress.',
9
9
  '@wordpress/dataviews'
10
10
  );
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Internal dependencies
3
3
  */
4
- import type { Field, AnyItem, NormalizedField } from './types';
4
+ import type { Field, NormalizedField, ItemRecord } from './types';
5
5
 
6
6
  /**
7
7
  * Apply default values and normalize the fields config.
@@ -9,11 +9,13 @@ import type { Field, AnyItem, NormalizedField } from './types';
9
9
  * @param fields Fields config.
10
10
  * @return Normalized fields config.
11
11
  */
12
- export function normalizeFields< Item extends AnyItem >(
12
+ export function normalizeFields< Item >(
13
13
  fields: Field< Item >[]
14
14
  ): NormalizedField< Item >[] {
15
15
  return fields.map( ( field ) => {
16
- const getValue = field.getValue || ( ( { item } ) => item[ field.id ] );
16
+ const getValue =
17
+ field.getValue ||
18
+ ( ( { item }: { item: ItemRecord } ) => item[ field.id ] );
17
19
 
18
20
  return {
19
21
  ...field,
@@ -90,7 +90,7 @@ const Pagination = memo( function Pagination( {
90
90
  } )
91
91
  }
92
92
  disabled={ currentPage === 1 }
93
- __experimentalIsFocusable
93
+ accessibleWhenDisabled
94
94
  label={ __( 'Previous page' ) }
95
95
  icon={ chevronLeft }
96
96
  showTooltip
@@ -102,7 +102,7 @@ const Pagination = memo( function Pagination( {
102
102
  onChangeView( { ...view, page: currentPage + 1 } )
103
103
  }
104
104
  disabled={ currentPage >= totalPages }
105
- __experimentalIsFocusable
105
+ accessibleWhenDisabled
106
106
  label={ __( 'Next page' ) }
107
107
  icon={ chevronRight }
108
108
  showTooltip
@@ -0,0 +1,2 @@
1
+ export type SelectionOrUpdater = string[] | ( ( prev: string[] ) => string[] );
2
+ export type SetSelection = ( selection: SelectionOrUpdater ) => void;
@@ -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 = 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', () => {