@wordpress/dataviews 1.2.0 → 2.0.1
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.
- package/CHANGELOG.md +16 -0
- package/README.md +33 -30
- package/build/add-filter.js +30 -22
- package/build/add-filter.js.map +1 -1
- package/build/bulk-actions-toolbar.js +74 -69
- package/build/bulk-actions-toolbar.js.map +1 -1
- package/build/bulk-actions.js +69 -56
- package/build/bulk-actions.js.map +1 -1
- package/build/constants.js +17 -10
- package/build/constants.js.map +1 -1
- package/build/dataviews.js +63 -56
- package/build/dataviews.js.map +1 -1
- package/build/filter-summary.js +105 -95
- package/build/filter-summary.js.map +1 -1
- package/build/filters.js +18 -17
- package/build/filters.js.map +1 -1
- package/build/index.js.map +1 -1
- package/build/item-actions.js +79 -65
- package/build/item-actions.js.map +1 -1
- package/build/layouts.js.map +1 -1
- package/build/pagination.js +60 -57
- package/build/pagination.js.map +1 -1
- package/build/reset-filters.js +9 -4
- package/build/reset-filters.js.map +1 -1
- package/build/search-widget.js +108 -89
- package/build/search-widget.js.map +1 -1
- package/build/search.js +13 -6
- package/build/search.js.map +1 -1
- package/build/single-selection-checkbox.js +2 -2
- package/build/single-selection-checkbox.js.map +1 -1
- package/build/types.js.map +1 -1
- package/build/utils.js +3 -15
- package/build/utils.js.map +1 -1
- package/build/view-actions.js +168 -120
- package/build/view-actions.js.map +1 -1
- package/build/view-grid.js +113 -99
- package/build/view-grid.js.map +1 -1
- package/build/view-list.js +154 -132
- package/build/view-list.js.map +1 -1
- package/build/view-table.js +220 -192
- package/build/view-table.js.map +1 -1
- package/build-module/add-filter.js +30 -22
- package/build-module/add-filter.js.map +1 -1
- package/build-module/bulk-actions-toolbar.js +76 -69
- package/build-module/bulk-actions-toolbar.js.map +1 -1
- package/build-module/bulk-actions.js +71 -56
- package/build-module/bulk-actions.js.map +1 -1
- package/build-module/constants.js +16 -9
- package/build-module/constants.js.map +1 -1
- package/build-module/dataviews.js +64 -56
- package/build-module/dataviews.js.map +1 -1
- package/build-module/filter-summary.js +106 -96
- package/build-module/filter-summary.js.map +1 -1
- package/build-module/filters.js +18 -17
- package/build-module/filters.js.map +1 -1
- package/build-module/index.js.map +1 -1
- package/build-module/item-actions.js +81 -65
- package/build-module/item-actions.js.map +1 -1
- package/build-module/layouts.js.map +1 -1
- package/build-module/pagination.js +61 -58
- package/build-module/pagination.js.map +1 -1
- package/build-module/reset-filters.js +9 -4
- package/build-module/reset-filters.js.map +1 -1
- package/build-module/search-widget.js +109 -89
- package/build-module/search-widget.js.map +1 -1
- package/build-module/search.js +13 -6
- package/build-module/search.js.map +1 -1
- package/build-module/single-selection-checkbox.js +2 -3
- package/build-module/single-selection-checkbox.js.map +1 -1
- package/build-module/types.js.map +1 -1
- package/build-module/utils.js +2 -13
- package/build-module/utils.js.map +1 -1
- package/build-module/view-actions.js +170 -121
- package/build-module/view-actions.js.map +1 -1
- package/build-module/view-grid.js +115 -99
- package/build-module/view-grid.js.map +1 -1
- package/build-module/view-list.js +155 -132
- package/build-module/view-list.js.map +1 -1
- package/build-module/view-table.js +223 -194
- package/build-module/view-table.js.map +1 -1
- package/build-style/style-rtl.css +115 -22
- package/build-style/style.css +115 -22
- package/build-types/add-filter.d.ts +9 -6
- package/build-types/add-filter.d.ts.map +1 -1
- package/build-types/bulk-actions-toolbar.d.ts +11 -7
- package/build-types/bulk-actions-toolbar.d.ts.map +1 -1
- package/build-types/bulk-actions.d.ts.map +1 -1
- package/build-types/constants.d.ts +19 -32
- package/build-types/constants.d.ts.map +1 -1
- package/build-types/dataviews.d.ts +21 -14
- package/build-types/dataviews.d.ts.map +1 -1
- package/build-types/filter-summary.d.ts +13 -5
- package/build-types/filter-summary.d.ts.map +1 -1
- package/build-types/filters.d.ts +11 -1
- package/build-types/filters.d.ts.map +1 -1
- package/build-types/index.d.ts +3 -3
- package/build-types/index.d.ts.map +1 -1
- package/build-types/item-actions.d.ts +5 -7
- package/build-types/item-actions.d.ts.map +1 -1
- package/build-types/layouts.d.ts +8 -4
- package/build-types/layouts.d.ts.map +1 -1
- package/build-types/reset-filters.d.ts +12 -5
- package/build-types/reset-filters.d.ts.map +1 -1
- package/build-types/search-widget.d.ts +9 -1
- package/build-types/search-widget.d.ts.map +1 -1
- package/build-types/search.d.ts +11 -1
- package/build-types/search.d.ts.map +1 -1
- package/build-types/types.d.ts +78 -10
- package/build-types/types.d.ts.map +1 -1
- package/build-types/utils.d.ts +2 -1
- package/build-types/utils.d.ts.map +1 -1
- package/build-types/view-actions.d.ts +10 -1
- package/build-types/view-actions.d.ts.map +1 -1
- package/build-types/view-grid.d.ts +1 -12
- package/build-types/view-grid.d.ts.map +1 -1
- package/build-types/view-list.d.ts +2 -14
- package/build-types/view-list.d.ts.map +1 -1
- package/build-types/view-table.d.ts +3 -12
- package/build-types/view-table.d.ts.map +1 -1
- package/package.json +11 -12
- package/src/{add-filter.js → add-filter.tsx} +17 -1
- package/src/{bulk-actions-toolbar.js → bulk-actions-toolbar.tsx} +68 -40
- package/src/bulk-actions.tsx +5 -1
- package/src/constants.ts +12 -5
- package/src/{dataviews.js → dataviews.tsx} +41 -12
- package/src/{filter-summary.js → filter-summary.tsx} +35 -6
- package/src/{filters.js → filters.tsx} +18 -6
- package/src/item-actions.tsx +21 -15
- package/src/pagination.tsx +1 -1
- package/src/{reset-filters.js → reset-filters.tsx} +17 -2
- package/src/{search-widget.js → search-widget.tsx} +27 -7
- package/src/{search.js → search.tsx} +22 -5
- package/src/style.scss +102 -25
- package/src/types.ts +105 -10
- package/src/{utils.js → utils.ts} +5 -13
- package/src/{view-actions.js → view-actions.tsx} +105 -49
- package/src/view-grid.tsx +4 -20
- package/src/view-list.tsx +13 -23
- package/src/{view-table.js → view-table.tsx} +91 -32
- package/tsconfig.json +0 -3
- package/tsconfig.tsbuildinfo +1 -1
- package/build/dropdown-menu-helper.js +0 -71
- package/build/dropdown-menu-helper.js.map +0 -1
- package/build-module/dropdown-menu-helper.js +0 -64
- package/build-module/dropdown-menu-helper.js.map +0 -1
- package/build-types/dropdown-menu-helper.d.ts +0 -6
- package/build-types/dropdown-menu-helper.d.ts.map +0 -1
- package/src/dropdown-menu-helper.js +0 -61
- /package/src/{index.js → index.ts} +0 -0
- /package/src/{layouts.js → layouts.ts} +0 -0
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External dependencies
|
|
3
|
+
*/
|
|
4
|
+
import type { ComponentType } from 'react';
|
|
5
|
+
|
|
1
6
|
/**
|
|
2
7
|
* WordPress dependencies
|
|
3
8
|
*/
|
|
@@ -16,21 +21,46 @@ import { VIEW_LAYOUTS } from './layouts';
|
|
|
16
21
|
import BulkActions from './bulk-actions';
|
|
17
22
|
import { normalizeFields } from './normalize-fields';
|
|
18
23
|
import BulkActionsToolbar from './bulk-actions-toolbar';
|
|
24
|
+
import type { Action, AnyItem, Field, View, ViewBaseProps } from './types';
|
|
25
|
+
|
|
26
|
+
interface DataViewsProps< Item extends AnyItem > {
|
|
27
|
+
view: View;
|
|
28
|
+
onChangeView: ( view: View ) => void;
|
|
29
|
+
fields: Field< Item >[];
|
|
30
|
+
search?: boolean;
|
|
31
|
+
searchLabel?: string;
|
|
32
|
+
actions?: Action< Item >[];
|
|
33
|
+
data: Item[];
|
|
34
|
+
getItemId?: ( item: Item ) => string;
|
|
35
|
+
isLoading?: boolean;
|
|
36
|
+
paginationInfo: {
|
|
37
|
+
totalItems: number;
|
|
38
|
+
totalPages: number;
|
|
39
|
+
};
|
|
40
|
+
supportedLayouts: string[];
|
|
41
|
+
onSelectionChange?: ( items: Item[] ) => void;
|
|
42
|
+
}
|
|
19
43
|
|
|
20
|
-
const defaultGetItemId = ( item ) => item.id;
|
|
44
|
+
const defaultGetItemId = ( item: AnyItem ) => item.id;
|
|
21
45
|
const defaultOnSelectionChange = () => {};
|
|
22
46
|
|
|
23
|
-
function useSomeItemHasAPossibleBulkAction
|
|
47
|
+
function useSomeItemHasAPossibleBulkAction< Item extends AnyItem >(
|
|
48
|
+
actions: Action< Item >[],
|
|
49
|
+
data: Item[]
|
|
50
|
+
) {
|
|
24
51
|
return useMemo( () => {
|
|
25
52
|
return data.some( ( item ) => {
|
|
26
53
|
return actions.some( ( action ) => {
|
|
27
|
-
return
|
|
54
|
+
return (
|
|
55
|
+
action.supportsBulk &&
|
|
56
|
+
( ! action.isEligible || action.isEligible( item ) )
|
|
57
|
+
);
|
|
28
58
|
} );
|
|
29
59
|
} );
|
|
30
60
|
}, [ actions, data ] );
|
|
31
61
|
}
|
|
32
62
|
|
|
33
|
-
export default function DataViews( {
|
|
63
|
+
export default function DataViews< Item extends AnyItem >( {
|
|
34
64
|
view,
|
|
35
65
|
onChangeView,
|
|
36
66
|
fields,
|
|
@@ -43,9 +73,9 @@ export default function DataViews( {
|
|
|
43
73
|
paginationInfo,
|
|
44
74
|
supportedLayouts,
|
|
45
75
|
onSelectionChange = defaultOnSelectionChange,
|
|
46
|
-
} ) {
|
|
47
|
-
const [ selection, setSelection ] = useState( [] );
|
|
48
|
-
const [ openedFilter, setOpenedFilter ] = useState( null );
|
|
76
|
+
}: DataViewsProps< Item > ) {
|
|
77
|
+
const [ selection, setSelection ] = useState< string[] >( [] );
|
|
78
|
+
const [ openedFilter, setOpenedFilter ] = useState< string | null >( null );
|
|
49
79
|
|
|
50
80
|
useEffect( () => {
|
|
51
81
|
if (
|
|
@@ -67,16 +97,15 @@ export default function DataViews( {
|
|
|
67
97
|
}, [ selection, data, getItemId, onSelectionChange ] );
|
|
68
98
|
|
|
69
99
|
const onSetSelection = useCallback(
|
|
70
|
-
( items ) => {
|
|
100
|
+
( items: Item[] ) => {
|
|
71
101
|
setSelection( items.map( ( item ) => getItemId( item ) ) );
|
|
72
102
|
onSelectionChange( items );
|
|
73
103
|
},
|
|
74
104
|
[ setSelection, getItemId, onSelectionChange ]
|
|
75
105
|
);
|
|
76
106
|
|
|
77
|
-
const ViewComponent = VIEW_LAYOUTS.find(
|
|
78
|
-
|
|
79
|
-
).component;
|
|
107
|
+
const ViewComponent = VIEW_LAYOUTS.find( ( v ) => v.type === view.type )
|
|
108
|
+
?.component as ComponentType< ViewBaseProps< Item > >;
|
|
80
109
|
const _fields = useMemo( () => normalizeFields( fields ), [ fields ] );
|
|
81
110
|
|
|
82
111
|
const hasPossibleBulkAction = useSomeItemHasAPossibleBulkAction(
|
|
@@ -150,7 +179,7 @@ export default function DataViews( {
|
|
|
150
179
|
data={ data }
|
|
151
180
|
actions={ actions }
|
|
152
181
|
selection={ selection }
|
|
153
|
-
|
|
182
|
+
onSelectionChange={ onSetSelection }
|
|
154
183
|
getItemId={ getItemId }
|
|
155
184
|
/>
|
|
156
185
|
) }
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* External dependencies
|
|
3
3
|
*/
|
|
4
4
|
import clsx from 'clsx';
|
|
5
|
+
import type { RefObject } from 'react';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* WordPress dependencies
|
|
@@ -35,8 +36,30 @@ import {
|
|
|
35
36
|
OPERATOR_IS_ALL,
|
|
36
37
|
OPERATOR_IS_NOT_ALL,
|
|
37
38
|
} from './constants';
|
|
39
|
+
import type { Filter, NormalizedFilter, Operator, Option, View } from './types';
|
|
38
40
|
|
|
39
|
-
|
|
41
|
+
interface FilterTextProps {
|
|
42
|
+
activeElements: Option[];
|
|
43
|
+
filterInView?: Filter;
|
|
44
|
+
filter: NormalizedFilter;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
interface OperatorSelectorProps {
|
|
48
|
+
filter: NormalizedFilter;
|
|
49
|
+
view: View;
|
|
50
|
+
onChangeView: ( view: View ) => void;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
interface FilterSummaryProps extends OperatorSelectorProps {
|
|
54
|
+
addFilterRef: RefObject< HTMLButtonElement >;
|
|
55
|
+
openedFilter: string | null;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const FilterText = ( {
|
|
59
|
+
activeElements,
|
|
60
|
+
filterInView,
|
|
61
|
+
filter,
|
|
62
|
+
}: FilterTextProps ) => {
|
|
40
63
|
if ( activeElements === undefined || activeElements.length === 0 ) {
|
|
41
64
|
return filter.name;
|
|
42
65
|
}
|
|
@@ -125,7 +148,11 @@ const FilterText = ( { activeElements, filterInView, filter } ) => {
|
|
|
125
148
|
);
|
|
126
149
|
};
|
|
127
150
|
|
|
128
|
-
function OperatorSelector( {
|
|
151
|
+
function OperatorSelector( {
|
|
152
|
+
filter,
|
|
153
|
+
view,
|
|
154
|
+
onChangeView,
|
|
155
|
+
}: OperatorSelectorProps ) {
|
|
129
156
|
const operatorOptions = filter.operators?.map( ( operator ) => ( {
|
|
130
157
|
value: operator,
|
|
131
158
|
label: OPERATORS[ operator ]?.label,
|
|
@@ -150,13 +177,14 @@ function OperatorSelector( { filter, view, onChangeView } ) {
|
|
|
150
177
|
value={ value }
|
|
151
178
|
options={ operatorOptions }
|
|
152
179
|
onChange={ ( newValue ) => {
|
|
180
|
+
const operator = newValue as Operator;
|
|
153
181
|
const newFilters = currentFilter
|
|
154
182
|
? [
|
|
155
183
|
...view.filters.map( ( _filter ) => {
|
|
156
184
|
if ( _filter.field === filter.field ) {
|
|
157
185
|
return {
|
|
158
186
|
..._filter,
|
|
159
|
-
operator
|
|
187
|
+
operator,
|
|
160
188
|
};
|
|
161
189
|
}
|
|
162
190
|
return _filter;
|
|
@@ -166,7 +194,8 @@ function OperatorSelector( { filter, view, onChangeView } ) {
|
|
|
166
194
|
...view.filters,
|
|
167
195
|
{
|
|
168
196
|
field: filter.field,
|
|
169
|
-
operator
|
|
197
|
+
operator,
|
|
198
|
+
value: undefined,
|
|
170
199
|
},
|
|
171
200
|
];
|
|
172
201
|
onChangeView( {
|
|
@@ -188,8 +217,8 @@ export default function FilterSummary( {
|
|
|
188
217
|
addFilterRef,
|
|
189
218
|
openedFilter,
|
|
190
219
|
...commonProps
|
|
191
|
-
} ) {
|
|
192
|
-
const toggleRef = useRef();
|
|
220
|
+
}: FilterSummaryProps ) {
|
|
221
|
+
const toggleRef = useRef< HTMLDivElement >( null );
|
|
193
222
|
const { filter, view, onChangeView } = commonProps;
|
|
194
223
|
const filterInView = view.filters.find( ( f ) => f.field === filter.field );
|
|
195
224
|
const activeElements = filter.elements.filter( ( element ) => {
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* WordPress dependencies
|
|
3
3
|
*/
|
|
4
4
|
import { memo, useRef } from '@wordpress/element';
|
|
5
|
+
import { __experimentalHStack as HStack } from '@wordpress/components';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Internal dependencies
|
|
@@ -11,17 +12,25 @@ import AddFilter from './add-filter';
|
|
|
11
12
|
import ResetFilters from './reset-filters';
|
|
12
13
|
import { sanitizeOperators } from './utils';
|
|
13
14
|
import { ALL_OPERATORS, OPERATOR_IS, OPERATOR_IS_NOT } from './constants';
|
|
14
|
-
import {
|
|
15
|
+
import type { AnyItem, NormalizedField, NormalizedFilter, View } from './types';
|
|
15
16
|
|
|
16
|
-
|
|
17
|
+
interface FiltersProps< Item extends AnyItem > {
|
|
18
|
+
fields: NormalizedField< Item >[];
|
|
19
|
+
view: View;
|
|
20
|
+
onChangeView: ( view: View ) => void;
|
|
21
|
+
openedFilter: string | null;
|
|
22
|
+
setOpenedFilter: ( openedFilter: string | null ) => void;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function _Filters< Item extends AnyItem >( {
|
|
17
26
|
fields,
|
|
18
27
|
view,
|
|
19
28
|
onChangeView,
|
|
20
29
|
openedFilter,
|
|
21
30
|
setOpenedFilter,
|
|
22
|
-
} ) {
|
|
23
|
-
const addFilterRef = useRef();
|
|
24
|
-
const filters = [];
|
|
31
|
+
}: FiltersProps< Item > ) {
|
|
32
|
+
const addFilterRef = useRef< HTMLButtonElement >( null );
|
|
33
|
+
const filters: NormalizedFilter[] = [];
|
|
25
34
|
fields.forEach( ( field ) => {
|
|
26
35
|
if ( ! field.elements?.length ) {
|
|
27
36
|
return;
|
|
@@ -108,6 +117,9 @@ const Filters = memo( function Filters( {
|
|
|
108
117
|
{ filterComponents }
|
|
109
118
|
</HStack>
|
|
110
119
|
);
|
|
111
|
-
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// A type assertion is used here to keep the type argument.
|
|
123
|
+
const Filters = memo( _Filters ) as typeof _Filters;
|
|
112
124
|
|
|
113
125
|
export default Filters;
|
package/src/item-actions.tsx
CHANGED
|
@@ -30,14 +30,11 @@ const {
|
|
|
30
30
|
kebabCase,
|
|
31
31
|
} = unlock( componentsPrivateApis );
|
|
32
32
|
|
|
33
|
-
interface
|
|
34
|
-
action: Action< Item >;
|
|
35
|
-
onClick: MouseEventHandler;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
interface DropdownMenuItemTriggerProps< Item extends AnyItem > {
|
|
33
|
+
export interface ActionTriggerProps< Item extends AnyItem > {
|
|
39
34
|
action: Action< Item >;
|
|
40
35
|
onClick: MouseEventHandler;
|
|
36
|
+
isBusy?: boolean;
|
|
37
|
+
items: Item[];
|
|
41
38
|
}
|
|
42
39
|
|
|
43
40
|
interface ActionModalProps< Item extends AnyItem > {
|
|
@@ -48,9 +45,7 @@ interface ActionModalProps< Item extends AnyItem > {
|
|
|
48
45
|
|
|
49
46
|
interface ActionWithModalProps< Item extends AnyItem >
|
|
50
47
|
extends ActionModalProps< Item > {
|
|
51
|
-
ActionTrigger: (
|
|
52
|
-
props: ButtonTriggerProps< Item > | DropdownMenuItemTriggerProps< Item >
|
|
53
|
-
) => ReactElement;
|
|
48
|
+
ActionTrigger: ( props: ActionTriggerProps< Item > ) => ReactElement;
|
|
54
49
|
isBusy?: boolean;
|
|
55
50
|
}
|
|
56
51
|
|
|
@@ -62,7 +57,7 @@ interface ActionsDropdownMenuGroupProps< Item extends AnyItem > {
|
|
|
62
57
|
interface ItemActionsProps< Item extends AnyItem > {
|
|
63
58
|
item: Item;
|
|
64
59
|
actions: Action< Item >[];
|
|
65
|
-
isCompact
|
|
60
|
+
isCompact?: boolean;
|
|
66
61
|
}
|
|
67
62
|
|
|
68
63
|
interface CompactItemActionsProps< Item extends AnyItem > {
|
|
@@ -73,10 +68,13 @@ interface CompactItemActionsProps< Item extends AnyItem > {
|
|
|
73
68
|
function ButtonTrigger< Item extends AnyItem >( {
|
|
74
69
|
action,
|
|
75
70
|
onClick,
|
|
76
|
-
|
|
71
|
+
items,
|
|
72
|
+
}: ActionTriggerProps< Item > ) {
|
|
73
|
+
const label =
|
|
74
|
+
typeof action.label === 'string' ? action.label : action.label( items );
|
|
77
75
|
return (
|
|
78
76
|
<Button
|
|
79
|
-
label={
|
|
77
|
+
label={ label }
|
|
80
78
|
icon={ action.icon }
|
|
81
79
|
isDestructive={ action.isDestructive }
|
|
82
80
|
size="compact"
|
|
@@ -88,13 +86,16 @@ function ButtonTrigger< Item extends AnyItem >( {
|
|
|
88
86
|
function DropdownMenuItemTrigger< Item extends AnyItem >( {
|
|
89
87
|
action,
|
|
90
88
|
onClick,
|
|
91
|
-
|
|
89
|
+
items,
|
|
90
|
+
}: ActionTriggerProps< Item > ) {
|
|
91
|
+
const label =
|
|
92
|
+
typeof action.label === 'string' ? action.label : action.label( items );
|
|
92
93
|
return (
|
|
93
94
|
<DropdownMenuItem
|
|
94
95
|
onClick={ onClick }
|
|
95
96
|
hideOnClick={ ! ( 'RenderModal' in action ) }
|
|
96
97
|
>
|
|
97
|
-
<DropdownMenuItemLabel>{
|
|
98
|
+
<DropdownMenuItemLabel>{ label }</DropdownMenuItemLabel>
|
|
98
99
|
</DropdownMenuItem>
|
|
99
100
|
);
|
|
100
101
|
}
|
|
@@ -104,9 +105,11 @@ export function ActionModal< Item extends AnyItem >( {
|
|
|
104
105
|
items,
|
|
105
106
|
closeModal,
|
|
106
107
|
}: ActionModalProps< Item > ) {
|
|
108
|
+
const label =
|
|
109
|
+
typeof action.label === 'string' ? action.label : action.label( items );
|
|
107
110
|
return (
|
|
108
111
|
<Modal
|
|
109
|
-
title={ action.modalHeader ||
|
|
112
|
+
title={ action.modalHeader || label }
|
|
110
113
|
__experimentalHideHeader={ !! action.hideModalHeader }
|
|
111
114
|
onRequestClose={ closeModal ?? ( () => {} ) }
|
|
112
115
|
overlayClassName={ `dataviews-action-modal dataviews-action-modal__${ kebabCase(
|
|
@@ -174,6 +177,7 @@ export function ActionsDropdownMenuGroup< Item extends AnyItem >( {
|
|
|
174
177
|
key={ action.id }
|
|
175
178
|
action={ action }
|
|
176
179
|
onClick={ () => action.callback( [ item ] ) }
|
|
180
|
+
items={ [ item ] }
|
|
177
181
|
/>
|
|
178
182
|
);
|
|
179
183
|
} ) }
|
|
@@ -230,6 +234,7 @@ export default function ItemActions< Item extends AnyItem >( {
|
|
|
230
234
|
key={ action.id }
|
|
231
235
|
action={ action }
|
|
232
236
|
onClick={ () => action.callback( [ item ] ) }
|
|
237
|
+
items={ [ item ] }
|
|
233
238
|
/>
|
|
234
239
|
);
|
|
235
240
|
} ) }
|
|
@@ -249,6 +254,7 @@ function CompactItemActions< Item extends AnyItem >( {
|
|
|
249
254
|
size="compact"
|
|
250
255
|
icon={ moreVertical }
|
|
251
256
|
label={ __( 'Actions' ) }
|
|
257
|
+
__experimentalIsFocusable
|
|
252
258
|
disabled={ ! actions.length }
|
|
253
259
|
className="dataviews-all-actions-button"
|
|
254
260
|
/>
|
package/src/pagination.tsx
CHANGED
|
@@ -4,8 +4,23 @@
|
|
|
4
4
|
import { Button } from '@wordpress/components';
|
|
5
5
|
import { __ } from '@wordpress/i18n';
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
/**
|
|
8
|
+
* Internal dependencies
|
|
9
|
+
*/
|
|
10
|
+
import type { NormalizedFilter, View } from './types';
|
|
11
|
+
|
|
12
|
+
interface ResetFilterProps {
|
|
13
|
+
filters: NormalizedFilter[];
|
|
14
|
+
view: View;
|
|
15
|
+
onChangeView: ( view: View ) => void;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export default function ResetFilter( {
|
|
19
|
+
filters,
|
|
20
|
+
view,
|
|
21
|
+
onChangeView,
|
|
22
|
+
}: ResetFilterProps ) {
|
|
23
|
+
const isPrimary = ( field: string ) =>
|
|
9
24
|
filters.some(
|
|
10
25
|
( _filter ) => _filter.field === field && _filter.isPrimary
|
|
11
26
|
);
|
|
@@ -22,6 +22,7 @@ import { SVG, Circle } from '@wordpress/primitives';
|
|
|
22
22
|
* Internal dependencies
|
|
23
23
|
*/
|
|
24
24
|
import { unlock } from './lock-unlock';
|
|
25
|
+
import type { Filter, NormalizedFilter, View } from './types';
|
|
25
26
|
|
|
26
27
|
const {
|
|
27
28
|
CompositeV2: Composite,
|
|
@@ -29,6 +30,12 @@ const {
|
|
|
29
30
|
useCompositeStoreV2: useCompositeStore,
|
|
30
31
|
} = unlock( componentsPrivateApis );
|
|
31
32
|
|
|
33
|
+
interface SearchWidgetProps {
|
|
34
|
+
view: View;
|
|
35
|
+
filter: NormalizedFilter;
|
|
36
|
+
onChangeView: ( view: View ) => void;
|
|
37
|
+
}
|
|
38
|
+
|
|
32
39
|
const radioCheck = (
|
|
33
40
|
<SVG xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
|
34
41
|
<Circle cx={ 12 } cy={ 12 } r={ 3 }></Circle>
|
|
@@ -39,8 +46,11 @@ function normalizeSearchInput( input = '' ) {
|
|
|
39
46
|
return removeAccents( input.trim().toLowerCase() );
|
|
40
47
|
}
|
|
41
48
|
|
|
42
|
-
const EMPTY_ARRAY = [];
|
|
43
|
-
const getCurrentValue = (
|
|
49
|
+
const EMPTY_ARRAY: [] = [];
|
|
50
|
+
const getCurrentValue = (
|
|
51
|
+
filterDefinition: NormalizedFilter,
|
|
52
|
+
currentFilter?: Filter
|
|
53
|
+
) => {
|
|
44
54
|
if ( filterDefinition.singleSelection ) {
|
|
45
55
|
return currentFilter?.value;
|
|
46
56
|
}
|
|
@@ -56,7 +66,11 @@ const getCurrentValue = ( filterDefinition, currentFilter ) => {
|
|
|
56
66
|
return EMPTY_ARRAY;
|
|
57
67
|
};
|
|
58
68
|
|
|
59
|
-
const getNewValue = (
|
|
69
|
+
const getNewValue = (
|
|
70
|
+
filterDefinition: NormalizedFilter,
|
|
71
|
+
currentFilter: Filter | undefined,
|
|
72
|
+
value: any
|
|
73
|
+
) => {
|
|
60
74
|
if ( filterDefinition.singleSelection ) {
|
|
61
75
|
return value;
|
|
62
76
|
}
|
|
@@ -70,7 +84,7 @@ const getNewValue = ( filterDefinition, currentFilter, value ) => {
|
|
|
70
84
|
return [ value ];
|
|
71
85
|
};
|
|
72
86
|
|
|
73
|
-
function ListBox( { view, filter, onChangeView } ) {
|
|
87
|
+
function ListBox( { view, filter, onChangeView }: SearchWidgetProps ) {
|
|
74
88
|
const compositeStore = useCompositeStore( {
|
|
75
89
|
virtualFocus: true,
|
|
76
90
|
focusLoop: true,
|
|
@@ -184,7 +198,7 @@ function ListBox( { view, filter, onChangeView } ) {
|
|
|
184
198
|
);
|
|
185
199
|
}
|
|
186
200
|
|
|
187
|
-
function ComboboxList( { view, filter, onChangeView } ) {
|
|
201
|
+
function ComboboxList( { view, filter, onChangeView }: SearchWidgetProps ) {
|
|
188
202
|
const [ searchValue, setSearchValue ] = useState( '' );
|
|
189
203
|
const deferredSearchValue = useDeferredValue( searchValue );
|
|
190
204
|
const currentFilter = view.filters.find(
|
|
@@ -234,7 +248,13 @@ function ComboboxList( { view, filter, onChangeView } ) {
|
|
|
234
248
|
setValue={ setSearchValue }
|
|
235
249
|
>
|
|
236
250
|
<div className="dataviews-search-widget-filter-combobox__wrapper">
|
|
237
|
-
<Ariakit.ComboboxLabel
|
|
251
|
+
<Ariakit.ComboboxLabel
|
|
252
|
+
render={
|
|
253
|
+
<VisuallyHidden>
|
|
254
|
+
{ __( 'Search items' ) }
|
|
255
|
+
</VisuallyHidden>
|
|
256
|
+
}
|
|
257
|
+
>
|
|
238
258
|
{ __( 'Search items' ) }
|
|
239
259
|
</Ariakit.ComboboxLabel>
|
|
240
260
|
<Ariakit.Combobox
|
|
@@ -290,7 +310,7 @@ function ComboboxList( { view, filter, onChangeView } ) {
|
|
|
290
310
|
);
|
|
291
311
|
}
|
|
292
312
|
|
|
293
|
-
export default function SearchWidget( props ) {
|
|
313
|
+
export default function SearchWidget( props: SearchWidgetProps ) {
|
|
294
314
|
const Widget = props.filter.elements.length > 10 ? ComboboxList : ListBox;
|
|
295
315
|
return <Widget { ...props } />;
|
|
296
316
|
}
|
|
@@ -6,20 +6,37 @@ import { useEffect, useRef, memo } from '@wordpress/element';
|
|
|
6
6
|
import { SearchControl } from '@wordpress/components';
|
|
7
7
|
import { useDebouncedInput } from '@wordpress/compose';
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Internal dependencies
|
|
11
|
+
*/
|
|
12
|
+
import type { View } from './types';
|
|
13
|
+
|
|
14
|
+
interface SearchProps {
|
|
15
|
+
label?: string;
|
|
16
|
+
view: View;
|
|
17
|
+
onChangeView: ( view: View ) => void;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const Search = memo( function Search( {
|
|
21
|
+
label,
|
|
22
|
+
view,
|
|
23
|
+
onChangeView,
|
|
24
|
+
}: SearchProps ) {
|
|
10
25
|
const [ search, setSearch, debouncedSearch ] = useDebouncedInput(
|
|
11
26
|
view.search
|
|
12
27
|
);
|
|
13
28
|
useEffect( () => {
|
|
14
|
-
setSearch( view.search );
|
|
15
|
-
}, [ view ] );
|
|
29
|
+
setSearch( view.search ?? '' );
|
|
30
|
+
}, [ view.search, setSearch ] );
|
|
16
31
|
const onChangeViewRef = useRef( onChangeView );
|
|
32
|
+
const viewRef = useRef( view );
|
|
17
33
|
useEffect( () => {
|
|
18
34
|
onChangeViewRef.current = onChangeView;
|
|
19
|
-
|
|
35
|
+
viewRef.current = view;
|
|
36
|
+
}, [ onChangeView, view ] );
|
|
20
37
|
useEffect( () => {
|
|
21
38
|
onChangeViewRef.current( {
|
|
22
|
-
...
|
|
39
|
+
...viewRef.current,
|
|
23
40
|
page: 1,
|
|
24
41
|
search: debouncedSearch,
|
|
25
42
|
} );
|