@wordpress/dataviews 4.1.0 → 4.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.
- package/CHANGELOG.md +19 -0
- package/README.md +77 -29
- package/build/components/dataviews/index.js +10 -14
- package/build/components/dataviews/index.js.map +1 -1
- package/build/components/dataviews-bulk-actions/index.js +145 -141
- package/build/components/dataviews-bulk-actions/index.js.map +1 -1
- package/build/components/dataviews-filters/add-filter.js +4 -6
- package/build/components/dataviews-filters/add-filter.js.map +1 -1
- package/build/components/dataviews-filters/index.js +3 -0
- package/build/components/dataviews-filters/index.js.map +1 -1
- package/build/components/dataviews-filters/search-widget.js +30 -23
- package/build/components/dataviews-filters/search-widget.js.map +1 -1
- package/build/components/dataviews-footer/index.js +45 -0
- package/build/components/dataviews-footer/index.js.map +1 -0
- package/build/components/dataviews-item-actions/index.js +5 -8
- package/build/components/dataviews-item-actions/index.js.map +1 -1
- package/build/components/dataviews-pagination/index.js +27 -19
- package/build/components/dataviews-pagination/index.js.map +1 -1
- package/build/components/dataviews-view-config/index.js +197 -41
- package/build/components/dataviews-view-config/index.js.map +1 -1
- package/build/dataform-controls/datetime.js +49 -0
- package/build/dataform-controls/datetime.js.map +1 -0
- package/build/dataform-controls/index.js +50 -0
- package/build/dataform-controls/index.js.map +1 -0
- package/build/dataform-controls/integer.js +45 -0
- package/build/dataform-controls/integer.js.map +1 -0
- package/build/dataform-controls/radio.js +45 -0
- package/build/dataform-controls/radio.js.map +1 -0
- package/build/dataform-controls/select.js +58 -0
- package/build/dataform-controls/select.js.map +1 -0
- package/build/dataform-controls/text.js +45 -0
- package/build/dataform-controls/text.js.map +1 -0
- package/build/dataforms-layouts/panel/index.js +10 -4
- package/build/dataforms-layouts/panel/index.js.map +1 -1
- package/build/dataforms-layouts/regular/index.js +6 -3
- package/build/dataforms-layouts/regular/index.js.map +1 -1
- package/build/dataviews-layouts/grid/density-picker.js +23 -52
- package/build/dataviews-layouts/grid/density-picker.js.map +1 -1
- package/build/dataviews-layouts/grid/index.js +1 -1
- package/build/dataviews-layouts/grid/index.js.map +1 -1
- package/build/dataviews-layouts/index.js +48 -2
- package/build/dataviews-layouts/index.js.map +1 -1
- package/build/dataviews-layouts/list/index.js +124 -80
- package/build/dataviews-layouts/list/index.js.map +1 -1
- package/build/dataviews-layouts/table/column-header-menu.js +52 -57
- package/build/dataviews-layouts/table/column-header-menu.js.map +1 -1
- package/build/dataviews-layouts/table/index.js +7 -35
- package/build/dataviews-layouts/table/index.js.map +1 -1
- package/build/field-types/datetime.js +30 -0
- package/build/field-types/datetime.js.map +1 -0
- package/build/field-types/index.js +4 -0
- package/build/field-types/index.js.map +1 -1
- package/build/field-types/integer.js +1 -60
- package/build/field-types/integer.js.map +1 -1
- package/build/field-types/text.js +1 -60
- package/build/field-types/text.js.map +1 -1
- package/build/normalize-fields.js +10 -9
- package/build/normalize-fields.js.map +1 -1
- package/build/types.js.map +1 -1
- package/build-module/components/dataviews/index.js +10 -14
- package/build-module/components/dataviews/index.js.map +1 -1
- package/build-module/components/dataviews-bulk-actions/index.js +145 -143
- package/build-module/components/dataviews-bulk-actions/index.js.map +1 -1
- package/build-module/components/dataviews-filters/add-filter.js +4 -6
- package/build-module/components/dataviews-filters/add-filter.js.map +1 -1
- package/build-module/components/dataviews-filters/index.js +3 -0
- package/build-module/components/dataviews-filters/index.js.map +1 -1
- package/build-module/components/dataviews-filters/search-widget.js +30 -23
- package/build-module/components/dataviews-filters/search-widget.js.map +1 -1
- package/build-module/components/dataviews-footer/index.js +38 -0
- package/build-module/components/dataviews-footer/index.js.map +1 -0
- package/build-module/components/dataviews-item-actions/index.js +5 -8
- package/build-module/components/dataviews-item-actions/index.js.map +1 -1
- package/build-module/components/dataviews-pagination/index.js +28 -20
- package/build-module/components/dataviews-pagination/index.js.map +1 -1
- package/build-module/components/dataviews-view-config/index.js +203 -47
- package/build-module/components/dataviews-view-config/index.js.map +1 -1
- package/build-module/dataform-controls/datetime.js +43 -0
- package/build-module/dataform-controls/datetime.js.map +1 -0
- package/build-module/dataform-controls/index.js +42 -0
- package/build-module/dataform-controls/index.js.map +1 -0
- package/build-module/dataform-controls/integer.js +38 -0
- package/build-module/dataform-controls/integer.js.map +1 -0
- package/build-module/dataform-controls/radio.js +38 -0
- package/build-module/dataform-controls/radio.js.map +1 -0
- package/build-module/dataform-controls/select.js +51 -0
- package/build-module/dataform-controls/select.js.map +1 -0
- package/build-module/dataform-controls/text.js +38 -0
- package/build-module/dataform-controls/text.js.map +1 -0
- package/build-module/dataforms-layouts/panel/index.js +10 -4
- package/build-module/dataforms-layouts/panel/index.js.map +1 -1
- package/build-module/dataforms-layouts/regular/index.js +6 -3
- package/build-module/dataforms-layouts/regular/index.js.map +1 -1
- package/build-module/dataviews-layouts/grid/density-picker.js +25 -56
- package/build-module/dataviews-layouts/grid/density-picker.js.map +1 -1
- package/build-module/dataviews-layouts/grid/index.js +1 -1
- package/build-module/dataviews-layouts/grid/index.js.map +1 -1
- package/build-module/dataviews-layouts/index.js +45 -1
- package/build-module/dataviews-layouts/index.js.map +1 -1
- package/build-module/dataviews-layouts/list/index.js +125 -80
- package/build-module/dataviews-layouts/list/index.js.map +1 -1
- package/build-module/dataviews-layouts/table/column-header-menu.js +52 -57
- package/build-module/dataviews-layouts/table/column-header-menu.js.map +1 -1
- package/build-module/dataviews-layouts/table/index.js +9 -37
- package/build-module/dataviews-layouts/table/index.js.map +1 -1
- package/build-module/field-types/datetime.js +24 -0
- package/build-module/field-types/datetime.js.map +1 -0
- package/build-module/field-types/index.js +4 -0
- package/build-module/field-types/index.js.map +1 -1
- package/build-module/field-types/integer.js +2 -60
- package/build-module/field-types/integer.js.map +1 -1
- package/build-module/field-types/text.js +2 -60
- package/build-module/field-types/text.js.map +1 -1
- package/build-module/normalize-fields.js +11 -9
- package/build-module/normalize-fields.js.map +1 -1
- package/build-module/types.js.map +1 -1
- package/build-style/style-rtl.css +93 -80
- package/build-style/style.css +93 -80
- package/build-types/components/dataform/stories/index.story.d.ts.map +1 -1
- package/build-types/components/dataviews/index.d.ts.map +1 -1
- package/build-types/components/dataviews/stories/fixtures.d.ts +28 -113
- package/build-types/components/dataviews/stories/fixtures.d.ts.map +1 -1
- package/build-types/components/dataviews/stories/index.story.d.ts +12 -44
- package/build-types/components/dataviews/stories/index.story.d.ts.map +1 -1
- package/build-types/components/dataviews-bulk-actions/index.d.ts +11 -1
- package/build-types/components/dataviews-bulk-actions/index.d.ts.map +1 -1
- package/build-types/components/dataviews-filters/add-filter.d.ts.map +1 -1
- package/build-types/components/dataviews-filters/index.d.ts +1 -1
- package/build-types/components/dataviews-filters/index.d.ts.map +1 -1
- package/build-types/components/dataviews-filters/search-widget.d.ts.map +1 -1
- package/build-types/components/dataviews-footer/index.d.ts +2 -0
- package/build-types/components/dataviews-footer/index.d.ts.map +1 -0
- package/build-types/components/dataviews-item-actions/index.d.ts.map +1 -1
- package/build-types/components/dataviews-pagination/index.d.ts.map +1 -1
- package/build-types/components/dataviews-view-config/index.d.ts +4 -3
- package/build-types/components/dataviews-view-config/index.d.ts.map +1 -1
- package/build-types/dataform-controls/datetime.d.ts +6 -0
- package/build-types/dataform-controls/datetime.d.ts.map +1 -0
- package/build-types/dataform-controls/index.d.ts +11 -0
- package/build-types/dataform-controls/index.d.ts.map +1 -0
- package/build-types/dataform-controls/integer.d.ts +6 -0
- package/build-types/dataform-controls/integer.d.ts.map +1 -0
- package/build-types/dataform-controls/radio.d.ts +6 -0
- package/build-types/dataform-controls/radio.d.ts.map +1 -0
- package/build-types/dataform-controls/select.d.ts +6 -0
- package/build-types/dataform-controls/select.d.ts.map +1 -0
- package/build-types/dataform-controls/text.d.ts +6 -0
- package/build-types/dataform-controls/text.d.ts.map +1 -0
- package/build-types/dataforms-layouts/panel/index.d.ts.map +1 -1
- package/build-types/dataforms-layouts/regular/index.d.ts.map +1 -1
- package/build-types/dataviews-layouts/grid/density-picker.d.ts.map +1 -1
- package/build-types/dataviews-layouts/index.d.ts +4 -2
- package/build-types/dataviews-layouts/index.d.ts.map +1 -1
- package/build-types/dataviews-layouts/list/index.d.ts.map +1 -1
- package/build-types/dataviews-layouts/table/column-header-menu.d.ts.map +1 -1
- package/build-types/dataviews-layouts/table/index.d.ts.map +1 -1
- package/build-types/field-types/datetime.d.ts +13 -0
- package/build-types/field-types/datetime.d.ts.map +1 -0
- package/build-types/field-types/index.d.ts +1 -1
- package/build-types/field-types/index.d.ts.map +1 -1
- package/build-types/field-types/integer.d.ts +2 -3
- package/build-types/field-types/integer.d.ts.map +1 -1
- package/build-types/field-types/text.d.ts +2 -3
- package/build-types/field-types/text.d.ts.map +1 -1
- package/build-types/normalize-fields.d.ts.map +1 -1
- package/build-types/types.d.ts +43 -21
- package/build-types/types.d.ts.map +1 -1
- package/package.json +12 -12
- package/src/components/dataform/stories/index.story.tsx +43 -2
- package/src/components/dataviews/index.tsx +14 -18
- package/src/components/dataviews/stories/fixtures.tsx +690 -0
- package/src/components/dataviews/stories/index.story.tsx +164 -0
- package/src/components/dataviews/style.scss +2 -12
- package/src/components/dataviews-bulk-actions/index.tsx +264 -213
- package/src/components/dataviews-bulk-actions/style.scss +9 -4
- package/src/components/dataviews-filters/add-filter.tsx +7 -11
- package/src/components/dataviews-filters/index.tsx +3 -0
- package/src/components/dataviews-filters/search-widget.tsx +46 -25
- package/src/components/dataviews-filters/style.scss +13 -3
- package/src/components/dataviews-footer/index.tsx +50 -0
- package/src/components/dataviews-footer/style.scss +40 -0
- package/src/components/dataviews-item-actions/index.tsx +8 -14
- package/src/components/dataviews-pagination/index.tsx +40 -21
- package/src/components/dataviews-pagination/style.scss +7 -21
- package/src/components/dataviews-view-config/index.tsx +297 -69
- package/src/components/dataviews-view-config/style.scss +25 -0
- package/src/dataform-controls/datetime.tsx +43 -0
- package/src/dataform-controls/index.tsx +61 -0
- package/src/dataform-controls/integer.tsx +38 -0
- package/src/dataform-controls/radio.tsx +42 -0
- package/src/dataform-controls/select.tsx +52 -0
- package/src/dataform-controls/style.scss +4 -0
- package/src/dataform-controls/text.tsx +40 -0
- package/src/dataforms-layouts/panel/index.tsx +8 -2
- package/src/dataforms-layouts/regular/index.tsx +6 -2
- package/src/dataviews-layouts/grid/density-picker.tsx +33 -67
- package/src/dataviews-layouts/grid/index.tsx +1 -1
- package/src/dataviews-layouts/grid/style.scss +1 -5
- package/src/dataviews-layouts/index.ts +63 -2
- package/src/dataviews-layouts/list/index.tsx +199 -123
- package/src/dataviews-layouts/list/style.scss +10 -4
- package/src/dataviews-layouts/table/column-header-menu.tsx +86 -90
- package/src/dataviews-layouts/table/index.tsx +8 -65
- package/src/dataviews-layouts/table/style.scss +0 -5
- package/src/field-types/datetime.tsx +28 -0
- package/src/field-types/index.tsx +5 -0
- package/src/field-types/integer.tsx +2 -71
- package/src/field-types/text.tsx +2 -70
- package/src/normalize-fields.ts +10 -10
- package/src/style.scss +2 -1
- package/src/test/filter-and-sort-data-view.js +28 -0
- package/src/types.ts +56 -32
- package/tsconfig.tsbuildinfo +1 -1
- package/build/components/dataviews-bulk-actions-toolbar/index.js +0 -207
- package/build/components/dataviews-bulk-actions-toolbar/index.js.map +0 -1
- package/build-module/components/dataviews-bulk-actions-toolbar/index.js +0 -201
- package/build-module/components/dataviews-bulk-actions-toolbar/index.js.map +0 -1
- package/build-types/components/dataviews-bulk-actions-toolbar/index.d.ts +0 -2
- package/build-types/components/dataviews-bulk-actions-toolbar/index.d.ts.map +0 -1
- package/src/components/dataviews/stories/fixtures.js +0 -222
- package/src/components/dataviews/stories/index.story.js +0 -65
- package/src/components/dataviews-bulk-actions-toolbar/index.tsx +0 -288
- package/src/components/dataviews-bulk-actions-toolbar/style.scss +0 -45
|
@@ -2,14 +2,11 @@
|
|
|
2
2
|
* External dependencies
|
|
3
3
|
*/
|
|
4
4
|
import clsx from 'clsx';
|
|
5
|
-
// Import CompositeStore type, which is not exported from @wordpress/components.
|
|
6
|
-
// eslint-disable-next-line no-restricted-imports
|
|
7
|
-
import type { CompositeStore } from '@ariakit/react';
|
|
8
5
|
|
|
9
6
|
/**
|
|
10
7
|
* WordPress dependencies
|
|
11
8
|
*/
|
|
12
|
-
import { useInstanceId } from '@wordpress/compose';
|
|
9
|
+
import { useInstanceId, usePrevious } from '@wordpress/compose';
|
|
13
10
|
import {
|
|
14
11
|
__experimentalHStack as HStack,
|
|
15
12
|
__experimentalVStack as VStack,
|
|
@@ -41,39 +38,115 @@ import type { Action, NormalizedField, ViewListProps } from '../../types';
|
|
|
41
38
|
|
|
42
39
|
interface ListViewItemProps< Item > {
|
|
43
40
|
actions: Action< Item >[];
|
|
44
|
-
|
|
41
|
+
idPrefix: string;
|
|
45
42
|
isSelected: boolean;
|
|
46
43
|
item: Item;
|
|
47
44
|
mediaField?: NormalizedField< Item >;
|
|
48
45
|
onSelect: ( item: Item ) => void;
|
|
49
46
|
primaryField?: NormalizedField< Item >;
|
|
50
|
-
store: CompositeStore;
|
|
51
47
|
visibleFields: NormalizedField< Item >[];
|
|
48
|
+
onDropdownTriggerKeyDown: React.KeyboardEventHandler< HTMLButtonElement >;
|
|
52
49
|
}
|
|
53
50
|
|
|
54
51
|
const {
|
|
55
|
-
useCompositeStoreV2: useCompositeStore,
|
|
56
52
|
CompositeV2: Composite,
|
|
57
53
|
CompositeItemV2: CompositeItem,
|
|
58
54
|
CompositeRowV2: CompositeRow,
|
|
59
55
|
DropdownMenuV2: DropdownMenu,
|
|
60
56
|
} = unlock( componentsPrivateApis );
|
|
61
57
|
|
|
58
|
+
function generateItemWrapperCompositeId( idPrefix: string ) {
|
|
59
|
+
return `${ idPrefix }-item-wrapper`;
|
|
60
|
+
}
|
|
61
|
+
function generatePrimaryActionCompositeId(
|
|
62
|
+
idPrefix: string,
|
|
63
|
+
primaryActionId: string
|
|
64
|
+
) {
|
|
65
|
+
return `${ idPrefix }-primary-action-${ primaryActionId }`;
|
|
66
|
+
}
|
|
67
|
+
function generateDropdownTriggerCompositeId( idPrefix: string ) {
|
|
68
|
+
return `${ idPrefix }-dropdown`;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function PrimaryActionGridCell< Item >( {
|
|
72
|
+
idPrefix,
|
|
73
|
+
primaryAction,
|
|
74
|
+
item,
|
|
75
|
+
}: {
|
|
76
|
+
idPrefix: string;
|
|
77
|
+
primaryAction: Action< Item >;
|
|
78
|
+
item: Item;
|
|
79
|
+
} ) {
|
|
80
|
+
const registry = useRegistry();
|
|
81
|
+
const [ isModalOpen, setIsModalOpen ] = useState( false );
|
|
82
|
+
|
|
83
|
+
const compositeItemId = generatePrimaryActionCompositeId(
|
|
84
|
+
idPrefix,
|
|
85
|
+
primaryAction.id
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
const label =
|
|
89
|
+
typeof primaryAction.label === 'string'
|
|
90
|
+
? primaryAction.label
|
|
91
|
+
: primaryAction.label( [ item ] );
|
|
92
|
+
|
|
93
|
+
return 'RenderModal' in primaryAction ? (
|
|
94
|
+
<div role="gridcell" key={ primaryAction.id }>
|
|
95
|
+
<CompositeItem
|
|
96
|
+
id={ compositeItemId }
|
|
97
|
+
render={
|
|
98
|
+
<Button
|
|
99
|
+
label={ label }
|
|
100
|
+
icon={ primaryAction.icon }
|
|
101
|
+
isDestructive={ primaryAction.isDestructive }
|
|
102
|
+
size="small"
|
|
103
|
+
onClick={ () => setIsModalOpen( true ) }
|
|
104
|
+
/>
|
|
105
|
+
}
|
|
106
|
+
>
|
|
107
|
+
{ isModalOpen && (
|
|
108
|
+
<ActionModal< Item >
|
|
109
|
+
action={ primaryAction }
|
|
110
|
+
items={ [ item ] }
|
|
111
|
+
closeModal={ () => setIsModalOpen( false ) }
|
|
112
|
+
/>
|
|
113
|
+
) }
|
|
114
|
+
</CompositeItem>
|
|
115
|
+
</div>
|
|
116
|
+
) : (
|
|
117
|
+
<div role="gridcell" key={ primaryAction.id }>
|
|
118
|
+
<CompositeItem
|
|
119
|
+
id={ compositeItemId }
|
|
120
|
+
render={
|
|
121
|
+
<Button
|
|
122
|
+
label={ label }
|
|
123
|
+
icon={ primaryAction.icon }
|
|
124
|
+
isDestructive={ primaryAction.isDestructive }
|
|
125
|
+
size="small"
|
|
126
|
+
onClick={ () => {
|
|
127
|
+
primaryAction.callback( [ item ], { registry } );
|
|
128
|
+
} }
|
|
129
|
+
/>
|
|
130
|
+
}
|
|
131
|
+
/>
|
|
132
|
+
</div>
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
|
|
62
136
|
function ListItem< Item >( {
|
|
63
137
|
actions,
|
|
64
|
-
|
|
138
|
+
idPrefix,
|
|
65
139
|
isSelected,
|
|
66
140
|
item,
|
|
67
141
|
mediaField,
|
|
68
142
|
onSelect,
|
|
69
143
|
primaryField,
|
|
70
|
-
store,
|
|
71
144
|
visibleFields,
|
|
145
|
+
onDropdownTriggerKeyDown,
|
|
72
146
|
}: ListViewItemProps< Item > ) {
|
|
73
|
-
const registry = useRegistry();
|
|
74
147
|
const itemRef = useRef< HTMLElement >( null );
|
|
75
|
-
const labelId = `${
|
|
76
|
-
const descriptionId = `${
|
|
148
|
+
const labelId = `${ idPrefix }-label`;
|
|
149
|
+
const descriptionId = `${ idPrefix }-description`;
|
|
77
150
|
|
|
78
151
|
const [ isHovered, setIsHovered ] = useState( false );
|
|
79
152
|
const handleMouseEnter = () => {
|
|
@@ -108,13 +181,6 @@ function ListItem< Item >( {
|
|
|
108
181
|
};
|
|
109
182
|
}, [ actions, item ] );
|
|
110
183
|
|
|
111
|
-
const [ isModalOpen, setIsModalOpen ] = useState( false );
|
|
112
|
-
const primaryActionLabel =
|
|
113
|
-
primaryAction &&
|
|
114
|
-
( typeof primaryAction.label === 'string'
|
|
115
|
-
? primaryAction.label
|
|
116
|
-
: primaryAction.label( [ item ] ) );
|
|
117
|
-
|
|
118
184
|
const renderedMediaField = mediaField?.render ? (
|
|
119
185
|
<mediaField.render item={ item } />
|
|
120
186
|
) : (
|
|
@@ -144,10 +210,9 @@ function ListItem< Item >( {
|
|
|
144
210
|
>
|
|
145
211
|
<div role="gridcell">
|
|
146
212
|
<CompositeItem
|
|
147
|
-
store={ store }
|
|
148
213
|
render={ <div /> }
|
|
149
214
|
role="button"
|
|
150
|
-
id={
|
|
215
|
+
id={ generateItemWrapperCompositeId( idPrefix ) }
|
|
151
216
|
aria-pressed={ isSelected }
|
|
152
217
|
aria-labelledby={ labelId }
|
|
153
218
|
aria-describedby={ descriptionId }
|
|
@@ -207,65 +272,20 @@ function ListItem< Item >( {
|
|
|
207
272
|
width: 'auto',
|
|
208
273
|
} }
|
|
209
274
|
>
|
|
210
|
-
{ primaryAction &&
|
|
211
|
-
<
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
label={ primaryActionLabel }
|
|
217
|
-
icon={ primaryAction.icon }
|
|
218
|
-
isDestructive={
|
|
219
|
-
primaryAction.isDestructive
|
|
220
|
-
}
|
|
221
|
-
size="small"
|
|
222
|
-
onClick={ () =>
|
|
223
|
-
setIsModalOpen( true )
|
|
224
|
-
}
|
|
225
|
-
/>
|
|
226
|
-
}
|
|
227
|
-
>
|
|
228
|
-
{ isModalOpen && (
|
|
229
|
-
<ActionModal< Item >
|
|
230
|
-
action={ primaryAction }
|
|
231
|
-
items={ [ item ] }
|
|
232
|
-
closeModal={ () =>
|
|
233
|
-
setIsModalOpen( false )
|
|
234
|
-
}
|
|
235
|
-
/>
|
|
236
|
-
) }
|
|
237
|
-
</CompositeItem>
|
|
238
|
-
</div>
|
|
275
|
+
{ primaryAction && (
|
|
276
|
+
<PrimaryActionGridCell
|
|
277
|
+
idPrefix={ idPrefix }
|
|
278
|
+
primaryAction={ primaryAction }
|
|
279
|
+
item={ item }
|
|
280
|
+
/>
|
|
239
281
|
) }
|
|
240
|
-
{ primaryAction &&
|
|
241
|
-
! ( 'RenderModal' in primaryAction ) && (
|
|
242
|
-
<div role="gridcell" key={ primaryAction.id }>
|
|
243
|
-
<CompositeItem
|
|
244
|
-
store={ store }
|
|
245
|
-
render={
|
|
246
|
-
<Button
|
|
247
|
-
label={ primaryActionLabel }
|
|
248
|
-
icon={ primaryAction.icon }
|
|
249
|
-
isDestructive={
|
|
250
|
-
primaryAction.isDestructive
|
|
251
|
-
}
|
|
252
|
-
size="small"
|
|
253
|
-
onClick={ () => {
|
|
254
|
-
primaryAction.callback(
|
|
255
|
-
[ item ],
|
|
256
|
-
{ registry }
|
|
257
|
-
);
|
|
258
|
-
} }
|
|
259
|
-
/>
|
|
260
|
-
}
|
|
261
|
-
/>
|
|
262
|
-
</div>
|
|
263
|
-
) }
|
|
264
282
|
<div role="gridcell">
|
|
265
283
|
<DropdownMenu
|
|
266
284
|
trigger={
|
|
267
285
|
<CompositeItem
|
|
268
|
-
|
|
286
|
+
id={ generateDropdownTriggerCompositeId(
|
|
287
|
+
idPrefix
|
|
288
|
+
) }
|
|
269
289
|
render={
|
|
270
290
|
<Button
|
|
271
291
|
size="small"
|
|
@@ -273,30 +293,9 @@ function ListItem< Item >( {
|
|
|
273
293
|
label={ __( 'Actions' ) }
|
|
274
294
|
accessibleWhenDisabled
|
|
275
295
|
disabled={ ! actions.length }
|
|
276
|
-
onKeyDown={
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
} ) => {
|
|
280
|
-
if (
|
|
281
|
-
event.key ===
|
|
282
|
-
'ArrowDown'
|
|
283
|
-
) {
|
|
284
|
-
// Prevent the default behaviour (open dropdown menu) and go down.
|
|
285
|
-
event.preventDefault();
|
|
286
|
-
store.move(
|
|
287
|
-
store.down()
|
|
288
|
-
);
|
|
289
|
-
}
|
|
290
|
-
if (
|
|
291
|
-
event.key === 'ArrowUp'
|
|
292
|
-
) {
|
|
293
|
-
// Prevent the default behavior (open dropdown menu) and go up.
|
|
294
|
-
event.preventDefault();
|
|
295
|
-
store.move(
|
|
296
|
-
store.up()
|
|
297
|
-
);
|
|
298
|
-
}
|
|
299
|
-
} }
|
|
296
|
+
onKeyDown={
|
|
297
|
+
onDropdownTriggerKeyDown
|
|
298
|
+
}
|
|
300
299
|
/>
|
|
301
300
|
}
|
|
302
301
|
/>
|
|
@@ -328,6 +327,7 @@ export default function ViewList< Item >( props: ViewListProps< Item > ) {
|
|
|
328
327
|
view,
|
|
329
328
|
} = props;
|
|
330
329
|
const baseId = useInstanceId( ViewList, 'view-list' );
|
|
330
|
+
|
|
331
331
|
const selectedItem = data?.findLast( ( item ) =>
|
|
332
332
|
selection.includes( getItemId( item ) )
|
|
333
333
|
);
|
|
@@ -350,33 +350,108 @@ export default function ViewList< Item >( props: ViewListProps< Item > ) {
|
|
|
350
350
|
const onSelect = ( item: Item ) =>
|
|
351
351
|
onChangeSelection( [ getItemId( item ) ] );
|
|
352
352
|
|
|
353
|
-
const
|
|
354
|
-
( item
|
|
355
|
-
item ? `${ baseId }-${ getItemId( item ) }` : undefined,
|
|
353
|
+
const generateCompositeItemIdPrefix = useCallback(
|
|
354
|
+
( item: Item ) => `${ baseId }-${ getItemId( item ) }`,
|
|
356
355
|
[ baseId, getItemId ]
|
|
357
356
|
);
|
|
358
357
|
|
|
359
|
-
const
|
|
360
|
-
|
|
361
|
-
|
|
358
|
+
const isActiveCompositeItem = useCallback(
|
|
359
|
+
( item: Item, idToCheck: string ) => {
|
|
360
|
+
// All composite items use the same prefix in their IDs.
|
|
361
|
+
return idToCheck.startsWith(
|
|
362
|
+
generateCompositeItemIdPrefix( item )
|
|
363
|
+
);
|
|
364
|
+
},
|
|
365
|
+
[ generateCompositeItemIdPrefix ]
|
|
366
|
+
);
|
|
362
367
|
|
|
363
|
-
//
|
|
364
|
-
const
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
368
|
+
// Controlled state for the active composite item.
|
|
369
|
+
const [ activeCompositeId, setActiveCompositeId ] = useState<
|
|
370
|
+
string | null | undefined
|
|
371
|
+
>( undefined );
|
|
372
|
+
|
|
373
|
+
// Update the active composite item when the selected item changes.
|
|
374
|
+
useEffect( () => {
|
|
375
|
+
if ( selectedItem ) {
|
|
376
|
+
setActiveCompositeId(
|
|
377
|
+
generateItemWrapperCompositeId(
|
|
378
|
+
generateCompositeItemIdPrefix( selectedItem )
|
|
379
|
+
)
|
|
380
|
+
);
|
|
381
|
+
}
|
|
382
|
+
}, [ selectedItem, generateCompositeItemIdPrefix ] );
|
|
383
|
+
|
|
384
|
+
const activeItemIndex = data.findIndex( ( item ) =>
|
|
385
|
+
isActiveCompositeItem( item, activeCompositeId ?? '' )
|
|
369
386
|
);
|
|
387
|
+
const previousActiveItemIndex = usePrevious( activeItemIndex );
|
|
388
|
+
const isActiveIdInList = activeItemIndex !== -1;
|
|
389
|
+
|
|
390
|
+
const selectCompositeItem = useCallback(
|
|
391
|
+
(
|
|
392
|
+
targetIndex: number,
|
|
393
|
+
// Allows invokers to specify a custom function to generate the
|
|
394
|
+
// target composite item ID
|
|
395
|
+
generateCompositeId: ( idPrefix: string ) => string
|
|
396
|
+
) => {
|
|
397
|
+
// Clamping between 0 and data.length - 1 to avoid out of bounds.
|
|
398
|
+
const clampedIndex = Math.min(
|
|
399
|
+
data.length - 1,
|
|
400
|
+
Math.max( 0, targetIndex )
|
|
401
|
+
);
|
|
402
|
+
const itemIdPrefix = generateCompositeItemIdPrefix(
|
|
403
|
+
data[ clampedIndex ]
|
|
404
|
+
);
|
|
405
|
+
const targetCompositeItemId = generateCompositeId( itemIdPrefix );
|
|
406
|
+
|
|
407
|
+
setActiveCompositeId( targetCompositeItemId );
|
|
408
|
+
document.getElementById( targetCompositeItemId )?.focus();
|
|
409
|
+
},
|
|
410
|
+
[ data, generateCompositeItemIdPrefix ]
|
|
411
|
+
);
|
|
412
|
+
|
|
413
|
+
// Select a new active composite item when the current active item
|
|
414
|
+
// is removed from the list.
|
|
370
415
|
useEffect( () => {
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
416
|
+
const wasActiveIdInList =
|
|
417
|
+
previousActiveItemIndex !== undefined &&
|
|
418
|
+
previousActiveItemIndex !== -1;
|
|
419
|
+
if ( ! isActiveIdInList && wasActiveIdInList ) {
|
|
420
|
+
// By picking `previousActiveItemIndex` as the next item index, we are
|
|
421
|
+
// basically picking the item that would have been after the deleted one.
|
|
422
|
+
// If the previously active (and removed) item was the last of the list,
|
|
423
|
+
// we will select the item before it — which is the new last item.
|
|
424
|
+
selectCompositeItem(
|
|
425
|
+
previousActiveItemIndex,
|
|
426
|
+
generateItemWrapperCompositeId
|
|
427
|
+
);
|
|
378
428
|
}
|
|
379
|
-
}, [ isActiveIdInList ] );
|
|
429
|
+
}, [ isActiveIdInList, selectCompositeItem, previousActiveItemIndex ] );
|
|
430
|
+
|
|
431
|
+
// Prevent the default behavior (open dropdown menu) and instead select the
|
|
432
|
+
// dropdown menu trigger on the previous/next row.
|
|
433
|
+
// https://github.com/ariakit/ariakit/issues/3768
|
|
434
|
+
const onDropdownTriggerKeyDown = useCallback(
|
|
435
|
+
( event: React.KeyboardEvent< HTMLButtonElement > ) => {
|
|
436
|
+
if ( event.key === 'ArrowDown' ) {
|
|
437
|
+
// Select the dropdown menu trigger item in the next row.
|
|
438
|
+
event.preventDefault();
|
|
439
|
+
selectCompositeItem(
|
|
440
|
+
activeItemIndex + 1,
|
|
441
|
+
generateDropdownTriggerCompositeId
|
|
442
|
+
);
|
|
443
|
+
}
|
|
444
|
+
if ( event.key === 'ArrowUp' ) {
|
|
445
|
+
// Select the dropdown menu trigger item in the previous row.
|
|
446
|
+
event.preventDefault();
|
|
447
|
+
selectCompositeItem(
|
|
448
|
+
activeItemIndex - 1,
|
|
449
|
+
generateDropdownTriggerCompositeId
|
|
450
|
+
);
|
|
451
|
+
}
|
|
452
|
+
},
|
|
453
|
+
[ selectCompositeItem, activeItemIndex ]
|
|
454
|
+
);
|
|
380
455
|
|
|
381
456
|
const hasData = data?.length;
|
|
382
457
|
if ( ! hasData ) {
|
|
@@ -400,22 +475,23 @@ export default function ViewList< Item >( props: ViewListProps< Item > ) {
|
|
|
400
475
|
render={ <ul /> }
|
|
401
476
|
className="dataviews-view-list"
|
|
402
477
|
role="grid"
|
|
403
|
-
|
|
478
|
+
activeId={ activeCompositeId }
|
|
479
|
+
setActiveId={ setActiveCompositeId }
|
|
404
480
|
>
|
|
405
481
|
{ data.map( ( item ) => {
|
|
406
|
-
const id =
|
|
482
|
+
const id = generateCompositeItemIdPrefix( item );
|
|
407
483
|
return (
|
|
408
484
|
<ListItem
|
|
409
485
|
key={ id }
|
|
410
|
-
|
|
486
|
+
idPrefix={ id }
|
|
411
487
|
actions={ actions }
|
|
412
488
|
item={ item }
|
|
413
489
|
isSelected={ item === selectedItem }
|
|
414
490
|
onSelect={ onSelect }
|
|
415
491
|
mediaField={ mediaField }
|
|
416
492
|
primaryField={ primaryField }
|
|
417
|
-
store={ store }
|
|
418
493
|
visibleFields={ visibleFields }
|
|
494
|
+
onDropdownTriggerKeyDown={ onDropdownTriggerKeyDown }
|
|
419
495
|
/>
|
|
420
496
|
);
|
|
421
497
|
} ) }
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
ul.dataviews-view-list {
|
|
2
|
+
list-style-type: none;
|
|
3
|
+
}
|
|
4
|
+
|
|
1
5
|
.dataviews-view-list {
|
|
2
6
|
margin: 0 0 auto;
|
|
3
7
|
|
|
@@ -73,6 +77,7 @@
|
|
|
73
77
|
color: $gray-900;
|
|
74
78
|
}
|
|
75
79
|
&:hover,
|
|
80
|
+
&.is-hovered,
|
|
76
81
|
&:focus-within {
|
|
77
82
|
color: var(--wp-admin-theme-color);
|
|
78
83
|
background-color: #f8f8f8;
|
|
@@ -100,6 +105,7 @@
|
|
|
100
105
|
}
|
|
101
106
|
|
|
102
107
|
.dataviews-view-list__item {
|
|
108
|
+
box-sizing: border-box;
|
|
103
109
|
padding: $grid-unit-20 $grid-unit-30;
|
|
104
110
|
width: 100%;
|
|
105
111
|
scroll-margin: $grid-unit-10 0;
|
|
@@ -108,12 +114,12 @@
|
|
|
108
114
|
&::before {
|
|
109
115
|
position: absolute;
|
|
110
116
|
content: "";
|
|
111
|
-
top:
|
|
117
|
+
top: var(--wp-admin-border-width-focus);
|
|
112
118
|
right: var(--wp-admin-border-width-focus);
|
|
113
119
|
bottom: var(--wp-admin-border-width-focus);
|
|
114
120
|
left: var(--wp-admin-border-width-focus);
|
|
115
121
|
box-shadow: inset 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color);
|
|
116
|
-
border-radius: $radius-
|
|
122
|
+
border-radius: $radius-small;
|
|
117
123
|
}
|
|
118
124
|
}
|
|
119
125
|
.dataviews-view-list__primary-field {
|
|
@@ -151,8 +157,8 @@
|
|
|
151
157
|
}
|
|
152
158
|
|
|
153
159
|
.dataviews-view-list__media-placeholder {
|
|
154
|
-
|
|
155
|
-
height: $grid-unit-
|
|
160
|
+
width: $grid-unit-05 * 13;
|
|
161
|
+
height: $grid-unit-05 * 13;
|
|
156
162
|
background-color: $gray-200;
|
|
157
163
|
}
|
|
158
164
|
|