@wordpress/dataviews 1.2.0 → 2.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.
- 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 +78 -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 +153 -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 +80 -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 +154 -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 +109 -20
- package/build-style/style.css +109 -20
- 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 +20 -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 +97 -23
- 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 +12 -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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"view-list.d.ts","sourceRoot":"","sources":["../src/view-list.tsx"],"names":[],"mappings":";AAkCA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"view-list.d.ts","sourceRoot":"","sources":["../src/view-list.tsx"],"names":[],"mappings":";AAkCA,OAAO,KAAK,EAAU,OAAO,EAAmB,aAAa,EAAE,MAAM,SAAS,CAAC;AA2Q/E,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAE,IAAI,SAAS,OAAO,EACrD,KAAK,EAAE,aAAa,CAAE,IAAI,CAAE,+BA2G5B"}
|
|
@@ -1,14 +1,5 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import type { AnyItem, ViewTableProps } from './types';
|
|
3
|
+
declare function ViewTable<Item extends AnyItem>({ actions, data, fields, getItemId, isLoading, onChangeView, onSelectionChange, selection, setOpenedFilter, view, }: ViewTableProps<Item>): import("react").JSX.Element | undefined;
|
|
1
4
|
export default ViewTable;
|
|
2
|
-
declare function ViewTable({ actions, data, fields, getItemId, isLoading, onChangeView, onSelectionChange, selection, setOpenedFilter, view, }: {
|
|
3
|
-
actions: any;
|
|
4
|
-
data: any;
|
|
5
|
-
fields: any;
|
|
6
|
-
getItemId: any;
|
|
7
|
-
isLoading?: boolean | undefined;
|
|
8
|
-
onChangeView: any;
|
|
9
|
-
onSelectionChange: any;
|
|
10
|
-
selection: any;
|
|
11
|
-
setOpenedFilter: any;
|
|
12
|
-
view: any;
|
|
13
|
-
}): import("react").JSX.Element | undefined;
|
|
14
5
|
//# sourceMappingURL=view-table.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"view-table.d.ts","sourceRoot":"","sources":["../src/view-table.
|
|
1
|
+
{"version":3,"file":"view-table.d.ts","sourceRoot":"","sources":["../src/view-table.tsx"],"names":[],"mappings":";AA8CA,OAAO,KAAK,EAEX,OAAO,EAIP,cAAc,EACd,MAAM,SAAS,CAAC;AA4WjB,iBAAS,SAAS,CAAE,IAAI,SAAS,OAAO,EAAI,EAC3C,OAAO,EACP,IAAI,EACJ,MAAM,EACN,SAAS,EACT,SAAiB,EACjB,YAAY,EACZ,iBAAiB,EACjB,SAAS,EACT,eAAe,EACf,IAAI,GACJ,EAAE,cAAc,CAAE,IAAI,CAAE,2CAiKxB;AAED,eAAe,SAAS,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wordpress/dataviews",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "DataViews is a component that provides an API to render datasets using different types of layouts (table, grid, list, etc.).",
|
|
5
5
|
"author": "The WordPress Contributors",
|
|
6
6
|
"license": "GPL-2.0-or-later",
|
|
@@ -19,7 +19,8 @@
|
|
|
19
19
|
"url": "https://github.com/WordPress/gutenberg/issues"
|
|
20
20
|
},
|
|
21
21
|
"engines": {
|
|
22
|
-
"node": ">=12"
|
|
22
|
+
"node": ">=18.12.0",
|
|
23
|
+
"npm": ">=8.19.2"
|
|
23
24
|
},
|
|
24
25
|
"main": "build/index.js",
|
|
25
26
|
"module": "build-module/index.js",
|
|
@@ -29,15 +30,13 @@
|
|
|
29
30
|
"dependencies": {
|
|
30
31
|
"@ariakit/react": "^0.3.12",
|
|
31
32
|
"@babel/runtime": "^7.16.0",
|
|
32
|
-
"@wordpress/
|
|
33
|
-
"@wordpress/
|
|
34
|
-
"@wordpress/
|
|
35
|
-
"@wordpress/
|
|
36
|
-
"@wordpress/
|
|
37
|
-
"@wordpress/
|
|
38
|
-
"@wordpress/
|
|
39
|
-
"@wordpress/primitives": "^3.56.0",
|
|
40
|
-
"@wordpress/private-apis": "^0.40.0",
|
|
33
|
+
"@wordpress/components": "^28.0.0",
|
|
34
|
+
"@wordpress/compose": "^7.0.0",
|
|
35
|
+
"@wordpress/element": "^6.0.0",
|
|
36
|
+
"@wordpress/i18n": "^5.0.0",
|
|
37
|
+
"@wordpress/icons": "^10.0.0",
|
|
38
|
+
"@wordpress/primitives": "^4.0.0",
|
|
39
|
+
"@wordpress/private-apis": "^1.0.0",
|
|
41
40
|
"clsx": "^2.1.1",
|
|
42
41
|
"remove-accents": "^0.5.0"
|
|
43
42
|
},
|
|
@@ -47,5 +46,5 @@
|
|
|
47
46
|
"publishConfig": {
|
|
48
47
|
"access": "public"
|
|
49
48
|
},
|
|
50
|
-
"gitHead": "
|
|
49
|
+
"gitHead": "2f30cddff15723ac7017fd009fc5913b7b419400"
|
|
51
50
|
}
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External dependencies
|
|
3
|
+
*/
|
|
4
|
+
import type { Ref } from 'react';
|
|
5
|
+
|
|
1
6
|
/**
|
|
2
7
|
* WordPress dependencies
|
|
3
8
|
*/
|
|
@@ -12,6 +17,7 @@ import { forwardRef } from '@wordpress/element';
|
|
|
12
17
|
* Internal dependencies
|
|
13
18
|
*/
|
|
14
19
|
import { unlock } from './lock-unlock';
|
|
20
|
+
import type { NormalizedFilter, View } from './types';
|
|
15
21
|
|
|
16
22
|
const {
|
|
17
23
|
DropdownMenuV2: DropdownMenu,
|
|
@@ -19,7 +25,17 @@ const {
|
|
|
19
25
|
DropdownMenuItemLabelV2: DropdownMenuItemLabel,
|
|
20
26
|
} = unlock( componentsPrivateApis );
|
|
21
27
|
|
|
22
|
-
|
|
28
|
+
interface AddFilterProps {
|
|
29
|
+
filters: NormalizedFilter[];
|
|
30
|
+
view: View;
|
|
31
|
+
onChangeView: ( view: View ) => void;
|
|
32
|
+
setOpenedFilter: ( filter: string | null ) => void;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function AddFilter(
|
|
36
|
+
{ filters, view, onChangeView, setOpenedFilter }: AddFilterProps,
|
|
37
|
+
ref: Ref< HTMLButtonElement >
|
|
38
|
+
) {
|
|
23
39
|
if ( ! filters.length || filters.every( ( { isPrimary } ) => isPrimary ) ) {
|
|
24
40
|
return null;
|
|
25
41
|
}
|
|
@@ -17,6 +17,30 @@ import { useReducedMotion } from '@wordpress/compose';
|
|
|
17
17
|
* Internal dependencies
|
|
18
18
|
*/
|
|
19
19
|
import { ActionWithModal } from './item-actions';
|
|
20
|
+
import type { Action, AnyItem } from './types';
|
|
21
|
+
import type { ActionTriggerProps } from './item-actions';
|
|
22
|
+
|
|
23
|
+
interface ActionButtonProps< Item extends AnyItem > {
|
|
24
|
+
action: Action< Item >;
|
|
25
|
+
selectedItems: Item[];
|
|
26
|
+
actionInProgress: string | null;
|
|
27
|
+
setActionInProgress: ( actionId: string | null ) => void;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
interface ToolbarContentProps< Item extends AnyItem > {
|
|
31
|
+
selection: string[];
|
|
32
|
+
actionsToShow: Action< Item >[];
|
|
33
|
+
selectedItems: Item[];
|
|
34
|
+
onSelectionChange: ( selection: Item[] ) => void;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
interface BulkActionsToolbarProps< Item extends AnyItem > {
|
|
38
|
+
data: Item[];
|
|
39
|
+
selection: string[];
|
|
40
|
+
actions: Action< Item >[];
|
|
41
|
+
onSelectionChange: ( selection: Item[] ) => void;
|
|
42
|
+
getItemId: ( item: Item ) => string;
|
|
43
|
+
}
|
|
20
44
|
|
|
21
45
|
const SNACKBAR_VARIANTS = {
|
|
22
46
|
init: {
|
|
@@ -37,11 +61,18 @@ const SNACKBAR_VARIANTS = {
|
|
|
37
61
|
},
|
|
38
62
|
};
|
|
39
63
|
|
|
40
|
-
function ActionTrigger
|
|
64
|
+
function ActionTrigger< Item extends AnyItem >( {
|
|
65
|
+
action,
|
|
66
|
+
onClick,
|
|
67
|
+
isBusy,
|
|
68
|
+
items,
|
|
69
|
+
}: ActionTriggerProps< Item > ) {
|
|
70
|
+
const label =
|
|
71
|
+
typeof action.label === 'string' ? action.label : action.label( items );
|
|
41
72
|
return (
|
|
42
73
|
<ToolbarButton
|
|
43
74
|
disabled={ isBusy }
|
|
44
|
-
label={
|
|
75
|
+
label={ label }
|
|
45
76
|
icon={ action.icon }
|
|
46
77
|
isDestructive={ action.isDestructive }
|
|
47
78
|
size="compact"
|
|
@@ -53,32 +84,26 @@ function ActionTrigger( { action, onClick, isBusy } ) {
|
|
|
53
84
|
);
|
|
54
85
|
}
|
|
55
86
|
|
|
56
|
-
const EMPTY_ARRAY = [];
|
|
87
|
+
const EMPTY_ARRAY: [] = [];
|
|
57
88
|
|
|
58
|
-
function ActionButton( {
|
|
89
|
+
function ActionButton< Item extends AnyItem >( {
|
|
59
90
|
action,
|
|
60
91
|
selectedItems,
|
|
61
92
|
actionInProgress,
|
|
62
93
|
setActionInProgress,
|
|
63
|
-
} ) {
|
|
94
|
+
}: ActionButtonProps< Item > ) {
|
|
64
95
|
const selectedEligibleItems = useMemo( () => {
|
|
65
96
|
return selectedItems.filter( ( item ) => {
|
|
66
|
-
return action.isEligible( item );
|
|
97
|
+
return ! action.isEligible || action.isEligible( item );
|
|
67
98
|
} );
|
|
68
99
|
}, [ action, selectedItems ] );
|
|
69
|
-
if (
|
|
100
|
+
if ( 'RenderModal' in action ) {
|
|
70
101
|
return (
|
|
71
102
|
<ActionWithModal
|
|
72
103
|
key={ action.id }
|
|
73
104
|
action={ action }
|
|
74
105
|
items={ selectedEligibleItems }
|
|
75
106
|
ActionTrigger={ ActionTrigger }
|
|
76
|
-
onActionStart={ () => {
|
|
77
|
-
setActionInProgress( action.id );
|
|
78
|
-
} }
|
|
79
|
-
onActionPerformed={ () => {
|
|
80
|
-
setActionInProgress( null );
|
|
81
|
-
} }
|
|
82
107
|
/>
|
|
83
108
|
);
|
|
84
109
|
}
|
|
@@ -86,25 +111,23 @@ function ActionButton( {
|
|
|
86
111
|
<ActionTrigger
|
|
87
112
|
key={ action.id }
|
|
88
113
|
action={ action }
|
|
89
|
-
items={ selectedItems }
|
|
90
114
|
onClick={ () => {
|
|
91
115
|
setActionInProgress( action.id );
|
|
92
|
-
action.callback( selectedItems
|
|
93
|
-
setActionInProgress( action.id );
|
|
94
|
-
} );
|
|
116
|
+
action.callback( selectedItems );
|
|
95
117
|
} }
|
|
118
|
+
items={ selectedEligibleItems }
|
|
96
119
|
isBusy={ actionInProgress === action.id }
|
|
97
120
|
/>
|
|
98
121
|
);
|
|
99
122
|
}
|
|
100
123
|
|
|
101
|
-
function renderToolbarContent(
|
|
102
|
-
selection,
|
|
103
|
-
actionsToShow,
|
|
104
|
-
selectedItems,
|
|
105
|
-
actionInProgress,
|
|
106
|
-
setActionInProgress,
|
|
107
|
-
|
|
124
|
+
function renderToolbarContent< Item extends AnyItem >(
|
|
125
|
+
selection: string[],
|
|
126
|
+
actionsToShow: Action< Item >[],
|
|
127
|
+
selectedItems: Item[],
|
|
128
|
+
actionInProgress: string | null,
|
|
129
|
+
setActionInProgress: ( actionId: string | null ) => void,
|
|
130
|
+
onSelectionChange: ( selection: Item[] ) => void
|
|
108
131
|
) {
|
|
109
132
|
return (
|
|
110
133
|
<>
|
|
@@ -144,7 +167,7 @@ function renderToolbarContent(
|
|
|
144
167
|
label={ __( 'Cancel' ) }
|
|
145
168
|
disabled={ !! actionInProgress }
|
|
146
169
|
onClick={ () => {
|
|
147
|
-
|
|
170
|
+
onSelectionChange( EMPTY_ARRAY );
|
|
148
171
|
} }
|
|
149
172
|
/>
|
|
150
173
|
</ToolbarGroup>
|
|
@@ -152,14 +175,16 @@ function renderToolbarContent(
|
|
|
152
175
|
);
|
|
153
176
|
}
|
|
154
177
|
|
|
155
|
-
function ToolbarContent( {
|
|
178
|
+
function ToolbarContent< Item extends AnyItem >( {
|
|
156
179
|
selection,
|
|
157
180
|
actionsToShow,
|
|
158
181
|
selectedItems,
|
|
159
|
-
|
|
160
|
-
} ) {
|
|
161
|
-
const [ actionInProgress, setActionInProgress ] = useState
|
|
162
|
-
|
|
182
|
+
onSelectionChange,
|
|
183
|
+
}: ToolbarContentProps< Item > ) {
|
|
184
|
+
const [ actionInProgress, setActionInProgress ] = useState< string | null >(
|
|
185
|
+
null
|
|
186
|
+
);
|
|
187
|
+
const buttons = useRef< JSX.Element | null >( null );
|
|
163
188
|
if ( ! actionInProgress ) {
|
|
164
189
|
if ( buttons.current ) {
|
|
165
190
|
buttons.current = null;
|
|
@@ -170,7 +195,7 @@ function ToolbarContent( {
|
|
|
170
195
|
selectedItems,
|
|
171
196
|
actionInProgress,
|
|
172
197
|
setActionInProgress,
|
|
173
|
-
|
|
198
|
+
onSelectionChange
|
|
174
199
|
);
|
|
175
200
|
} else if ( ! buttons.current ) {
|
|
176
201
|
buttons.current = renderToolbarContent(
|
|
@@ -179,19 +204,19 @@ function ToolbarContent( {
|
|
|
179
204
|
selectedItems,
|
|
180
205
|
actionInProgress,
|
|
181
206
|
setActionInProgress,
|
|
182
|
-
|
|
207
|
+
onSelectionChange
|
|
183
208
|
);
|
|
184
209
|
}
|
|
185
210
|
return buttons.current;
|
|
186
211
|
}
|
|
187
212
|
|
|
188
|
-
export default function BulkActionsToolbar( {
|
|
213
|
+
export default function BulkActionsToolbar< Item extends AnyItem >( {
|
|
189
214
|
data,
|
|
190
215
|
selection,
|
|
191
216
|
actions = EMPTY_ARRAY,
|
|
192
|
-
|
|
217
|
+
onSelectionChange,
|
|
193
218
|
getItemId,
|
|
194
|
-
} ) {
|
|
219
|
+
}: BulkActionsToolbarProps< Item > ) {
|
|
195
220
|
const isReducedMotion = useReducedMotion();
|
|
196
221
|
const selectedItems = useMemo( () => {
|
|
197
222
|
return data.filter( ( item ) =>
|
|
@@ -205,7 +230,10 @@ export default function BulkActionsToolbar( {
|
|
|
205
230
|
return (
|
|
206
231
|
action.supportsBulk &&
|
|
207
232
|
action.icon &&
|
|
208
|
-
selectedItems.some(
|
|
233
|
+
selectedItems.some(
|
|
234
|
+
( item ) =>
|
|
235
|
+
! action.isEligible || action.isEligible( item )
|
|
236
|
+
)
|
|
209
237
|
);
|
|
210
238
|
} ),
|
|
211
239
|
[ actions, selectedItems ]
|
|
@@ -222,9 +250,9 @@ export default function BulkActionsToolbar( {
|
|
|
222
250
|
<AnimatePresence>
|
|
223
251
|
<motion.div
|
|
224
252
|
layout={ ! isReducedMotion } // See https://www.framer.com/docs/animation/#layout-animations
|
|
225
|
-
initial=
|
|
226
|
-
animate=
|
|
227
|
-
exit=
|
|
253
|
+
initial="init"
|
|
254
|
+
animate="open"
|
|
255
|
+
exit="exit"
|
|
228
256
|
variants={ isReducedMotion ? undefined : SNACKBAR_VARIANTS }
|
|
229
257
|
className="dataviews-bulk-actions"
|
|
230
258
|
>
|
|
@@ -234,7 +262,7 @@ export default function BulkActionsToolbar( {
|
|
|
234
262
|
selection={ selection }
|
|
235
263
|
actionsToShow={ actionsToShow }
|
|
236
264
|
selectedItems={ selectedItems }
|
|
237
|
-
|
|
265
|
+
onSelectionChange={ onSelectionChange }
|
|
238
266
|
/>
|
|
239
267
|
</div>
|
|
240
268
|
</Toolbar>
|
package/src/bulk-actions.tsx
CHANGED
|
@@ -94,9 +94,13 @@ function ActionWithModal< Item extends AnyItem >( {
|
|
|
94
94
|
const onCloseModal = useCallback( () => {
|
|
95
95
|
setActionWithModal( undefined );
|
|
96
96
|
}, [ setActionWithModal ] );
|
|
97
|
+
const label =
|
|
98
|
+
typeof action.label === 'string'
|
|
99
|
+
? action.label
|
|
100
|
+
: action.label( selectedItems );
|
|
97
101
|
return (
|
|
98
102
|
<Modal
|
|
99
|
-
title={ ! hideModalHeader ?
|
|
103
|
+
title={ ! hideModalHeader ? label : undefined }
|
|
100
104
|
__experimentalHideHeader={ !! hideModalHeader }
|
|
101
105
|
onRequestClose={ onCloseModal }
|
|
102
106
|
overlayClassName="dataviews-action-modal"
|
package/src/constants.ts
CHANGED
|
@@ -3,6 +3,11 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { __ } from '@wordpress/i18n';
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Internal dependencies
|
|
8
|
+
*/
|
|
9
|
+
import type { Operator } from './types';
|
|
10
|
+
|
|
6
11
|
// Filter operators.
|
|
7
12
|
export const OPERATOR_IS = 'is';
|
|
8
13
|
export const OPERATOR_IS_NOT = 'isNot';
|
|
@@ -19,7 +24,7 @@ export const ALL_OPERATORS = [
|
|
|
19
24
|
OPERATOR_IS_ALL,
|
|
20
25
|
OPERATOR_IS_NOT_ALL,
|
|
21
26
|
];
|
|
22
|
-
export const OPERATORS = {
|
|
27
|
+
export const OPERATORS: Record< Operator, { key: string; label: string } > = {
|
|
23
28
|
[ OPERATOR_IS ]: {
|
|
24
29
|
key: 'is-filter',
|
|
25
30
|
label: __( 'Is' ),
|
|
@@ -46,10 +51,12 @@ export const OPERATORS = {
|
|
|
46
51
|
},
|
|
47
52
|
};
|
|
48
53
|
|
|
49
|
-
|
|
50
|
-
export const
|
|
51
|
-
|
|
52
|
-
|
|
54
|
+
export const SORTING_DIRECTIONS = [ 'asc', 'desc' ] as const;
|
|
55
|
+
export const sortArrows = { asc: '↑', desc: '↓' };
|
|
56
|
+
export const sortValues = { asc: 'ascending', desc: 'descending' } as const;
|
|
57
|
+
export const sortLabels = {
|
|
58
|
+
asc: __( 'Sort ascending' ),
|
|
59
|
+
desc: __( 'Sort descending' ),
|
|
53
60
|
};
|
|
54
61
|
|
|
55
62
|
// View layouts.
|
|
@@ -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;
|