@wordpress/dataviews 3.0.0 → 4.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.
Files changed (274) hide show
  1. package/CHANGELOG.md +8 -1
  2. package/README.md +19 -4
  3. package/build/{dataform.js → components/dataform/index.js} +5 -5
  4. package/build/components/dataform/index.js.map +1 -0
  5. package/build/components/dataviews/index.js +115 -0
  6. package/build/components/dataviews/index.js.map +1 -0
  7. package/build/{bulk-actions.js → components/dataviews-bulk-actions/index.js} +39 -16
  8. package/build/components/dataviews-bulk-actions/index.js.map +1 -0
  9. package/build/{bulk-actions-toolbar.js → components/dataviews-bulk-actions-toolbar/index.js} +36 -19
  10. package/build/components/dataviews-bulk-actions-toolbar/index.js.map +1 -0
  11. package/build/components/dataviews-context/index.js +36 -0
  12. package/build/components/dataviews-context/index.js.map +1 -0
  13. package/build/{add-filter.js → components/dataviews-filters/add-filter.js} +2 -2
  14. package/build/components/dataviews-filters/add-filter.js.map +1 -0
  15. package/build/{filter-summary.js → components/dataviews-filters/filter-summary.js} +9 -9
  16. package/build/components/dataviews-filters/filter-summary.js.map +1 -0
  17. package/build/{filters.js → components/dataviews-filters/index.js} +14 -15
  18. package/build/components/dataviews-filters/index.js.map +1 -0
  19. package/build/components/dataviews-filters/reset-filters.js.map +1 -0
  20. package/build/{search-widget.js → components/dataviews-filters/search-widget.js} +13 -13
  21. package/build/components/dataviews-filters/search-widget.js.map +1 -0
  22. package/build/{item-actions.js → components/dataviews-item-actions/index.js} +2 -2
  23. package/build/components/dataviews-item-actions/index.js.map +1 -0
  24. package/build/components/dataviews-layout/index.js +53 -0
  25. package/build/components/dataviews-layout/index.js.map +1 -0
  26. package/build/{pagination.js → components/dataviews-pagination/index.js} +16 -13
  27. package/build/components/dataviews-pagination/index.js.map +1 -0
  28. package/build/{search.js → components/dataviews-search/index.js} +10 -6
  29. package/build/components/dataviews-search/index.js.map +1 -0
  30. package/build/{single-selection-checkbox.js → components/dataviews-selection-checkbox/index.js} +6 -6
  31. package/build/components/dataviews-selection-checkbox/index.js.map +1 -0
  32. package/build/{view-actions.js → components/dataviews-view-config/index.js} +19 -16
  33. package/build/components/dataviews-view-config/index.js.map +1 -0
  34. package/build/index.js +2 -2
  35. package/build/index.js.map +1 -1
  36. package/build/layouts/grid/density-picker.js +143 -0
  37. package/build/layouts/grid/density-picker.js.map +1 -0
  38. package/build/{view-grid.js → layouts/grid/index.js} +34 -35
  39. package/build/layouts/grid/index.js.map +1 -0
  40. package/build/layouts/index.js +52 -0
  41. package/build/layouts/index.js.map +1 -0
  42. package/build/{view-list.js → layouts/list/index.js} +26 -23
  43. package/build/layouts/list/index.js.map +1 -0
  44. package/build/layouts/table/column-header-menu.js +196 -0
  45. package/build/layouts/table/column-header-menu.js.map +1 -0
  46. package/build/layouts/table/index.js +350 -0
  47. package/build/layouts/table/index.js.map +1 -0
  48. package/build/normalize-fields.js +1 -1
  49. package/build/normalize-fields.js.map +1 -1
  50. package/build/types.js.map +1 -1
  51. package/build-module/{dataform.js → components/dataform/index.js} +5 -5
  52. package/build-module/components/dataform/index.js.map +1 -0
  53. package/build-module/components/dataviews/index.js +108 -0
  54. package/build-module/components/dataviews/index.js.map +1 -0
  55. package/build-module/{bulk-actions.js → components/dataviews-bulk-actions/index.js} +39 -17
  56. package/build-module/components/dataviews-bulk-actions/index.js.map +1 -0
  57. package/build-module/{bulk-actions-toolbar.js → components/dataviews-bulk-actions-toolbar/index.js} +35 -19
  58. package/build-module/components/dataviews-bulk-actions-toolbar/index.js.map +1 -0
  59. package/build-module/components/dataviews-context/index.js +30 -0
  60. package/build-module/components/dataviews-context/index.js.map +1 -0
  61. package/build-module/{add-filter.js → components/dataviews-filters/add-filter.js} +2 -2
  62. package/build-module/components/dataviews-filters/add-filter.js.map +1 -0
  63. package/build-module/{filter-summary.js → components/dataviews-filters/filter-summary.js} +9 -9
  64. package/build-module/components/dataviews-filters/filter-summary.js.map +1 -0
  65. package/build-module/{filters.js → components/dataviews-filters/index.js} +15 -16
  66. package/build-module/components/dataviews-filters/index.js.map +1 -0
  67. package/build-module/components/dataviews-filters/reset-filters.js.map +1 -0
  68. package/build-module/{search-widget.js → components/dataviews-filters/search-widget.js} +13 -13
  69. package/build-module/components/dataviews-filters/search-widget.js.map +1 -0
  70. package/build-module/{item-actions.js → components/dataviews-item-actions/index.js} +2 -2
  71. package/build-module/components/dataviews-item-actions/index.js.map +1 -0
  72. package/build-module/components/dataviews-layout/index.js +45 -0
  73. package/build-module/components/dataviews-layout/index.js.map +1 -0
  74. package/build-module/{pagination.js → components/dataviews-pagination/index.js} +17 -15
  75. package/build-module/components/dataviews-pagination/index.js.map +1 -0
  76. package/build-module/{search.js → components/dataviews-search/index.js} +10 -7
  77. package/build-module/components/dataviews-search/index.js.map +1 -0
  78. package/build-module/{single-selection-checkbox.js → components/dataviews-selection-checkbox/index.js} +5 -5
  79. package/build-module/components/dataviews-selection-checkbox/index.js.map +1 -0
  80. package/build-module/{view-actions.js → components/dataviews-view-config/index.js} +19 -17
  81. package/build-module/components/dataviews-view-config/index.js.map +1 -0
  82. package/build-module/index.js +2 -2
  83. package/build-module/index.js.map +1 -1
  84. package/build-module/layouts/grid/density-picker.js +138 -0
  85. package/build-module/layouts/grid/density-picker.js.map +1 -0
  86. package/build-module/{view-grid.js → layouts/grid/index.js} +31 -32
  87. package/build-module/layouts/grid/index.js.map +1 -0
  88. package/build-module/layouts/index.js +43 -0
  89. package/build-module/layouts/index.js.map +1 -0
  90. package/build-module/{view-list.js → layouts/list/index.js} +24 -21
  91. package/build-module/layouts/list/index.js.map +1 -0
  92. package/build-module/layouts/table/column-header-menu.js +190 -0
  93. package/build-module/layouts/table/column-header-menu.js.map +1 -0
  94. package/build-module/layouts/table/index.js +344 -0
  95. package/build-module/layouts/table/index.js.map +1 -0
  96. package/build-module/normalize-fields.js +1 -1
  97. package/build-module/normalize-fields.js.map +1 -1
  98. package/build-module/types.js.map +1 -1
  99. package/build-style/style-rtl.css +607 -545
  100. package/build-style/style.css +607 -545
  101. package/build-types/{dataform.d.ts → components/dataform/index.d.ts} +2 -2
  102. package/build-types/components/dataform/index.d.ts.map +1 -0
  103. package/build-types/components/dataform/stories/index.story.d.ts +11 -0
  104. package/build-types/components/dataform/stories/index.story.d.ts.map +1 -0
  105. package/build-types/{dataviews.d.ts → components/dataviews/index.d.ts} +9 -7
  106. package/build-types/components/dataviews/index.d.ts.map +1 -0
  107. package/build-types/{stories → components/dataviews/stories}/fixtures.d.ts +7 -19
  108. package/build-types/components/dataviews/stories/fixtures.d.ts.map +1 -0
  109. package/build-types/components/dataviews/stories/index.story.d.ts +46 -0
  110. package/build-types/components/dataviews/stories/index.story.d.ts.map +1 -0
  111. package/build-types/components/dataviews-bulk-actions/index.d.ts +5 -0
  112. package/build-types/components/dataviews-bulk-actions/index.d.ts.map +1 -0
  113. package/build-types/components/dataviews-bulk-actions-toolbar/index.d.ts +2 -0
  114. package/build-types/components/dataviews-bulk-actions-toolbar/index.d.ts.map +1 -0
  115. package/build-types/components/dataviews-context/index.d.ts +26 -0
  116. package/build-types/components/dataviews-context/index.d.ts.map +1 -0
  117. package/build-types/{add-filter.d.ts → components/dataviews-filters/add-filter.d.ts} +1 -2
  118. package/build-types/components/dataviews-filters/add-filter.d.ts.map +1 -0
  119. package/build-types/{filter-summary.d.ts → components/dataviews-filters/filter-summary.d.ts} +1 -1
  120. package/build-types/components/dataviews-filters/filter-summary.d.ts.map +1 -0
  121. package/build-types/components/dataviews-filters/index.d.ts +4 -0
  122. package/build-types/components/dataviews-filters/index.d.ts.map +1 -0
  123. package/build-types/{reset-filters.d.ts → components/dataviews-filters/reset-filters.d.ts} +1 -2
  124. package/build-types/components/dataviews-filters/reset-filters.d.ts.map +1 -0
  125. package/build-types/{search-widget.d.ts → components/dataviews-filters/search-widget.d.ts} +1 -2
  126. package/build-types/components/dataviews-filters/search-widget.d.ts.map +1 -0
  127. package/build-types/{item-actions.d.ts → components/dataviews-item-actions/index.d.ts} +2 -2
  128. package/build-types/components/dataviews-item-actions/index.d.ts.map +1 -0
  129. package/build-types/components/dataviews-layout/index.d.ts +2 -0
  130. package/build-types/components/dataviews-layout/index.d.ts.map +1 -0
  131. package/build-types/components/dataviews-pagination/index.d.ts +4 -0
  132. package/build-types/components/dataviews-pagination/index.d.ts.map +1 -0
  133. package/build-types/components/dataviews-search/index.d.ts +6 -0
  134. package/build-types/components/dataviews-search/index.d.ts.map +1 -0
  135. package/build-types/components/dataviews-selection-checkbox/index.d.ts +16 -0
  136. package/build-types/components/dataviews-selection-checkbox/index.d.ts.map +1 -0
  137. package/build-types/components/dataviews-view-config/index.d.ts +8 -0
  138. package/build-types/components/dataviews-view-config/index.d.ts.map +1 -0
  139. package/build-types/index.d.ts +2 -2
  140. package/build-types/index.d.ts.map +1 -1
  141. package/build-types/layouts/grid/density-picker.d.ts +5 -0
  142. package/build-types/layouts/grid/density-picker.d.ts.map +1 -0
  143. package/build-types/layouts/grid/index.d.ts +3 -0
  144. package/build-types/layouts/grid/index.d.ts.map +1 -0
  145. package/build-types/{layouts.d.ts → layouts/index.d.ts} +6 -5
  146. package/build-types/layouts/index.d.ts.map +1 -0
  147. package/build-types/layouts/list/index.d.ts +3 -0
  148. package/build-types/layouts/list/index.d.ts.map +1 -0
  149. package/build-types/layouts/table/column-header-menu.d.ts +17 -0
  150. package/build-types/layouts/table/column-header-menu.d.ts.map +1 -0
  151. package/build-types/layouts/table/index.d.ts +4 -0
  152. package/build-types/layouts/table/index.d.ts.map +1 -0
  153. package/build-types/types.d.ts +42 -23
  154. package/build-types/types.d.ts.map +1 -1
  155. package/package.json +10 -10
  156. package/src/{dataform.tsx → components/dataform/index.tsx} +5 -5
  157. package/src/components/dataform/stories/index.story.tsx +42 -0
  158. package/src/components/dataviews/index.tsx +149 -0
  159. package/src/{stories → components/dataviews/stories}/fixtures.js +7 -11
  160. package/src/{stories → components/dataviews/stories}/index.story.js +17 -3
  161. package/src/components/dataviews/style.scss +97 -0
  162. package/src/{bulk-actions.tsx → components/dataviews-bulk-actions/index.tsx} +46 -29
  163. package/src/components/dataviews-bulk-actions/style.scss +7 -0
  164. package/src/{bulk-actions-toolbar.tsx → components/dataviews-bulk-actions-toolbar/index.tsx} +42 -30
  165. package/src/components/dataviews-bulk-actions-toolbar/style.scss +45 -0
  166. package/src/components/dataviews-context/index.ts +49 -0
  167. package/src/{add-filter.tsx → components/dataviews-filters/add-filter.tsx} +3 -3
  168. package/src/{filter-summary.tsx → components/dataviews-filters/filter-summary.tsx} +18 -10
  169. package/src/{filters.tsx → components/dataviews-filters/index.tsx} +10 -24
  170. package/src/{reset-filters.tsx → components/dataviews-filters/reset-filters.tsx} +1 -1
  171. package/src/{search-widget.tsx → components/dataviews-filters/search-widget.tsx} +14 -14
  172. package/src/components/dataviews-filters/style.scss +252 -0
  173. package/src/{item-actions.tsx → components/dataviews-item-actions/index.tsx} +2 -2
  174. package/src/components/dataviews-item-actions/style.scss +3 -0
  175. package/src/components/dataviews-layout/index.tsx +51 -0
  176. package/src/{pagination.tsx → components/dataviews-pagination/index.tsx} +13 -21
  177. package/src/components/dataviews-pagination/style.scss +26 -0
  178. package/src/{search.tsx → components/dataviews-search/index.tsx} +5 -10
  179. package/src/{single-selection-checkbox.tsx → components/dataviews-selection-checkbox/index.tsx} +9 -9
  180. package/src/components/dataviews-selection-checkbox/style.scss +14 -0
  181. package/src/{view-actions.tsx → components/dataviews-view-config/index.tsx} +16 -22
  182. package/src/index.ts +2 -2
  183. package/src/layouts/grid/density-picker.tsx +136 -0
  184. package/src/{view-grid.tsx → layouts/grid/index.tsx} +28 -29
  185. package/src/layouts/grid/style.scss +140 -0
  186. package/src/layouts/index.ts +66 -0
  187. package/src/{view-list.tsx → layouts/list/index.tsx} +30 -17
  188. package/src/layouts/list/style.scss +189 -0
  189. package/src/layouts/table/column-header-menu.tsx +268 -0
  190. package/src/layouts/table/index.tsx +471 -0
  191. package/src/layouts/table/style.scss +201 -0
  192. package/src/normalize-fields.ts +1 -1
  193. package/src/style.scss +11 -907
  194. package/src/test/filter-and-sort-data-view.js +1 -1
  195. package/src/types.ts +48 -24
  196. package/tsconfig.tsbuildinfo +1 -1
  197. package/build/add-filter.js.map +0 -1
  198. package/build/bulk-actions-toolbar.js.map +0 -1
  199. package/build/bulk-actions.js.map +0 -1
  200. package/build/dataform.js.map +0 -1
  201. package/build/dataviews.js +0 -125
  202. package/build/dataviews.js.map +0 -1
  203. package/build/filter-summary.js.map +0 -1
  204. package/build/filters.js.map +0 -1
  205. package/build/item-actions.js.map +0 -1
  206. package/build/layouts.js +0 -38
  207. package/build/layouts.js.map +0 -1
  208. package/build/pagination.js.map +0 -1
  209. package/build/reset-filters.js.map +0 -1
  210. package/build/search-widget.js.map +0 -1
  211. package/build/search.js.map +0 -1
  212. package/build/single-selection-checkbox.js.map +0 -1
  213. package/build/view-actions.js.map +0 -1
  214. package/build/view-grid.js.map +0 -1
  215. package/build/view-list.js.map +0 -1
  216. package/build/view-table.js +0 -400
  217. package/build/view-table.js.map +0 -1
  218. package/build-module/add-filter.js.map +0 -1
  219. package/build-module/bulk-actions-toolbar.js.map +0 -1
  220. package/build-module/bulk-actions.js.map +0 -1
  221. package/build-module/dataform.js.map +0 -1
  222. package/build-module/dataviews.js +0 -116
  223. package/build-module/dataviews.js.map +0 -1
  224. package/build-module/filter-summary.js.map +0 -1
  225. package/build-module/filters.js.map +0 -1
  226. package/build-module/item-actions.js.map +0 -1
  227. package/build-module/layouts.js +0 -30
  228. package/build-module/layouts.js.map +0 -1
  229. package/build-module/pagination.js.map +0 -1
  230. package/build-module/reset-filters.js.map +0 -1
  231. package/build-module/search-widget.js.map +0 -1
  232. package/build-module/search.js.map +0 -1
  233. package/build-module/single-selection-checkbox.js.map +0 -1
  234. package/build-module/view-actions.js.map +0 -1
  235. package/build-module/view-grid.js.map +0 -1
  236. package/build-module/view-list.js.map +0 -1
  237. package/build-module/view-table.js +0 -393
  238. package/build-module/view-table.js.map +0 -1
  239. package/build-types/add-filter.d.ts.map +0 -1
  240. package/build-types/bulk-actions-toolbar.d.ts +0 -13
  241. package/build-types/bulk-actions-toolbar.d.ts.map +0 -1
  242. package/build-types/bulk-actions.d.ts +0 -15
  243. package/build-types/bulk-actions.d.ts.map +0 -1
  244. package/build-types/dataform.d.ts.map +0 -1
  245. package/build-types/dataviews.d.ts.map +0 -1
  246. package/build-types/filter-summary.d.ts.map +0 -1
  247. package/build-types/filters.d.ts +0 -13
  248. package/build-types/filters.d.ts.map +0 -1
  249. package/build-types/item-actions.d.ts.map +0 -1
  250. package/build-types/layouts.d.ts.map +0 -1
  251. package/build-types/pagination.d.ts +0 -16
  252. package/build-types/pagination.d.ts.map +0 -1
  253. package/build-types/reset-filters.d.ts.map +0 -1
  254. package/build-types/search-widget.d.ts.map +0 -1
  255. package/build-types/search.d.ts +0 -13
  256. package/build-types/search.d.ts.map +0 -1
  257. package/build-types/single-selection-checkbox.d.ts +0 -17
  258. package/build-types/single-selection-checkbox.d.ts.map +0 -1
  259. package/build-types/stories/fixtures.d.ts.map +0 -1
  260. package/build-types/stories/index.story.d.ts +0 -29
  261. package/build-types/stories/index.story.d.ts.map +0 -1
  262. package/build-types/view-actions.d.ts +0 -12
  263. package/build-types/view-actions.d.ts.map +0 -1
  264. package/build-types/view-grid.d.ts +0 -4
  265. package/build-types/view-grid.d.ts.map +0 -1
  266. package/build-types/view-list.d.ts +0 -4
  267. package/build-types/view-list.d.ts.map +0 -1
  268. package/build-types/view-table.d.ts +0 -5
  269. package/build-types/view-table.d.ts.map +0 -1
  270. package/src/dataviews.tsx +0 -183
  271. package/src/layouts.ts +0 -39
  272. package/src/view-table.tsx +0 -592
  273. /package/build/{reset-filters.js → components/dataviews-filters/reset-filters.js} +0 -0
  274. /package/build-module/{reset-filters.js → components/dataviews-filters/reset-filters.js} +0 -0
@@ -7,15 +7,16 @@ import {
7
7
  Modal,
8
8
  } from '@wordpress/components';
9
9
  import { __, sprintf, _n } from '@wordpress/i18n';
10
- import { useMemo, useState, useCallback } from '@wordpress/element';
10
+ import { useMemo, useState, useCallback, useContext } from '@wordpress/element';
11
11
  import { useRegistry } from '@wordpress/data';
12
12
 
13
13
  /**
14
14
  * Internal dependencies
15
15
  */
16
- import { unlock } from './lock-unlock';
17
- import type { Action, ActionModal } from './types';
18
- import type { SetSelection } from './private-types';
16
+ import DataViewsContext from '../dataviews-context';
17
+ import { LAYOUT_TABLE, LAYOUT_GRID } from '../../constants';
18
+ import { unlock } from '../../lock-unlock';
19
+ import type { Action, ActionModal } from '../../types';
19
20
 
20
21
  const {
21
22
  DropdownMenuV2: DropdownMenu,
@@ -43,14 +44,6 @@ interface ActionsMenuGroupProps< Item > {
43
44
  setActionWithModal: ( action?: ActionModal< Item > ) => void;
44
45
  }
45
46
 
46
- interface BulkActionsProps< Item > {
47
- data: Item[];
48
- actions: Action< Item >[];
49
- selection: string[];
50
- onSelectionChange: SetSelection;
51
- getItemId: ( item: Item ) => string;
52
- }
53
-
54
47
  export function useHasAPossibleBulkAction< Item >(
55
48
  actions: Action< Item >[],
56
49
  item: Item
@@ -105,7 +98,7 @@ function ActionWithModal< Item >( {
105
98
  title={ ! hideModalHeader ? label : undefined }
106
99
  __experimentalHideHeader={ !! hideModalHeader }
107
100
  onRequestClose={ onCloseModal }
108
- overlayClassName="dataviews-action-modal"
101
+ overlayClassName="dataviews-bulk-actions__modal"
109
102
  >
110
103
  <RenderModal
111
104
  items={ eligibleItems }
@@ -133,7 +126,6 @@ function BulkActionItem< Item >( {
133
126
  return (
134
127
  <DropdownMenuItem
135
128
  key={ action.id }
136
- disabled={ eligibleItems.length === 0 }
137
129
  hideOnClick={ ! shouldShowModal }
138
130
  onClick={ async () => {
139
131
  if ( shouldShowModal ) {
@@ -142,9 +134,7 @@ function BulkActionItem< Item >( {
142
134
  action.callback( eligibleItems, { registry } );
143
135
  }
144
136
  } }
145
- suffix={
146
- eligibleItems.length > 0 ? eligibleItems.length : undefined
147
- }
137
+ suffix={ eligibleItems.length }
148
138
  >
149
139
  { action.label }
150
140
  </DropdownMenuItem>
@@ -156,10 +146,20 @@ function ActionsMenuGroup< Item >( {
156
146
  selectedItems,
157
147
  setActionWithModal,
158
148
  }: ActionsMenuGroupProps< Item > ) {
149
+ const elligibleActions = useMemo( () => {
150
+ return actions.filter( ( action ) => {
151
+ return selectedItems.some(
152
+ ( item ) => ! action.isEligible || action.isEligible( item )
153
+ );
154
+ } );
155
+ }, [ actions, selectedItems ] );
156
+ if ( ! elligibleActions.length ) {
157
+ return null;
158
+ }
159
159
  return (
160
160
  <>
161
161
  <DropdownMenuGroup>
162
- { actions.map( ( action ) => (
162
+ { elligibleActions.map( ( action ) => (
163
163
  <BulkActionItem
164
164
  key={ action.id }
165
165
  action={ action }
@@ -173,20 +173,21 @@ function ActionsMenuGroup< Item >( {
173
173
  );
174
174
  }
175
175
 
176
- export default function BulkActions< Item >( {
177
- data,
178
- actions,
179
- selection,
180
- onSelectionChange,
181
- getItemId,
182
- }: BulkActionsProps< Item > ) {
176
+ function _BulkActions() {
177
+ const {
178
+ data,
179
+ actions = [],
180
+ selection,
181
+ onChangeSelection,
182
+ getItemId,
183
+ } = useContext( DataViewsContext );
183
184
  const bulkActions = useMemo(
184
185
  () => actions.filter( ( action ) => action.supportsBulk ),
185
186
  [ actions ]
186
187
  );
187
188
  const [ isMenuOpen, onMenuOpenChange ] = useState( false );
188
189
  const [ actionWithModal, setActionWithModal ] = useState<
189
- ActionModal< Item > | undefined
190
+ ActionModal< any > | undefined
190
191
  >();
191
192
  const selectableItems = useMemo( () => {
192
193
  return data.filter( ( item ) => {
@@ -220,7 +221,7 @@ export default function BulkActions< Item >( {
220
221
  style={ { minWidth: '240px' } }
221
222
  trigger={
222
223
  <Button
223
- className="dataviews-bulk-edit-button"
224
+ className="dataviews-bulk-actions__edit-button"
224
225
  __next40pxDefaultSize
225
226
  variant="tertiary"
226
227
  size="compact"
@@ -249,7 +250,7 @@ export default function BulkActions< Item >( {
249
250
  disabled={ areAllSelected }
250
251
  hideOnClick={ false }
251
252
  onClick={ () => {
252
- onSelectionChange(
253
+ onChangeSelection(
253
254
  selectableItems.map( ( item ) =>
254
255
  getItemId( item )
255
256
  )
@@ -263,7 +264,7 @@ export default function BulkActions< Item >( {
263
264
  disabled={ selection.length === 0 }
264
265
  hideOnClick={ false }
265
266
  onClick={ () => {
266
- onSelectionChange( [] );
267
+ onChangeSelection( [] );
267
268
  } }
268
269
  >
269
270
  { __( 'Deselect' ) }
@@ -281,3 +282,19 @@ export default function BulkActions< Item >( {
281
282
  </>
282
283
  );
283
284
  }
285
+
286
+ export default function BulkActions() {
287
+ const { data, actions = [], view } = useContext( DataViewsContext );
288
+ const hasPossibleBulkAction = useSomeItemHasAPossibleBulkAction(
289
+ actions,
290
+ data
291
+ );
292
+ if (
293
+ ! [ LAYOUT_TABLE, LAYOUT_GRID ].includes( view.type ) ||
294
+ ! hasPossibleBulkAction
295
+ ) {
296
+ return null;
297
+ }
298
+
299
+ return <_BulkActions />;
300
+ }
@@ -0,0 +1,7 @@
1
+ .dataviews-bulk-actions__modal {
2
+ z-index: z-index(".dataviews-bulk-actions__modal");
3
+ }
4
+
5
+ .dataviews-bulk-actions__edit-button.components-button {
6
+ flex-shrink: 0;
7
+ }
@@ -8,7 +8,7 @@ import {
8
8
  __unstableMotion as motion,
9
9
  __unstableAnimatePresence as AnimatePresence,
10
10
  } from '@wordpress/components';
11
- import { useMemo, useState, useRef } from '@wordpress/element';
11
+ import { useMemo, useState, useRef, useContext } from '@wordpress/element';
12
12
  import { _n, sprintf, __ } from '@wordpress/i18n';
13
13
  import { closeSmall } from '@wordpress/icons';
14
14
  import { useReducedMotion } from '@wordpress/compose';
@@ -17,10 +17,13 @@ import { useRegistry } from '@wordpress/data';
17
17
  /**
18
18
  * Internal dependencies
19
19
  */
20
- import { ActionWithModal } from './item-actions';
21
- import type { Action } from './types';
22
- import type { ActionTriggerProps } from './item-actions';
23
- import type { SetSelection } from './private-types';
20
+ import { useSomeItemHasAPossibleBulkAction } from '../dataviews-bulk-actions';
21
+ import DataViewsContext from '../dataviews-context';
22
+ import { ActionWithModal } from '../dataviews-item-actions';
23
+ import { LAYOUT_GRID, LAYOUT_TABLE } from '../../constants';
24
+ import type { Action } from '../../types';
25
+ import type { ActionTriggerProps } from '../dataviews-item-actions';
26
+ import type { SetSelection } from '../../private-types';
24
27
 
25
28
  interface ActionButtonProps< Item > {
26
29
  action: Action< Item >;
@@ -33,15 +36,7 @@ interface ToolbarContentProps< Item > {
33
36
  selection: string[];
34
37
  actionsToShow: Action< Item >[];
35
38
  selectedItems: Item[];
36
- onSelectionChange: SetSelection;
37
- }
38
-
39
- interface BulkActionsToolbarProps< Item > {
40
- data: Item[];
41
- selection: string[];
42
- actions: Action< Item >[];
43
- onSelectionChange: SetSelection;
44
- getItemId: ( item: Item ) => string;
39
+ onChangeSelection: SetSelection;
45
40
  }
46
41
 
47
42
  const SNACKBAR_VARIANTS = {
@@ -131,12 +126,12 @@ function renderToolbarContent< Item >(
131
126
  selectedItems: Item[],
132
127
  actionInProgress: string | null,
133
128
  setActionInProgress: ( actionId: string | null ) => void,
134
- onSelectionChange: SetSelection
129
+ onChangeSelection: SetSelection
135
130
  ) {
136
131
  return (
137
132
  <>
138
133
  <ToolbarGroup>
139
- <div className="dataviews-bulk-actions__selection-count">
134
+ <div className="dataviews-bulk-actions-toolbar__selection-count">
140
135
  { selection.length === 1
141
136
  ? __( '1 item selected' )
142
137
  : sprintf(
@@ -171,7 +166,7 @@ function renderToolbarContent< Item >(
171
166
  label={ __( 'Cancel' ) }
172
167
  disabled={ !! actionInProgress }
173
168
  onClick={ () => {
174
- onSelectionChange( EMPTY_ARRAY );
169
+ onChangeSelection( EMPTY_ARRAY );
175
170
  } }
176
171
  />
177
172
  </ToolbarGroup>
@@ -183,7 +178,7 @@ function ToolbarContent< Item >( {
183
178
  selection,
184
179
  actionsToShow,
185
180
  selectedItems,
186
- onSelectionChange,
181
+ onChangeSelection,
187
182
  }: ToolbarContentProps< Item > ) {
188
183
  const [ actionInProgress, setActionInProgress ] = useState< string | null >(
189
184
  null
@@ -199,7 +194,7 @@ function ToolbarContent< Item >( {
199
194
  selectedItems,
200
195
  actionInProgress,
201
196
  setActionInProgress,
202
- onSelectionChange
197
+ onChangeSelection
203
198
  );
204
199
  } else if ( ! buttons.current ) {
205
200
  buttons.current = renderToolbarContent(
@@ -208,19 +203,20 @@ function ToolbarContent< Item >( {
208
203
  selectedItems,
209
204
  actionInProgress,
210
205
  setActionInProgress,
211
- onSelectionChange
206
+ onChangeSelection
212
207
  );
213
208
  }
214
209
  return buttons.current;
215
210
  }
216
211
 
217
- export default function BulkActionsToolbar< Item >( {
218
- data,
219
- selection,
220
- actions = EMPTY_ARRAY,
221
- onSelectionChange,
222
- getItemId,
223
- }: BulkActionsToolbarProps< Item > ) {
212
+ function _BulkActionsToolbar() {
213
+ const {
214
+ data,
215
+ selection,
216
+ actions = EMPTY_ARRAY,
217
+ onChangeSelection,
218
+ getItemId,
219
+ } = useContext( DataViewsContext );
224
220
  const isReducedMotion = useReducedMotion();
225
221
  const selectedItems = useMemo( () => {
226
222
  return data.filter( ( item ) =>
@@ -258,15 +254,15 @@ export default function BulkActionsToolbar< Item >( {
258
254
  animate="open"
259
255
  exit="exit"
260
256
  variants={ isReducedMotion ? undefined : SNACKBAR_VARIANTS }
261
- className="dataviews-bulk-actions"
257
+ className="dataviews-bulk-actions-toolbar"
262
258
  >
263
259
  <Toolbar label={ __( 'Bulk actions' ) }>
264
- <div className="dataviews-bulk-actions-toolbar-wrapper">
260
+ <div className="dataviews-bulk-actions-toolbar__wrapper">
265
261
  <ToolbarContent
266
262
  selection={ selection }
267
263
  actionsToShow={ actionsToShow }
268
264
  selectedItems={ selectedItems }
269
- onSelectionChange={ onSelectionChange }
265
+ onChangeSelection={ onChangeSelection }
270
266
  />
271
267
  </div>
272
268
  </Toolbar>
@@ -274,3 +270,19 @@ export default function BulkActionsToolbar< Item >( {
274
270
  </AnimatePresence>
275
271
  );
276
272
  }
273
+
274
+ export default function BulkActionsToolbar() {
275
+ const { data, actions = [], view } = useContext( DataViewsContext );
276
+ const hasPossibleBulkAction = useSomeItemHasAPossibleBulkAction(
277
+ actions,
278
+ data
279
+ );
280
+ if (
281
+ ! [ LAYOUT_TABLE, LAYOUT_GRID ].includes( view.type ) ||
282
+ ! hasPossibleBulkAction
283
+ ) {
284
+ return null;
285
+ }
286
+
287
+ return <_BulkActionsToolbar />;
288
+ }
@@ -0,0 +1,45 @@
1
+ .dataviews-bulk-actions-toolbar {
2
+ position: sticky;
3
+ display: flex;
4
+ flex-direction: column;
5
+ align-content: center;
6
+ flex-wrap: wrap;
7
+ width: fit-content;
8
+ margin-left: auto;
9
+ margin-right: auto;
10
+ bottom: $grid-unit-30;
11
+ z-index: z-index(".dataviews-bulk-actions-toolbar");
12
+
13
+ .components-accessible-toolbar {
14
+ border-color: $gray-300;
15
+ box-shadow: $shadow-popover;
16
+
17
+ .components-toolbar-group {
18
+ border-color: $gray-200;
19
+
20
+ &:last-child {
21
+ border: 0;
22
+ }
23
+ }
24
+ }
25
+
26
+ .dataviews-bulk-actions-toolbar__selection-count {
27
+ display: flex;
28
+ align-items: center;
29
+ margin: 0 $grid-unit-10 0 $grid-unit-10;
30
+ }
31
+ }
32
+
33
+ .dataviews-bulk-actions-toolbar__wrapper {
34
+ display: flex;
35
+ flex-grow: 1;
36
+ width: 100%;
37
+
38
+ .components-toolbar-group {
39
+ align-items: center;
40
+ }
41
+
42
+ .components-button.is-busy {
43
+ max-height: $button-size;
44
+ }
45
+ }
@@ -0,0 +1,49 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { createContext } from '@wordpress/element';
5
+
6
+ /**
7
+ * Internal dependencies
8
+ */
9
+ import type { View, Action, NormalizedField } from '../../types';
10
+ import type { SetSelection } from '../../private-types';
11
+ import { LAYOUT_TABLE } from '../../constants';
12
+
13
+ type DataViewsContextType< Item > = {
14
+ view: View;
15
+ onChangeView: ( view: View ) => void;
16
+ fields: NormalizedField< Item >[];
17
+ actions?: Action< Item >[];
18
+ data: Item[];
19
+ isLoading?: boolean;
20
+ paginationInfo: {
21
+ totalItems: number;
22
+ totalPages: number;
23
+ };
24
+ selection: string[];
25
+ onChangeSelection: SetSelection;
26
+ openedFilter: string | null;
27
+ setOpenedFilter: ( openedFilter: string | null ) => void;
28
+ getItemId: ( item: Item ) => string;
29
+ density: number;
30
+ };
31
+
32
+ const DataViewsContext = createContext< DataViewsContextType< any > >( {
33
+ view: { type: LAYOUT_TABLE },
34
+ onChangeView: () => {},
35
+ fields: [],
36
+ data: [],
37
+ paginationInfo: {
38
+ totalItems: 0,
39
+ totalPages: 0,
40
+ },
41
+ selection: [],
42
+ onChangeSelection: () => {},
43
+ setOpenedFilter: () => {},
44
+ openedFilter: null,
45
+ getItemId: ( item ) => item.id,
46
+ density: 0,
47
+ } );
48
+
49
+ export default DataViewsContext;
@@ -16,8 +16,8 @@ import { forwardRef } from '@wordpress/element';
16
16
  /**
17
17
  * Internal dependencies
18
18
  */
19
- import { unlock } from './lock-unlock';
20
- import type { NormalizedFilter, View } from './types';
19
+ import { unlock } from '../../lock-unlock';
20
+ import type { NormalizedFilter, View } from '../../types';
21
21
 
22
22
  const {
23
23
  DropdownMenuV2: DropdownMenu,
@@ -46,7 +46,7 @@ function AddFilter(
46
46
  <Button
47
47
  accessibleWhenDisabled
48
48
  size="compact"
49
- className="dataviews-filters-button"
49
+ className="dataviews-filters__button"
50
50
  variant="tertiary"
51
51
  disabled={ ! inactiveFilters.length }
52
52
  ref={ ref }
@@ -35,8 +35,14 @@ import {
35
35
  OPERATOR_IS_NONE,
36
36
  OPERATOR_IS_ALL,
37
37
  OPERATOR_IS_NOT_ALL,
38
- } from './constants';
39
- import type { Filter, NormalizedFilter, Operator, Option, View } from './types';
38
+ } from '../../constants';
39
+ import type {
40
+ Filter,
41
+ NormalizedFilter,
42
+ Operator,
43
+ Option,
44
+ View,
45
+ } from '../../types';
40
46
 
41
47
  interface FilterTextProps {
42
48
  activeElements: Option[];
@@ -65,8 +71,10 @@ const FilterText = ( {
65
71
  }
66
72
 
67
73
  const filterTextWrappers = {
68
- Name: <span className="dataviews-filter-summary__filter-text-name" />,
69
- Value: <span className="dataviews-filter-summary__filter-text-value" />,
74
+ Name: <span className="dataviews-filters__summary-filter-text-name" />,
75
+ Value: (
76
+ <span className="dataviews-filters__summary-filter-text-value" />
77
+ ),
70
78
  };
71
79
 
72
80
  if ( filterInView?.operator === OPERATOR_IS_ANY ) {
@@ -166,9 +174,9 @@ function OperatorSelector( {
166
174
  <HStack
167
175
  spacing={ 2 }
168
176
  justify="flex-start"
169
- className="dataviews-filter-summary__operators-container"
177
+ className="dataviews-filters__summary-operators-container"
170
178
  >
171
- <FlexItem className="dataviews-filter-summary__operators-filter-name">
179
+ <FlexItem className="dataviews-filters__summary-operators-filter-name">
172
180
  { filter.name }
173
181
  </FlexItem>
174
182
 
@@ -239,13 +247,13 @@ export default function FilterSummary( {
239
247
  return (
240
248
  <Dropdown
241
249
  defaultOpen={ openedFilter === filter.field }
242
- contentClassName="dataviews-filter-summary__popover"
250
+ contentClassName="dataviews-filters__summary-popover"
243
251
  popoverProps={ { placement: 'bottom-start', role: 'dialog' } }
244
252
  onClose={ () => {
245
253
  toggleRef.current?.focus();
246
254
  } }
247
255
  renderToggle={ ( { isOpen, onToggle } ) => (
248
- <div className="dataviews-filter-summary__chip-container">
256
+ <div className="dataviews-filters__summary-chip-container">
249
257
  <Tooltip
250
258
  text={ sprintf(
251
259
  /* translators: 1: Filter name. */
@@ -256,7 +264,7 @@ export default function FilterSummary( {
256
264
  >
257
265
  <div
258
266
  className={ clsx(
259
- 'dataviews-filter-summary__chip',
267
+ 'dataviews-filters__summary-chip',
260
268
  {
261
269
  'has-reset': canResetOrRemove,
262
270
  'has-values': hasValues,
@@ -289,7 +297,7 @@ export default function FilterSummary( {
289
297
  >
290
298
  <button
291
299
  className={ clsx(
292
- 'dataviews-filter-summary__chip-remove',
300
+ 'dataviews-filters__summary-chip-remove',
293
301
  { 'has-values': hasValues }
294
302
  ) }
295
303
  onClick={ () => {
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
- import { memo, useRef } from '@wordpress/element';
4
+ import { memo, useContext, useRef } from '@wordpress/element';
5
5
  import { __experimentalHStack as HStack } from '@wordpress/components';
6
6
 
7
7
  /**
@@ -10,25 +10,14 @@ import { __experimentalHStack as HStack } from '@wordpress/components';
10
10
  import FilterSummary from './filter-summary';
11
11
  import AddFilter from './add-filter';
12
12
  import ResetFilters from './reset-filters';
13
- import { sanitizeOperators } from './utils';
14
- import { ALL_OPERATORS, OPERATOR_IS, OPERATOR_IS_NOT } from './constants';
15
- import type { NormalizedField, NormalizedFilter, View } from './types';
13
+ import DataViewsContext from '../dataviews-context';
14
+ import { sanitizeOperators } from '../../utils';
15
+ import { ALL_OPERATORS, OPERATOR_IS, OPERATOR_IS_NOT } from '../../constants';
16
+ import type { NormalizedFilter } from '../../types';
16
17
 
17
- interface FiltersProps< Item > {
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 >( {
26
- fields,
27
- view,
28
- onChangeView,
29
- openedFilter,
30
- setOpenedFilter,
31
- }: FiltersProps< Item > ) {
18
+ function Filters() {
19
+ const { fields, view, onChangeView, openedFilter, setOpenedFilter } =
20
+ useContext( DataViewsContext );
32
21
  const addFilterRef = useRef< HTMLButtonElement >( null );
33
22
  const filters: NormalizedFilter[] = [];
34
23
  fields.forEach( ( field ) => {
@@ -44,7 +33,7 @@ function _Filters< Item >( {
44
33
  const isPrimary = !! field.filterBy?.isPrimary;
45
34
  filters.push( {
46
35
  field: field.id,
47
- name: field.header,
36
+ name: field.label,
48
37
  elements: field.elements,
49
38
  singleSelection: operators.some( ( op ) =>
50
39
  [ OPERATOR_IS, OPERATOR_IS_NOT ].includes( op )
@@ -119,7 +108,4 @@ function _Filters< Item >( {
119
108
  );
120
109
  }
121
110
 
122
- // A type assertion is used here to keep the type argument.
123
- const Filters = memo( _Filters ) as typeof _Filters;
124
-
125
- export default Filters;
111
+ export default memo( Filters );
@@ -7,7 +7,7 @@ import { __ } from '@wordpress/i18n';
7
7
  /**
8
8
  * Internal dependencies
9
9
  */
10
- import type { NormalizedFilter, View } from './types';
10
+ import type { NormalizedFilter, View } from '../../types';
11
11
 
12
12
  interface ResetFilterProps {
13
13
  filters: NormalizedFilter[];
@@ -21,8 +21,8 @@ import { SVG, Circle } from '@wordpress/primitives';
21
21
  /**
22
22
  * Internal dependencies
23
23
  */
24
- import { unlock } from './lock-unlock';
25
- import type { Filter, NormalizedFilter, View } from './types';
24
+ import { unlock } from '../../lock-unlock';
25
+ import type { Filter, NormalizedFilter, View } from '../../types';
26
26
 
27
27
  const {
28
28
  CompositeV2: Composite,
@@ -101,7 +101,7 @@ function ListBox( { view, filter, onChangeView }: SearchWidgetProps ) {
101
101
  <Composite
102
102
  store={ compositeStore }
103
103
  role="listbox"
104
- className="dataviews-search-widget-listbox"
104
+ className="dataviews-filters__search-widget-listbox"
105
105
  aria-label={ sprintf(
106
106
  /* translators: List of items for a filter. 1: Filter name. e.g.: "List of: Author". */
107
107
  __( 'List of: %1$s' ),
@@ -124,7 +124,7 @@ function ListBox( { view, filter, onChangeView }: SearchWidgetProps ) {
124
124
  <div
125
125
  aria-label={ element.label }
126
126
  role="option"
127
- className="dataviews-search-widget-listitem"
127
+ className="dataviews-filters__search-widget-listitem"
128
128
  />
129
129
  }
130
130
  onClick={ () => {
@@ -174,7 +174,7 @@ function ListBox( { view, filter, onChangeView }: SearchWidgetProps ) {
174
174
  />
175
175
  }
176
176
  >
177
- <span className="dataviews-search-widget-listitem-check">
177
+ <span className="dataviews-filters__search-widget-listitem-check">
178
178
  { filter.singleSelection &&
179
179
  currentValue === element.value && (
180
180
  <Icon icon={ radioCheck } />
@@ -187,7 +187,7 @@ function ListBox( { view, filter, onChangeView }: SearchWidgetProps ) {
187
187
  <span>
188
188
  { element.label }
189
189
  { !! element.description && (
190
- <span className="dataviews-search-widget-listitem-description">
190
+ <span className="dataviews-filters__search-widget-listitem-description">
191
191
  { element.description }
192
192
  </span>
193
193
  ) }
@@ -247,7 +247,7 @@ function ComboboxList( { view, filter, onChangeView }: SearchWidgetProps ) {
247
247
  } }
248
248
  setValue={ setSearchValue }
249
249
  >
250
- <div className="dataviews-search-widget-filter-combobox__wrapper">
250
+ <div className="dataviews-filters__search-widget-filter-combobox__wrapper">
251
251
  <Ariakit.ComboboxLabel
252
252
  render={
253
253
  <VisuallyHidden>
@@ -260,14 +260,14 @@ function ComboboxList( { view, filter, onChangeView }: SearchWidgetProps ) {
260
260
  <Ariakit.Combobox
261
261
  autoSelect="always"
262
262
  placeholder={ __( 'Search' ) }
263
- className="dataviews-search-widget-filter-combobox__input"
263
+ className="dataviews-filters__search-widget-filter-combobox__input"
264
264
  />
265
- <div className="dataviews-search-widget-filter-combobox__icon">
265
+ <div className="dataviews-filters__search-widget-filter-combobox__icon">
266
266
  <Icon icon={ search } />
267
267
  </div>
268
268
  </div>
269
269
  <Ariakit.ComboboxList
270
- className="dataviews-search-widget-filter-combobox-list"
270
+ className="dataviews-filters__search-widget-filter-combobox-list"
271
271
  alwaysVisible
272
272
  >
273
273
  { matches.map( ( element ) => {
@@ -275,12 +275,12 @@ function ComboboxList( { view, filter, onChangeView }: SearchWidgetProps ) {
275
275
  <Ariakit.ComboboxItem
276
276
  key={ element.value }
277
277
  value={ element.value }
278
- className="dataviews-search-widget-listitem"
278
+ className="dataviews-filters__search-widget-listitem"
279
279
  hideOnClick={ false }
280
280
  setValueOnClick={ false }
281
281
  focusOnHover
282
282
  >
283
- <span className="dataviews-search-widget-listitem-check">
283
+ <span className="dataviews-filters__search-widget-listitem-check">
284
284
  { filter.singleSelection &&
285
285
  currentValue === element.value && (
286
286
  <Icon icon={ radioCheck } />
@@ -292,11 +292,11 @@ function ComboboxList( { view, filter, onChangeView }: SearchWidgetProps ) {
292
292
  </span>
293
293
  <span>
294
294
  <Ariakit.ComboboxItemValue
295
- className="dataviews-search-widget-filter-combobox-item-value"
295
+ className="dataviews-filters__search-widget-filter-combobox-item-value"
296
296
  value={ element.label }
297
297
  />
298
298
  { !! element.description && (
299
- <span className="dataviews-search-widget-listitem-description">
299
+ <span className="dataviews-filters__search-widget-listitem-description">
300
300
  { element.description }
301
301
  </span>
302
302
  ) }