@wordpress/edit-site 5.21.0 → 5.21.1-next.f8d8eceb.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 (107) hide show
  1. package/build/components/actions/index.js +121 -0
  2. package/build/components/actions/index.js.map +1 -0
  3. package/build/components/block-editor/use-site-editor-settings.js +12 -4
  4. package/build/components/block-editor/use-site-editor-settings.js.map +1 -1
  5. package/build/components/dataviews/context.js +15 -0
  6. package/build/components/dataviews/context.js.map +1 -0
  7. package/build/components/dataviews/dataviews.js +10 -2
  8. package/build/components/dataviews/dataviews.js.map +1 -1
  9. package/build/components/dataviews/filters.js +30 -17
  10. package/build/components/dataviews/filters.js.map +1 -1
  11. package/build/components/dataviews/in-filter.js +5 -7
  12. package/build/components/dataviews/in-filter.js.map +1 -1
  13. package/build/components/dataviews/item-actions.js +62 -0
  14. package/build/components/dataviews/item-actions.js.map +1 -0
  15. package/build/components/dataviews/pagination.js +31 -50
  16. package/build/components/dataviews/pagination.js.map +1 -1
  17. package/build/components/dataviews/{text-filter.js → search.js} +10 -10
  18. package/build/components/dataviews/search.js.map +1 -0
  19. package/build/components/dataviews/view-grid.js +3 -3
  20. package/build/components/dataviews/view-grid.js.map +1 -1
  21. package/build/components/dataviews/view-list.js +2 -2
  22. package/build/components/dataviews/view-list.js.map +1 -1
  23. package/build/components/global-styles/font-library-modal/font-collection.js +1 -1
  24. package/build/components/global-styles/font-library-modal/font-collection.js.map +1 -1
  25. package/build/components/global-styles/screen-block.js +1 -8
  26. package/build/components/global-styles/screen-block.js.map +1 -1
  27. package/build/components/page-pages/default-views.js +60 -0
  28. package/build/components/page-pages/default-views.js.map +1 -0
  29. package/build/components/page-pages/index.js +73 -52
  30. package/build/components/page-pages/index.js.map +1 -1
  31. package/build/components/sidebar/index.js +3 -1
  32. package/build/components/sidebar/index.js.map +1 -1
  33. package/build/components/sidebar-dataviews/index.js +72 -0
  34. package/build/components/sidebar-dataviews/index.js.map +1 -0
  35. package/build/hooks/commands/use-edit-mode-commands.js +3 -2
  36. package/build/hooks/commands/use-edit-mode-commands.js.map +1 -1
  37. package/build-module/components/actions/index.js +108 -0
  38. package/build-module/components/actions/index.js.map +1 -0
  39. package/build-module/components/block-editor/use-site-editor-settings.js +12 -4
  40. package/build-module/components/block-editor/use-site-editor-settings.js.map +1 -1
  41. package/build-module/components/dataviews/context.js +7 -0
  42. package/build-module/components/dataviews/context.js.map +1 -0
  43. package/build-module/components/dataviews/dataviews.js +10 -2
  44. package/build-module/components/dataviews/dataviews.js.map +1 -1
  45. package/build-module/components/dataviews/filters.js +30 -17
  46. package/build-module/components/dataviews/filters.js.map +1 -1
  47. package/build-module/components/dataviews/in-filter.js +5 -7
  48. package/build-module/components/dataviews/in-filter.js.map +1 -1
  49. package/build-module/components/dataviews/item-actions.js +55 -0
  50. package/build-module/components/dataviews/item-actions.js.map +1 -0
  51. package/build-module/components/dataviews/pagination.js +32 -51
  52. package/build-module/components/dataviews/pagination.js.map +1 -1
  53. package/build-module/components/dataviews/{text-filter.js → search.js} +9 -9
  54. package/build-module/components/dataviews/search.js.map +1 -0
  55. package/build-module/components/dataviews/view-grid.js +3 -3
  56. package/build-module/components/dataviews/view-grid.js.map +1 -1
  57. package/build-module/components/dataviews/view-list.js +2 -2
  58. package/build-module/components/dataviews/view-list.js.map +1 -1
  59. package/build-module/components/global-styles/font-library-modal/font-collection.js +1 -1
  60. package/build-module/components/global-styles/font-library-modal/font-collection.js.map +1 -1
  61. package/build-module/components/global-styles/screen-block.js +1 -8
  62. package/build-module/components/global-styles/screen-block.js.map +1 -1
  63. package/build-module/components/page-pages/default-views.js +53 -0
  64. package/build-module/components/page-pages/default-views.js.map +1 -0
  65. package/build-module/components/page-pages/index.js +71 -52
  66. package/build-module/components/page-pages/index.js.map +1 -1
  67. package/build-module/components/sidebar/index.js +3 -1
  68. package/build-module/components/sidebar/index.js.map +1 -1
  69. package/build-module/components/sidebar-dataviews/index.js +64 -0
  70. package/build-module/components/sidebar-dataviews/index.js.map +1 -0
  71. package/build-module/hooks/commands/use-edit-mode-commands.js +4 -3
  72. package/build-module/hooks/commands/use-edit-mode-commands.js.map +1 -1
  73. package/build-style/style-rtl.css +9 -5
  74. package/build-style/style.css +9 -5
  75. package/package.json +40 -40
  76. package/src/components/actions/index.js +123 -0
  77. package/src/components/block-editor/use-site-editor-settings.js +21 -13
  78. package/src/components/dataviews/README.md +134 -47
  79. package/src/components/dataviews/context.js +7 -0
  80. package/src/components/dataviews/dataviews.js +11 -1
  81. package/src/components/dataviews/filters.js +35 -17
  82. package/src/components/dataviews/in-filter.js +5 -7
  83. package/src/components/dataviews/item-actions.js +69 -0
  84. package/src/components/dataviews/pagination.js +53 -74
  85. package/src/components/dataviews/{text-filter.js → search.js} +7 -7
  86. package/src/components/dataviews/style.scss +10 -5
  87. package/src/components/dataviews/view-grid.js +7 -2
  88. package/src/components/dataviews/view-list.js +2 -2
  89. package/src/components/global-styles/font-library-modal/font-collection.js +1 -1
  90. package/src/components/global-styles/screen-block.js +1 -7
  91. package/src/components/page-pages/default-views.js +58 -0
  92. package/src/components/page-pages/index.js +85 -60
  93. package/src/components/sidebar/index.js +2 -0
  94. package/src/components/sidebar-dataviews/index.js +65 -0
  95. package/src/hooks/commands/use-edit-mode-commands.js +3 -1
  96. package/build/components/actions/trash-post.js +0 -48
  97. package/build/components/actions/trash-post.js.map +0 -1
  98. package/build/components/dataviews/field-actions.js +0 -30
  99. package/build/components/dataviews/field-actions.js.map +0 -1
  100. package/build/components/dataviews/text-filter.js.map +0 -1
  101. package/build-module/components/actions/trash-post.js +0 -41
  102. package/build-module/components/actions/trash-post.js.map +0 -1
  103. package/build-module/components/dataviews/field-actions.js +0 -22
  104. package/build-module/components/dataviews/field-actions.js.map +0 -1
  105. package/build-module/components/dataviews/text-filter.js.map +0 -1
  106. package/src/components/actions/trash-post.js +0 -55
  107. package/src/components/dataviews/field-actions.js +0 -28
@@ -1,107 +1,194 @@
1
1
  # DataView
2
2
 
3
- This file aims to document the main APIs related to the DataView component.
3
+ This file documents the DataViews UI component, which provides an API to render datasets using different view types (table, grid, etc.).
4
+
5
+ ```js
6
+ <DataViews
7
+ data={ pages }
8
+ isLoading= { isLoadingPages }
9
+ view={ view }
10
+ onChangeView={ onChangeView }
11
+ fields={ fields }
12
+ actions={ [ trashPostAction ] }
13
+ paginationInfo={ { totalItems, totalPages } }
14
+ />
15
+ ```
16
+
17
+ ## Data
18
+
19
+ The dataset to work with, represented as a one-dimensional array.
20
+
21
+ Example:
22
+
23
+ ```js
24
+ [
25
+ { id: 1, title: "Title", ... },
26
+ { ... }
27
+ ]
28
+ ```
4
29
 
5
30
  ## View
6
31
 
7
- The view is responsible for configuring how the dataset is visible to the user. For example:
32
+ The view object configures how the dataset is visible to the user.
33
+
34
+ Example:
8
35
 
9
36
  ```js
10
37
  {
11
38
  type: 'list',
12
- page: 1,
13
39
  perPage: 5,
40
+ page: 1,
14
41
  sort: {
15
42
  field: 'date',
16
43
  direction: 'desc',
17
44
  },
45
+ search: '',
18
46
  filters: {
19
- search: '',
20
47
  author: 2,
21
48
  status: 'publish, draft'
22
49
  },
23
- visibleFilters: [ 'search', 'author', 'status' ],
50
+ visibleFilters: [ 'author', 'status' ],
24
51
  hiddenFields: [ 'date', 'featured-image' ],
25
52
  layout: {},
26
53
  }
27
54
  ```
28
55
 
29
- - `type`: one of `list` or `grid`.
30
- - `page`: the current page.
31
- - `perPage`: number of records per page.
32
- - `sort.field`: field used for sorting.
33
- - `sort.direction`: one of `asc` or `desc`.
34
- - `filters`: the filters applied to the dataset.
56
+ - `type`: view type, one of `list` or `grid`.
57
+ - `perPage`: number of records to show per page.
58
+ - `page`: the page that is visible.
59
+ - `sort.field`: field used for sorting the dataset.
60
+ - `sort.direction`: the direction to use for sorting, one of `asc` or `desc`.
61
+ - `search`: the text search applied to the dataset.
62
+ - `filters`: the filters applied to the dataset. See filters section.
35
63
  - `visibleFilters`: the `id` of the filters that are visible in the UI.
36
64
  - `hiddenFields`: the `id` of the fields that are hidden in the UI.
37
65
  - `layout`: ...
38
66
 
39
- The view configuration is used to retrieve the corresponding entity that holds the dataset:
67
+ Note that it's the consumer's responsibility to provide the data and make sure the dataset corresponds to the view's config (sort, pagination, filters, etc.).
68
+
69
+ Example:
40
70
 
41
71
  ```js
42
- const {
43
- records: pages,
44
- isLoading: isLoadingPages,
45
- totalItems,
46
- totalPages
47
- } = useEntityRecords( 'postType', 'page', {
48
- per_page: view.perPage,
49
- page: view.page,
50
- order: view.sort?.direction,
51
- orderby: view.sort?.field
52
- ...view.filters
53
- } );
72
+ function MyCustomPageList() {
73
+ const [ view, setView ] = useState( {
74
+ type: 'list',
75
+ page: 1,
76
+ "...": "..."
77
+ } );
78
+
79
+ const queryArgs = useMemo(
80
+ () => ( {
81
+ per_page: view.perPage,
82
+ page: view.page,
83
+ order: view.sort?.direction,
84
+ orderby: view.sort?.field
85
+ search: view.search,
86
+ ...view.filters
87
+ } ),
88
+ [ view ]
89
+ );
90
+
91
+ const {
92
+ records
93
+ } = useEntityRecords( 'postType', 'page', queryArgs );
94
+
95
+ return (
96
+ <DataViews
97
+ data={ records }
98
+ view={ view }
99
+ onChangeView={ setView }
100
+ "..."
101
+ />
102
+ );
103
+ }
54
104
  ```
55
105
 
56
106
  ## Fields
57
107
 
58
- The fields describe the dataset. For example:
108
+ The fields describe the visible items for each record in the dataset.
109
+
110
+ Example:
59
111
 
60
112
  ```js
61
113
  [
114
+ {
115
+ id: 'date',
116
+ header: __( 'Date' ),
117
+ getValue: ( { item } ) => item.date,
118
+ render: ( { item } ) => {
119
+ return (
120
+ <time>{ getFormattedDate( item.date ) }</time>
121
+ );
122
+ }
123
+ },
62
124
  {
63
125
  id: 'author',
64
126
  header: __( 'Author' ),
65
127
  getValue: ( { item } ) => item.author,
66
- render: ( {item} ) => {
128
+ render: ( { item } ) => {
67
129
  return (
68
130
  <a href="...">{ item.author }</a>
69
131
  );
70
132
  },
71
133
  elements: [
72
- { value: 1, label: 'admin' }
73
- { value: 2, label: 'user' }
134
+ { value: 1, label: 'Admin' }
135
+ { value: 2, label: 'User' }
74
136
  ]
75
- filters: [
76
- { id: 'author', type: 'enumeration' },
77
- { id: 'author_search', type: 'search' }
78
- ],
79
- },
137
+ filters: [ 'enumeration' ],
138
+ }
80
139
  ]
81
140
  ```
82
141
 
83
142
  - `id`: identifier for the field. Unique.
84
- - `header`: the field name for the UI.
143
+ - `header`: the field's name to be shown in the UI.
85
144
  - `getValue`: function that returns the value of the field.
86
145
  - `render`: function that renders the field.
87
- - `elements`: a set of valid values for the field.
88
- - `filters`: what filters are available. A filter is an object with `id` and `type` as properties:
89
- - `id`: unique identifier for the filter. Matches the entity query param.
90
- - `type`: the type of filter. One of `search` or `enumeration`.
91
-
146
+ - `elements`: the set of valid values for the field's value.
147
+ - `filters`: what filters are available for the user to use. See filters section.
92
148
 
93
- ## DataViews
149
+ ## Filters
94
150
 
95
- The UI component responsible for rendering the dataset.
151
+ Filters describe the conditions a record should match to be listed as part of the dataset. Filters are provided per field.
96
152
 
97
153
  ```js
154
+ const field = [
155
+ {
156
+ id: 'author',
157
+ filters: [ 'enumeration' ],
158
+ }
159
+ ];
160
+
98
161
  <DataViews
99
- data={ pages }
100
- isLoading= { isLoadingPages }
101
162
  fields={ fields }
102
- view={ view }
103
- onChangeView={ onChangeView }
104
- actions={ [ trashPostAction ] }
105
- paginationInfo={ { totalItems, totalPages } }
106
163
  />
107
164
  ```
165
+
166
+ A filter is an object that may contain the following properties:
167
+
168
+ - `id`: unique identifier for the filter. Matches the entity query param. Field filters may omit it, in which case the field's `id` will be used.
169
+ - `name`: nice looking name for the filter. Field filters may omit it, in which case the field's `header` will be used.
170
+ - `type`: the type of filter. Only `enumeration` is supported at the moment.
171
+ - `elements`: for filters of type `enumeration`, the list of options to show. A one-dimensional array of object with value/label keys, as in `[ { value: 1, label: "Value name" } ]`.
172
+ - `value`: what's serialized into the view's filters.
173
+ - `label`: nice-looking name for users.
174
+ - `resetValue`: for filters of type `enumeration`, this is the value for the reset option. If none is provided, `''` will be used.
175
+ - `resetLabel`: for filters of type `enumeration`, this is the label for the reset option. If none is provided, `All` will be used.
176
+
177
+ As a convenience, field's filter can provide abbreviated versions for the filter. All of following examples result in the same filter:
178
+
179
+ ```js
180
+ const field = [
181
+ {
182
+ id: 'author',
183
+ header: __( 'Author' ),
184
+ elements: authors,
185
+ filters: [
186
+ 'enumeration',
187
+ { type: 'enumeration' },
188
+ { id: 'author', type: 'enumeration' },
189
+ { id: 'author', type: 'enumeration', name: __( 'Author' ) },
190
+ { id: 'author', type: 'enumeration', name: __( 'Author' ), elements: authors },
191
+ ],
192
+ }
193
+ ];
194
+ ```
@@ -0,0 +1,7 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { createContext } from '@wordpress/element';
5
+
6
+ const DataviewsContext = createContext( {} );
7
+ export default DataviewsContext;
@@ -14,12 +14,15 @@ import ViewList from './view-list';
14
14
  import Pagination from './pagination';
15
15
  import ViewActions from './view-actions';
16
16
  import Filters from './filters';
17
+ import Search from './search';
17
18
  import { ViewGrid } from './view-grid';
18
19
 
19
20
  export default function DataViews( {
20
21
  view,
21
22
  onChangeView,
22
23
  fields,
24
+ search = true,
25
+ searchLabel = undefined,
23
26
  actions,
24
27
  data,
25
28
  isLoading = false,
@@ -34,9 +37,16 @@ export default function DataViews( {
34
37
  }, [ fields ] );
35
38
  return (
36
39
  <div className="dataviews-wrapper">
37
- <VStack spacing={ 4 }>
40
+ <VStack spacing={ 4 } justify="flex-start">
38
41
  <HStack>
39
42
  <HStack justify="start">
43
+ { search && (
44
+ <Search
45
+ label={ searchLabel }
46
+ view={ view }
47
+ onChangeView={ onChangeView }
48
+ />
49
+ ) }
40
50
  <Filters
41
51
  fields={ fields }
42
52
  view={ view }
@@ -6,45 +6,63 @@ import { __ } from '@wordpress/i18n';
6
6
  /**
7
7
  * Internal dependencies
8
8
  */
9
- import TextFilter from './text-filter';
10
9
  import InFilter from './in-filter';
11
10
 
12
11
  export default function Filters( { fields, view, onChangeView } ) {
13
- const filters = {};
12
+ const filterIndex = {};
14
13
  fields.forEach( ( field ) => {
15
14
  if ( ! field.filters ) {
16
15
  return;
17
16
  }
18
17
 
19
- field.filters.forEach( ( f ) => {
20
- filters[ f.id ] = { type: f.type };
18
+ field.filters.forEach( ( filter ) => {
19
+ let id = field.id;
20
+ if ( 'string' === typeof filter ) {
21
+ filterIndex[ id ] = {
22
+ id,
23
+ name: field.header,
24
+ type: filter,
25
+ };
26
+ }
27
+
28
+ if ( 'object' === typeof filter ) {
29
+ id = filter.id || field.id;
30
+ filterIndex[ id ] = {
31
+ id,
32
+ name: filter.name || field.header,
33
+ type: filter.type,
34
+ };
35
+ }
36
+
37
+ if ( 'enumeration' === filterIndex[ id ]?.type ) {
38
+ const elements = [
39
+ {
40
+ value: filter.resetValue || '',
41
+ label: filter.resetLabel || __( 'All' ),
42
+ },
43
+ ...( field.elements || [] ),
44
+ ];
45
+ filterIndex[ id ] = {
46
+ ...filterIndex[ id ],
47
+ elements,
48
+ };
49
+ }
21
50
  } );
22
51
  } );
23
52
 
24
53
  return (
25
54
  view.visibleFilters?.map( ( filterName ) => {
26
- const filter = filters[ filterName ];
55
+ const filter = filterIndex[ filterName ];
27
56
 
28
57
  if ( ! filter ) {
29
58
  return null;
30
59
  }
31
60
 
32
- if ( filter.type === 'search' ) {
33
- return (
34
- <TextFilter
35
- key={ filterName }
36
- id={ filterName }
37
- view={ view }
38
- onChangeView={ onChangeView }
39
- />
40
- );
41
- }
42
61
  if ( filter.type === 'enumeration' ) {
43
62
  return (
44
63
  <InFilter
45
64
  key={ filterName }
46
- id={ filterName }
47
- fields={ fields }
65
+ filter={ filter }
48
66
  view={ view }
49
67
  onChangeView={ onChangeView }
50
68
  />
@@ -14,21 +14,19 @@ import { unlock } from '../../lock-unlock';
14
14
 
15
15
  const { cleanEmptyObject } = unlock( blockEditorPrivateApis );
16
16
 
17
- export default ( { id, fields, view, onChangeView } ) => {
18
- const field = fields.find( ( f ) => f.id === id );
19
-
17
+ export default ( { filter, view, onChangeView } ) => {
20
18
  return (
21
19
  <SelectControl
22
- value={ view.filters[ id ] }
20
+ value={ view.filters[ filter.id ] }
23
21
  prefix={
24
22
  <InputControlPrefixWrapper
25
23
  as="span"
26
24
  className="dataviews__select-control-prefix"
27
25
  >
28
- { field.header + ':' }
26
+ { filter.name + ':' }
29
27
  </InputControlPrefixWrapper>
30
28
  }
31
- options={ field?.elements || [] }
29
+ options={ filter.elements }
32
30
  onChange={ ( value ) => {
33
31
  if ( value === '' ) {
34
32
  value = undefined;
@@ -38,7 +36,7 @@ export default ( { id, fields, view, onChangeView } ) => {
38
36
  ...currentView,
39
37
  filters: cleanEmptyObject( {
40
38
  ...currentView.filters,
41
- [ id ]: value,
39
+ [ filter.id ]: value,
42
40
  } ),
43
41
  } ) );
44
42
  } }
@@ -0,0 +1,69 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import {
5
+ DropdownMenu,
6
+ MenuGroup,
7
+ MenuItem,
8
+ Button,
9
+ __experimentalHStack as HStack,
10
+ } from '@wordpress/components';
11
+ import { __ } from '@wordpress/i18n';
12
+ import { useMemo } from '@wordpress/element';
13
+ import { moreVertical } from '@wordpress/icons';
14
+
15
+ export default function ItemActions( { item, actions } ) {
16
+ const { primaryActions, secondaryActions } = useMemo( () => {
17
+ return actions.reduce(
18
+ ( accumulator, action ) => {
19
+ // If an action is eligible for all items, doesn't need
20
+ // to provide the `isEligible` function.
21
+ if ( action.isEligible && ! action.isEligible( item ) ) {
22
+ return accumulator;
23
+ }
24
+ if ( action.isPrimary && !! action.icon ) {
25
+ accumulator.primaryActions.push( action );
26
+ } else {
27
+ accumulator.secondaryActions.push( action );
28
+ }
29
+ return accumulator;
30
+ },
31
+ { primaryActions: [], secondaryActions: [] }
32
+ );
33
+ }, [ actions, item ] );
34
+ if ( ! primaryActions.length && ! secondaryActions.length ) {
35
+ return null;
36
+ }
37
+ return (
38
+ <HStack justify="flex-end">
39
+ { !! primaryActions.length &&
40
+ primaryActions.map( ( action ) => (
41
+ <Button
42
+ label={ action.label }
43
+ key={ action.id }
44
+ icon={ action.icon }
45
+ onClick={ () => action.perform( item ) }
46
+ isDestructive={ action.isDestructive }
47
+ size="compact"
48
+ />
49
+ ) ) }
50
+ { !! secondaryActions.length && (
51
+ <DropdownMenu icon={ moreVertical } label={ __( 'Actions' ) }>
52
+ { () => (
53
+ <MenuGroup>
54
+ { secondaryActions.map( ( action ) => (
55
+ <MenuItem
56
+ key={ action.id }
57
+ onClick={ () => action.perform( item ) }
58
+ isDestructive={ action.isDestructive }
59
+ >
60
+ { action.label }
61
+ </MenuItem>
62
+ ) ) }
63
+ </MenuGroup>
64
+ ) }
65
+ </DropdownMenu>
66
+ ) }
67
+ </HStack>
68
+ );
69
+ }
@@ -6,45 +6,11 @@ import {
6
6
  __experimentalHStack as HStack,
7
7
  __experimentalText as Text,
8
8
  __experimentalNumberControl as NumberControl,
9
- __experimentalInputControlPrefixWrapper as InputControlPrefixWrapper,
10
- SelectControl,
11
9
  } from '@wordpress/components';
12
10
  import { createInterpolateElement } from '@wordpress/element';
13
11
  import { sprintf, __, _x, _n } from '@wordpress/i18n';
12
+ import { chevronRight, chevronLeft, previous, next } from '@wordpress/icons';
14
13
 
15
- const PAGE_SIZE_VALUES = [ 5, 20, 50 ];
16
- function PageSizeControl( { view, onChangeView } ) {
17
- const label = __( 'Rows per page:' );
18
- return (
19
- <SelectControl
20
- __nextHasNoMarginBottom
21
- label={ label }
22
- hideLabelFromVision
23
- // TODO: This should probably use a label based on the wanted design
24
- // and we could remove InputControlPrefixWrapper usage.
25
- prefix={
26
- <InputControlPrefixWrapper
27
- as="span"
28
- className="dataviews__select-control-prefix"
29
- >
30
- { label }
31
- </InputControlPrefixWrapper>
32
- }
33
- value={ view.perPage }
34
- options={ PAGE_SIZE_VALUES.map( ( pageSize ) => ( {
35
- value: pageSize,
36
- label: pageSize,
37
- } ) ) }
38
- onChange={ ( value ) =>
39
- onChangeView( { ...view, perPage: value, page: 1 } )
40
- }
41
- />
42
- );
43
- }
44
-
45
- // For now this is copied from the patterns list Pagination component, because
46
- // the datatable pagination starts from index zero(`0`). Eventually all lists will be
47
- // using this one.
48
14
  function Pagination( {
49
15
  view,
50
16
  onChangeView,
@@ -71,29 +37,37 @@ function Pagination( {
71
37
  }
72
38
  </Text>
73
39
  { !! totalItems && (
74
- <HStack expanded={ false } spacing={ 1 }>
75
- <Button
76
- variant="tertiary"
77
- onClick={ () => onChangeView( { ...view, page: 1 } ) }
78
- disabled={ view.page === 1 }
79
- aria-label={ __( 'First page' ) }
80
- >
81
- «
82
- </Button>
83
- <Button
84
- variant="tertiary"
85
- onClick={ () =>
86
- onChangeView( { ...view, page: view.page - 1 } )
87
- }
88
- disabled={ view.page === 1 }
89
- aria-label={ __( 'Previous page' ) }
90
- >
91
-
92
- </Button>
40
+ <HStack expanded={ false } spacing={ 3 }>
93
41
  <HStack
94
42
  justify="flex-start"
95
43
  expanded={ false }
96
44
  spacing={ 1 }
45
+ >
46
+ <Button
47
+ onClick={ () =>
48
+ onChangeView( { ...view, page: 1 } )
49
+ }
50
+ disabled={ view.page === 1 }
51
+ label={ __( 'First page' ) }
52
+ icon={ previous }
53
+ showTooltip
54
+ size="compact"
55
+ />
56
+ <Button
57
+ onClick={ () =>
58
+ onChangeView( { ...view, page: view.page - 1 } )
59
+ }
60
+ disabled={ view.page === 1 }
61
+ label={ __( 'Previous page' ) }
62
+ icon={ chevronLeft }
63
+ showTooltip
64
+ size="compact"
65
+ />
66
+ </HStack>
67
+ <HStack
68
+ justify="flex-start"
69
+ expanded={ false }
70
+ spacing={ 2 }
97
71
  >
98
72
  { createInterpolateElement(
99
73
  sprintf(
@@ -130,29 +104,34 @@ function Pagination( {
130
104
  }
131
105
  ) }
132
106
  </HStack>
133
- <Button
134
- variant="tertiary"
135
- onClick={ () =>
136
- onChangeView( { ...view, page: view.page + 1 } )
137
- }
138
- disabled={ view.page >= totalPages }
139
- aria-label={ __( 'Next page' ) }
140
- >
141
-
142
- </Button>
143
- <Button
144
- variant="tertiary"
145
- onClick={ () =>
146
- onChangeView( { ...view, page: totalPages } )
147
- }
148
- disabled={ view.page >= totalPages }
149
- aria-label={ __( 'Last page' ) }
107
+ <HStack
108
+ justify="flex-start"
109
+ expanded={ false }
110
+ spacing={ 1 }
150
111
  >
151
- »
152
- </Button>
112
+ <Button
113
+ onClick={ () =>
114
+ onChangeView( { ...view, page: view.page + 1 } )
115
+ }
116
+ disabled={ view.page >= totalPages }
117
+ label={ __( 'Next page' ) }
118
+ icon={ chevronRight }
119
+ showTooltip
120
+ size="compact"
121
+ />
122
+ <Button
123
+ onClick={ () =>
124
+ onChangeView( { ...view, page: totalPages } )
125
+ }
126
+ disabled={ view.page >= totalPages }
127
+ label={ __( 'Last page' ) }
128
+ icon={ next }
129
+ showTooltip
130
+ size="compact"
131
+ />
132
+ </HStack>
153
133
  </HStack>
154
134
  ) }
155
- <PageSizeControl view={ view } onChangeView={ onChangeView } />
156
135
  </HStack>
157
136
  );
158
137
  }
@@ -10,10 +10,13 @@ import { SearchControl } from '@wordpress/components';
10
10
  */
11
11
  import useDebouncedInput from '../../utils/use-debounced-input';
12
12
 
13
- export default function TextFilter( { id, view, onChangeView } ) {
13
+ export default function Search( { label, view, onChangeView } ) {
14
14
  const [ search, setSearch, debouncedSearch ] = useDebouncedInput(
15
- view.filters[ id ]
15
+ view.search
16
16
  );
17
+ useEffect( () => {
18
+ setSearch( view.search );
19
+ }, [ view ] );
17
20
  const onChangeViewRef = useRef( onChangeView );
18
21
  useEffect( () => {
19
22
  onChangeViewRef.current = onChangeView;
@@ -22,13 +25,10 @@ export default function TextFilter( { id, view, onChangeView } ) {
22
25
  onChangeViewRef.current( ( currentView ) => ( {
23
26
  ...currentView,
24
27
  page: 1,
25
- filters: {
26
- ...currentView.filters,
27
- [ id ]: debouncedSearch,
28
- },
28
+ search: debouncedSearch,
29
29
  } ) );
30
30
  }, [ debouncedSearch ] );
31
- const searchLabel = __( 'Filter list' );
31
+ const searchLabel = label || __( 'Filter list' );
32
32
  return (
33
33
  <SearchControl
34
34
  onChange={ setSearch }
@@ -1,6 +1,16 @@
1
1
  .dataviews-wrapper {
2
2
  width: 100%;
3
+ height: 100%;
4
+ overflow: auto;
3
5
  padding: $grid-unit-40;
6
+
7
+ > div {
8
+ min-height: 100%;
9
+ }
10
+ }
11
+
12
+ .dataviews-pagination {
13
+ margin-top: auto;
4
14
  }
5
15
 
6
16
  .dataviews-list-view {
@@ -30,11 +40,6 @@
30
40
  }
31
41
  }
32
42
 
33
- .dataviews__select-control-prefix {
34
- color: $gray-700;
35
- text-wrap: nowrap;
36
- }
37
-
38
43
  .dataviews-view-grid__media {
39
44
  width: 100%;
40
45
  min-height: 200px;