@wordpress/dataviews 0.2.0 → 0.3.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 (87) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/LICENSE.md +1 -1
  3. package/README.md +30 -6
  4. package/build/add-filter.js +109 -49
  5. package/build/add-filter.js.map +1 -1
  6. package/build/constants.js +24 -2
  7. package/build/constants.js.map +1 -1
  8. package/build/dataviews.js +12 -9
  9. package/build/dataviews.js.map +1 -1
  10. package/build/dropdown-menu-helper.js +72 -0
  11. package/build/dropdown-menu-helper.js.map +1 -0
  12. package/build/filter-summary.js +43 -54
  13. package/build/filter-summary.js.map +1 -1
  14. package/build/filters.js +27 -17
  15. package/build/filters.js.map +1 -1
  16. package/build/index.js +13 -0
  17. package/build/index.js.map +1 -1
  18. package/build/item-actions.js +12 -12
  19. package/build/item-actions.js.map +1 -1
  20. package/build/pagination.js +31 -65
  21. package/build/pagination.js.map +1 -1
  22. package/build/reset-filters.js +8 -8
  23. package/build/reset-filters.js.map +1 -1
  24. package/build/search.js +8 -6
  25. package/build/search.js.map +1 -1
  26. package/build/utils.js +71 -0
  27. package/build/utils.js.map +1 -0
  28. package/build/view-actions.js +72 -95
  29. package/build/view-actions.js.map +1 -1
  30. package/build/view-grid.js +4 -6
  31. package/build/view-grid.js.map +1 -1
  32. package/build/view-list.js +26 -13
  33. package/build/view-list.js.map +1 -1
  34. package/build/view-table.js +153 -154
  35. package/build/view-table.js.map +1 -1
  36. package/build-module/add-filter.js +113 -53
  37. package/build-module/add-filter.js.map +1 -1
  38. package/build-module/constants.js +20 -0
  39. package/build-module/constants.js.map +1 -1
  40. package/build-module/dataviews.js +13 -10
  41. package/build-module/dataviews.js.map +1 -1
  42. package/build-module/dropdown-menu-helper.js +64 -0
  43. package/build-module/dropdown-menu-helper.js.map +1 -0
  44. package/build-module/filter-summary.js +45 -56
  45. package/build-module/filter-summary.js.map +1 -1
  46. package/build-module/filters.js +26 -17
  47. package/build-module/filters.js.map +1 -1
  48. package/build-module/index.js +1 -0
  49. package/build-module/index.js.map +1 -1
  50. package/build-module/item-actions.js +12 -12
  51. package/build-module/item-actions.js.map +1 -1
  52. package/build-module/pagination.js +35 -69
  53. package/build-module/pagination.js.map +1 -1
  54. package/build-module/reset-filters.js +6 -6
  55. package/build-module/reset-filters.js.map +1 -1
  56. package/build-module/search.js +7 -6
  57. package/build-module/search.js.map +1 -1
  58. package/build-module/utils.js +63 -0
  59. package/build-module/utils.js.map +1 -0
  60. package/build-module/view-actions.js +73 -97
  61. package/build-module/view-actions.js.map +1 -1
  62. package/build-module/view-grid.js +4 -6
  63. package/build-module/view-grid.js.map +1 -1
  64. package/build-module/view-list.js +27 -14
  65. package/build-module/view-list.js.map +1 -1
  66. package/build-module/view-table.js +156 -157
  67. package/build-module/view-table.js.map +1 -1
  68. package/build-style/style-rtl.css +180 -70
  69. package/build-style/style.css +180 -70
  70. package/package.json +11 -10
  71. package/src/add-filter.js +227 -68
  72. package/src/constants.js +16 -0
  73. package/src/dataviews.js +19 -12
  74. package/src/dropdown-menu-helper.js +61 -0
  75. package/src/filter-summary.js +70 -103
  76. package/src/filters.js +41 -24
  77. package/src/index.js +1 -0
  78. package/src/item-actions.js +30 -25
  79. package/src/pagination.js +75 -123
  80. package/src/reset-filters.js +5 -5
  81. package/src/search.js +8 -6
  82. package/src/style.scss +182 -48
  83. package/src/utils.js +51 -0
  84. package/src/view-actions.js +113 -114
  85. package/src/view-grid.js +4 -4
  86. package/src/view-list.js +42 -28
  87. package/src/view-table.js +280 -238
@@ -6,23 +6,24 @@ import {
6
6
  privateApis as componentsPrivateApis,
7
7
  Icon,
8
8
  } from '@wordpress/components';
9
- import { chevronDown, chevronRightSmall, check } from '@wordpress/icons';
9
+ import { chevronDown } from '@wordpress/icons';
10
10
  import { __, sprintf } from '@wordpress/i18n';
11
11
  import { Children, Fragment } from '@wordpress/element';
12
12
 
13
13
  /**
14
14
  * Internal dependencies
15
15
  */
16
- import { OPERATOR_IN, OPERATOR_NOT_IN } from './constants';
16
+ import { OPERATOR_IN, OPERATOR_NOT_IN, OPERATORS } from './constants';
17
17
  import { unlock } from './lock-unlock';
18
+ import { DropdownMenuRadioItemCustom } from './dropdown-menu-helper';
18
19
 
19
20
  const {
20
21
  DropdownMenuV2: DropdownMenu,
21
22
  DropdownMenuGroupV2: DropdownMenuGroup,
22
23
  DropdownMenuItemV2: DropdownMenuItem,
23
24
  DropdownMenuSeparatorV2: DropdownMenuSeparator,
24
- DropdownSubMenuV2: DropdownSubMenu,
25
- DropdownSubMenuTriggerV2: DropdownSubMenuTrigger,
25
+ DropdownMenuItemLabelV2: DropdownMenuItemLabel,
26
+ DropdownMenuItemHelpTextV2: DropdownMenuItemHelpText,
26
27
  } = unlock( componentsPrivateApis );
27
28
 
28
29
  const FilterText = ( { activeElement, filterInView, filter } ) => {
@@ -74,9 +75,13 @@ function WithSeparators( { children } ) {
74
75
 
75
76
  export default function FilterSummary( { filter, view, onChangeView } ) {
76
77
  const filterInView = view.filters.find( ( f ) => f.field === filter.field );
78
+ const otherFilters = view.filters.filter(
79
+ ( f ) => f.field !== filter.field
80
+ );
77
81
  const activeElement = filter.elements.find(
78
82
  ( element ) => element.value === filterInView?.value
79
83
  );
84
+ const activeOperator = filterInView?.operator || filter.operators[ 0 ];
80
85
 
81
86
  return (
82
87
  <DropdownMenu
@@ -95,125 +100,87 @@ export default function FilterSummary( { filter, view, onChangeView } ) {
95
100
  <WithSeparators>
96
101
  <DropdownMenuGroup>
97
102
  { filter.elements.map( ( element ) => {
103
+ const isActive = activeElement?.value === element.value;
98
104
  return (
99
- <DropdownMenuItem
105
+ <DropdownMenuRadioItemCustom
100
106
  key={ element.value }
101
- role="menuitemradio"
102
- aria-checked={
103
- activeElement?.value === element.value
104
- }
105
- prefix={
106
- activeElement?.value === element.value && (
107
- <Icon icon={ check } />
108
- )
109
- }
110
- onSelect={ () =>
111
- onChangeView( ( currentView ) => ( {
112
- ...currentView,
107
+ name={ `filter-summary-${ filter.field }` }
108
+ value={ element.value }
109
+ checked={ isActive }
110
+ onClick={ () =>
111
+ onChangeView( {
112
+ ...view,
113
113
  page: 1,
114
114
  filters: [
115
- ...view.filters.filter(
116
- ( f ) =>
117
- f.field !== filter.field
118
- ),
115
+ ...otherFilters,
119
116
  {
120
117
  field: filter.field,
121
- operator:
122
- filterInView?.operator ||
123
- filter.operators[ 0 ],
124
- value:
125
- activeElement?.value ===
126
- element.value
127
- ? undefined
128
- : element.value,
118
+ operator: activeOperator,
119
+ value: isActive
120
+ ? undefined
121
+ : element.value,
129
122
  },
130
123
  ],
131
- } ) )
124
+ } )
132
125
  }
133
126
  >
134
- { element.label }
135
- </DropdownMenuItem>
127
+ <DropdownMenuItemLabel>
128
+ { element.label }
129
+ </DropdownMenuItemLabel>
130
+ { !! element.description && (
131
+ <DropdownMenuItemHelpText>
132
+ { element.description }
133
+ </DropdownMenuItemHelpText>
134
+ ) }
135
+ </DropdownMenuRadioItemCustom>
136
136
  );
137
137
  } ) }
138
138
  </DropdownMenuGroup>
139
139
  { filter.operators.length > 1 && (
140
- <DropdownSubMenu
140
+ <DropdownMenu
141
141
  trigger={
142
- <DropdownSubMenuTrigger
142
+ <DropdownMenuItem
143
143
  suffix={
144
- <>
145
- { filterInView.operator === OPERATOR_IN
146
- ? __( 'Is' )
147
- : __( 'Is not' ) }
148
- <Icon icon={ chevronRightSmall } />{ ' ' }
149
- </>
144
+ <span aria-hidden="true">
145
+ { OPERATORS[ activeOperator ]?.label }
146
+ </span>
150
147
  }
151
148
  >
152
- { __( 'Conditions' ) }
153
- </DropdownSubMenuTrigger>
149
+ <DropdownMenuItemLabel>
150
+ { __( 'Conditions' ) }
151
+ </DropdownMenuItemLabel>
152
+ </DropdownMenuItem>
154
153
  }
155
154
  >
156
- <DropdownMenuItem
157
- key="in-filter"
158
- role="menuitemradio"
159
- aria-checked={
160
- filterInView?.operator === OPERATOR_IN
161
- }
162
- prefix={
163
- filterInView?.operator === OPERATOR_IN && (
164
- <Icon icon={ check } />
165
- )
166
- }
167
- onSelect={ () =>
168
- onChangeView( ( currentView ) => ( {
169
- ...currentView,
170
- page: 1,
171
- filters: [
172
- ...view.filters.filter(
173
- ( f ) => f.field !== filter.field
174
- ),
175
- {
176
- field: filter.field,
177
- operator: OPERATOR_IN,
178
- value: filterInView?.value,
179
- },
180
- ],
181
- } ) )
182
- }
183
- >
184
- { __( 'Is' ) }
185
- </DropdownMenuItem>
186
- <DropdownMenuItem
187
- key="not-in-filter"
188
- role="menuitemradio"
189
- aria-checked={
190
- filterInView?.operator === OPERATOR_NOT_IN
191
- }
192
- prefix={
193
- filterInView?.operator === OPERATOR_NOT_IN && (
194
- <Icon icon={ check } />
195
- )
196
- }
197
- onSelect={ () =>
198
- onChangeView( ( currentView ) => ( {
199
- ...currentView,
200
- page: 1,
201
- filters: [
202
- ...view.filters.filter(
203
- ( f ) => f.field !== filter.field
204
- ),
205
- {
206
- field: filter.field,
207
- operator: OPERATOR_NOT_IN,
208
- value: filterInView?.value,
209
- },
210
- ],
211
- } ) )
212
- }
213
- >
214
- { __( 'Is not' ) }
215
- </DropdownMenuItem>
216
- </DropdownSubMenu>
155
+ { Object.entries( OPERATORS ).map(
156
+ ( [ operator, { label, key } ] ) => (
157
+ <DropdownMenuRadioItemCustom
158
+ key={ key }
159
+ name={ `filter-summary-${ filter.field }-conditions` }
160
+ value={ operator }
161
+ checked={ activeOperator === operator }
162
+ onChange={ ( e ) => {
163
+ onChangeView( {
164
+ ...view,
165
+ page: 1,
166
+ filters: [
167
+ ...otherFilters,
168
+ {
169
+ field: filter.field,
170
+ operator: e.target.value,
171
+ value: filterInView?.value,
172
+ },
173
+ ],
174
+ } );
175
+ } }
176
+ >
177
+ <DropdownMenuItemLabel>
178
+ { label }
179
+ </DropdownMenuItemLabel>
180
+ </DropdownMenuRadioItemCustom>
181
+ )
182
+ ) }
183
+ </DropdownMenu>
217
184
  ) }
218
185
  </WithSeparators>
219
186
  </DropdownMenu>
package/src/filters.js CHANGED
@@ -1,12 +1,22 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { memo } from '@wordpress/element';
5
+
1
6
  /**
2
7
  * Internal dependencies
3
8
  */
4
9
  import FilterSummary from './filter-summary';
5
10
  import AddFilter from './add-filter';
6
11
  import ResetFilters from './reset-filters';
7
- import { ENUMERATION_TYPE, OPERATOR_IN, OPERATOR_NOT_IN } from './constants';
12
+ import {
13
+ ENUMERATION_TYPE,
14
+ OPERATOR_IN,
15
+ OPERATOR_NOT_IN,
16
+ LAYOUT_LIST,
17
+ } from './constants';
8
18
 
9
- const operatorsFromField = ( field ) => {
19
+ const sanitizeOperators = ( field ) => {
10
20
  let operators = field.filterBy?.operators;
11
21
  if ( ! operators || ! Array.isArray( operators ) ) {
12
22
  operators = [ OPERATOR_IN, OPERATOR_NOT_IN ];
@@ -16,24 +26,27 @@ const operatorsFromField = ( field ) => {
16
26
  );
17
27
  };
18
28
 
19
- export default function Filters( { fields, view, onChangeView } ) {
29
+ const Filters = memo( function Filters( { fields, view, onChangeView } ) {
20
30
  const filters = [];
21
31
  fields.forEach( ( field ) => {
22
32
  if ( ! field.type ) {
23
33
  return;
24
34
  }
25
35
 
26
- const operators = operatorsFromField( field );
36
+ const operators = sanitizeOperators( field );
27
37
  if ( operators.length === 0 ) {
28
38
  return;
29
39
  }
30
40
 
31
41
  switch ( field.type ) {
32
42
  case ENUMERATION_TYPE:
43
+ if ( ! field.elements?.length ) {
44
+ return;
45
+ }
33
46
  filters.push( {
34
47
  field: field.id,
35
48
  name: field.header,
36
- elements: field.elements || [],
49
+ elements: field.elements,
37
50
  operators,
38
51
  isVisible: view.filters.some(
39
52
  ( f ) =>
@@ -46,31 +59,33 @@ export default function Filters( { fields, view, onChangeView } ) {
46
59
  }
47
60
  } );
48
61
 
49
- const filterComponents = filters.map( ( filter ) => {
50
- if ( ! filter.isVisible ) {
51
- return null;
52
- }
53
-
54
- return (
55
- <FilterSummary
56
- key={ filter.field + '.' + filter.operator }
57
- filter={ filter }
58
- view={ view }
59
- onChangeView={ onChangeView }
60
- />
61
- );
62
- } );
63
-
64
- filterComponents.push(
62
+ const addFilter = (
65
63
  <AddFilter
66
64
  key="add-filter"
67
- fields={ fields }
65
+ filters={ filters }
68
66
  view={ view }
69
67
  onChangeView={ onChangeView }
70
68
  />
71
69
  );
70
+ const filterComponents = [
71
+ addFilter,
72
+ ...filters.map( ( filter ) => {
73
+ if ( ! filter.isVisible || view.type === LAYOUT_LIST ) {
74
+ return null;
75
+ }
76
+
77
+ return (
78
+ <FilterSummary
79
+ key={ filter.field }
80
+ filter={ filter }
81
+ view={ view }
82
+ onChangeView={ onChangeView }
83
+ />
84
+ );
85
+ } ),
86
+ ];
72
87
 
73
- if ( filterComponents.length > 1 ) {
88
+ if ( filterComponents.length > 1 && view.type !== LAYOUT_LIST ) {
74
89
  filterComponents.push(
75
90
  <ResetFilters
76
91
  key="reset-filters"
@@ -81,4 +96,6 @@ export default function Filters( { fields, view, onChangeView } ) {
81
96
  }
82
97
 
83
98
  return filterComponents;
84
- }
99
+ } );
100
+
101
+ export default Filters;
package/src/index.js CHANGED
@@ -1,2 +1,3 @@
1
1
  export { default as DataViews } from './dataviews';
2
+ export { sortByTextFields, getPaginationResults } from './utils';
2
3
  export { VIEW_LAYOUTS } from './constants';
@@ -17,10 +17,11 @@ import { moreVertical } from '@wordpress/icons';
17
17
  import { unlock } from './lock-unlock';
18
18
 
19
19
  const {
20
- DropdownMenuV2Ariakit: DropdownMenu,
21
- DropdownMenuGroupV2Ariakit: DropdownMenuGroup,
22
- DropdownMenuItemV2Ariakit: DropdownMenuItem,
23
- DropdownMenuItemLabelV2Ariakit: DropdownMenuItemLabel,
20
+ DropdownMenuV2: DropdownMenu,
21
+ DropdownMenuGroupV2: DropdownMenuGroup,
22
+ DropdownMenuItemV2: DropdownMenuItem,
23
+ DropdownMenuItemLabelV2: DropdownMenuItemLabel,
24
+ kebabCase,
24
25
  } = unlock( componentsPrivateApis );
25
26
 
26
27
  function ButtonTrigger( { action, onClick } ) {
@@ -58,12 +59,17 @@ function ActionWithModal( { action, item, ActionTrigger } ) {
58
59
  <ActionTrigger { ...actionTriggerProps } />
59
60
  { isModalOpen && (
60
61
  <Modal
61
- title={ ! hideModalHeader && action.label }
62
+ title={
63
+ ( ! hideModalHeader && action.modalHeader ) ||
64
+ action.label
65
+ }
62
66
  __experimentalHideHeader={ !! hideModalHeader }
63
67
  onRequestClose={ () => {
64
68
  setIsModalOpen( false );
65
69
  } }
66
- overlayClassName="dataviews-action-modal"
70
+ overlayClassName={ `dataviews-action-modal dataviews-action-modal__${ kebabCase(
71
+ action.id
72
+ ) }` }
67
73
  >
68
74
  <RenderModal
69
75
  item={ item }
@@ -120,9 +126,6 @@ export default function ItemActions( { item, actions, isCompact } ) {
120
126
  { primaryActions: [], secondaryActions: [] }
121
127
  );
122
128
  }, [ actions, item ] );
123
- if ( ! primaryActions.length && ! secondaryActions.length ) {
124
- return null;
125
- }
126
129
  if ( isCompact ) {
127
130
  return (
128
131
  <CompactItemActions
@@ -161,23 +164,22 @@ export default function ItemActions( { item, actions, isCompact } ) {
161
164
  />
162
165
  );
163
166
  } ) }
164
- { !! secondaryActions.length && (
165
- <DropdownMenu
166
- trigger={
167
- <Button
168
- size="compact"
169
- icon={ moreVertical }
170
- label={ __( 'Actions' ) }
171
- />
172
- }
173
- placement="bottom-end"
174
- >
175
- <ActionsDropdownMenuGroup
176
- actions={ secondaryActions }
177
- item={ item }
167
+ <DropdownMenu
168
+ trigger={
169
+ <Button
170
+ size="compact"
171
+ icon={ moreVertical }
172
+ label={ __( 'Actions' ) }
173
+ disabled={ ! secondaryActions.length }
178
174
  />
179
- </DropdownMenu>
180
- ) }
175
+ }
176
+ placement="bottom-end"
177
+ >
178
+ <ActionsDropdownMenuGroup
179
+ actions={ secondaryActions }
180
+ item={ item }
181
+ />
182
+ </DropdownMenu>
181
183
  </HStack>
182
184
  );
183
185
  }
@@ -190,6 +192,9 @@ function CompactItemActions( { item, primaryActions, secondaryActions } ) {
190
192
  size="compact"
191
193
  icon={ moreVertical }
192
194
  label={ __( 'Actions' ) }
195
+ disabled={
196
+ ! primaryActions.length && ! secondaryActions.length
197
+ }
193
198
  />
194
199
  }
195
200
  placement="bottom-end"
package/src/pagination.js CHANGED
@@ -4,14 +4,13 @@
4
4
  import {
5
5
  Button,
6
6
  __experimentalHStack as HStack,
7
- __experimentalText as Text,
8
- __experimentalNumberControl as NumberControl,
7
+ SelectControl,
9
8
  } from '@wordpress/components';
10
- import { createInterpolateElement } from '@wordpress/element';
11
- import { sprintf, __, _x, _n } from '@wordpress/i18n';
12
- import { chevronRight, chevronLeft, previous, next } from '@wordpress/icons';
9
+ import { createInterpolateElement, memo } from '@wordpress/element';
10
+ import { sprintf, __, _x } from '@wordpress/i18n';
11
+ import { chevronRight, chevronLeft } from '@wordpress/icons';
13
12
 
14
- function Pagination( {
13
+ const Pagination = memo( function Pagination( {
15
14
  view,
16
15
  onChangeView,
17
16
  paginationInfo: { totalItems = 0, totalPages },
@@ -20,125 +19,78 @@ function Pagination( {
20
19
  return null;
21
20
  }
22
21
  return (
23
- <HStack
24
- expanded={ false }
25
- spacing={ 3 }
26
- justify="space-between"
27
- className="dataviews-pagination"
28
- >
29
- <Text variant="muted">
30
- {
31
- // translators: %s: Total number of entries.
32
- sprintf(
33
- // translators: %s: Total number of entries.
34
- _n( '%s item', '%s items', totalItems ),
35
- totalItems
36
- )
37
- }
38
- </Text>
39
- { !! totalItems && totalPages !== 1 && (
40
- <HStack expanded={ false } spacing={ 3 }>
41
- <HStack
42
- justify="flex-start"
43
- expanded={ false }
44
- spacing={ 1 }
45
- >
46
- <Button
47
- onClick={ () =>
48
- onChangeView( { ...view, page: 1 } )
49
- }
50
- disabled={ view.page === 1 }
51
- __experimentalIsFocusable
52
- label={ __( 'First page' ) }
53
- icon={ previous }
54
- showTooltip
55
- size="compact"
56
- />
57
- <Button
58
- onClick={ () =>
59
- onChangeView( { ...view, page: view.page - 1 } )
60
- }
61
- disabled={ view.page === 1 }
62
- __experimentalIsFocusable
63
- label={ __( 'Previous page' ) }
64
- icon={ chevronLeft }
65
- showTooltip
66
- size="compact"
67
- />
68
- </HStack>
69
- <HStack
70
- justify="flex-start"
71
- expanded={ false }
72
- spacing={ 2 }
73
- >
74
- { createInterpolateElement(
75
- sprintf(
76
- // translators: %1$s: Current page number, %2$s: Total number of pages.
77
- _x( '<CurrenPageControl /> of %2$s', 'paging' ),
78
- view.page,
79
- totalPages
22
+ !! totalItems &&
23
+ totalPages !== 1 && (
24
+ <HStack
25
+ expanded={ false }
26
+ spacing={ 6 }
27
+ justify="end"
28
+ className="dataviews-pagination"
29
+ >
30
+ <HStack justify="flex-start" expanded={ false } spacing={ 2 }>
31
+ { createInterpolateElement(
32
+ sprintf(
33
+ // translators: %1$s: Current page number, %2$s: Total number of pages.
34
+ _x(
35
+ 'Page <CurrenPageControl /> of %2$s',
36
+ 'paging'
80
37
  ),
81
- {
82
- CurrenPageControl: (
83
- <NumberControl
84
- aria-label={ __( 'Current page' ) }
85
- min={ 1 }
86
- max={ totalPages }
87
- onChange={ ( value ) => {
88
- const _value = +value;
89
- if (
90
- ! _value ||
91
- _value < 1 ||
92
- _value > totalPages
93
- ) {
94
- return;
95
- }
96
- onChangeView( {
97
- ...view,
98
- page: _value,
99
- } );
100
- } }
101
- step="1"
102
- value={ view.page }
103
- isDragEnabled={ false }
104
- spinControls="none"
105
- />
106
- ),
107
- }
108
- ) }
109
- </HStack>
110
- <HStack
111
- justify="flex-start"
112
- expanded={ false }
113
- spacing={ 1 }
114
- >
115
- <Button
116
- onClick={ () =>
117
- onChangeView( { ...view, page: view.page + 1 } )
118
- }
119
- disabled={ view.page >= totalPages }
120
- __experimentalIsFocusable
121
- label={ __( 'Next page' ) }
122
- icon={ chevronRight }
123
- showTooltip
124
- size="compact"
125
- />
126
- <Button
127
- onClick={ () =>
128
- onChangeView( { ...view, page: totalPages } )
129
- }
130
- disabled={ view.page >= totalPages }
131
- __experimentalIsFocusable
132
- label={ __( 'Last page' ) }
133
- icon={ next }
134
- showTooltip
135
- size="compact"
136
- />
137
- </HStack>
38
+ view.page,
39
+ totalPages
40
+ ),
41
+ {
42
+ CurrenPageControl: (
43
+ <SelectControl
44
+ aria-label={ __( 'Current page' ) }
45
+ value={ view.page }
46
+ options={ Array.from(
47
+ Array( totalPages )
48
+ ).map( ( _, i ) => {
49
+ const page = i + 1;
50
+ return { value: page, label: page };
51
+ } ) }
52
+ onChange={ ( newValue ) => {
53
+ onChangeView( {
54
+ ...view,
55
+ page: +newValue,
56
+ } );
57
+ } }
58
+ size={ 'compact' }
59
+ __nextHasNoMarginBottom
60
+ />
61
+ ),
62
+ }
63
+ ) }
64
+ </HStack>
65
+ <HStack expanded={ false } spacing={ 1 }>
66
+ <Button
67
+ onClick={ () =>
68
+ onChangeView( { ...view, page: view.page - 1 } )
69
+ }
70
+ disabled={ view.page === 1 }
71
+ __experimentalIsFocusable
72
+ label={ __( 'Previous page' ) }
73
+ icon={ chevronLeft }
74
+ showTooltip
75
+ size="compact"
76
+ tooltipPosition="top"
77
+ />
78
+ <Button
79
+ onClick={ () =>
80
+ onChangeView( { ...view, page: view.page + 1 } )
81
+ }
82
+ disabled={ view.page >= totalPages }
83
+ __experimentalIsFocusable
84
+ label={ __( 'Next page' ) }
85
+ icon={ chevronRight }
86
+ showTooltip
87
+ size="compact"
88
+ tooltipPosition="top"
89
+ />
138
90
  </HStack>
139
- ) }
140
- </HStack>
91
+ </HStack>
92
+ )
141
93
  );
142
- }
94
+ } );
143
95
 
144
96
  export default Pagination;
@@ -4,7 +4,7 @@
4
4
  import { Button } from '@wordpress/components';
5
5
  import { __ } from '@wordpress/i18n';
6
6
 
7
- export default ( { view, onChangeView } ) => {
7
+ export default function ResetFilter( { view, onChangeView } ) {
8
8
  return (
9
9
  <Button
10
10
  disabled={ view.search === '' && view.filters?.length === 0 }
@@ -12,15 +12,15 @@ export default ( { view, onChangeView } ) => {
12
12
  size="compact"
13
13
  variant="tertiary"
14
14
  onClick={ () => {
15
- onChangeView( ( currentView ) => ( {
16
- ...currentView,
15
+ onChangeView( {
16
+ ...view,
17
17
  page: 1,
18
18
  search: '',
19
19
  filters: [],
20
- } ) );
20
+ } );
21
21
  } }
22
22
  >
23
23
  { __( 'Reset filters' ) }
24
24
  </Button>
25
25
  );
26
- };
26
+ }