@wordpress/dataviews 12.0.1-next.v.202602091733.0 → 12.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (260) hide show
  1. package/CHANGELOG.md +39 -1
  2. package/README.md +3 -1
  3. package/build/components/dataform-controls/color.cjs +19 -30
  4. package/build/components/dataform-controls/color.cjs.map +3 -3
  5. package/build/components/dataform-controls/date.cjs.map +1 -1
  6. package/build/components/dataform-controls/datetime.cjs +12 -21
  7. package/build/components/dataform-controls/datetime.cjs.map +2 -2
  8. package/build/components/dataform-layouts/card/index.cjs +112 -164
  9. package/build/components/dataform-layouts/card/index.cjs.map +3 -3
  10. package/build/components/dataform-layouts/index.cjs +1 -1
  11. package/build/components/dataform-layouts/index.cjs.map +1 -1
  12. package/build/components/dataform-layouts/normalize-form.cjs +2 -1
  13. package/build/components/dataform-layouts/normalize-form.cjs.map +2 -2
  14. package/build/components/dataform-layouts/panel/dropdown.cjs +79 -65
  15. package/build/components/dataform-layouts/panel/dropdown.cjs.map +3 -3
  16. package/build/components/dataform-layouts/panel/index.cjs +13 -177
  17. package/build/components/dataform-layouts/panel/index.cjs.map +3 -3
  18. package/build/components/dataform-layouts/panel/modal.cjs +12 -9
  19. package/build/components/dataform-layouts/panel/modal.cjs.map +3 -3
  20. package/build/components/dataform-layouts/panel/summary-button.cjs +125 -56
  21. package/build/components/dataform-layouts/panel/summary-button.cjs.map +3 -3
  22. package/build/components/dataform-layouts/panel/utils/get-first-validation-error.cjs +59 -0
  23. package/build/components/dataform-layouts/panel/utils/get-first-validation-error.cjs.map +7 -0
  24. package/build/components/dataform-layouts/panel/utils/get-label-classname.cjs +45 -0
  25. package/build/components/dataform-layouts/panel/utils/get-label-classname.cjs.map +7 -0
  26. package/build/components/dataform-layouts/panel/utils/get-label-content.cjs +36 -0
  27. package/build/components/dataform-layouts/panel/utils/get-label-content.cjs.map +7 -0
  28. package/build/components/dataform-layouts/panel/utils/use-field-from-form-field.cjs +77 -0
  29. package/build/components/dataform-layouts/panel/utils/use-field-from-form-field.cjs.map +7 -0
  30. package/build/components/dataviews-bulk-actions/index.cjs +2 -2
  31. package/build/components/dataviews-bulk-actions/index.cjs.map +2 -2
  32. package/build/components/dataviews-context/index.cjs +1 -0
  33. package/build/components/dataviews-context/index.cjs.map +2 -2
  34. package/build/components/dataviews-filters/filter.cjs.map +1 -1
  35. package/build/components/dataviews-filters/search-widget.cjs +25 -11
  36. package/build/components/dataviews-filters/search-widget.cjs.map +2 -2
  37. package/build/components/dataviews-filters/toggle.cjs +6 -2
  38. package/build/components/dataviews-filters/toggle.cjs.map +2 -2
  39. package/build/components/dataviews-footer/index.cjs +28 -12
  40. package/build/components/dataviews-footer/index.cjs.map +3 -3
  41. package/build/components/dataviews-item-actions/index.cjs +0 -1
  42. package/build/components/dataviews-item-actions/index.cjs.map +2 -2
  43. package/build/components/dataviews-layout/index.cjs +12 -0
  44. package/build/components/dataviews-layout/index.cjs.map +2 -2
  45. package/build/components/dataviews-layouts/activity/index.cjs +41 -26
  46. package/build/components/dataviews-layouts/activity/index.cjs.map +3 -3
  47. package/build/components/dataviews-layouts/grid/composite-grid.cjs +2 -0
  48. package/build/components/dataviews-layouts/grid/composite-grid.cjs.map +2 -2
  49. package/build/components/dataviews-layouts/grid/index.cjs +19 -14
  50. package/build/components/dataviews-layouts/grid/index.cjs.map +3 -3
  51. package/build/components/dataviews-layouts/list/index.cjs +13 -9
  52. package/build/components/dataviews-layouts/list/index.cjs.map +2 -2
  53. package/build/components/dataviews-layouts/picker-table/index.cjs +1 -1
  54. package/build/components/dataviews-layouts/picker-table/index.cjs.map +2 -2
  55. package/build/components/dataviews-layouts/table/index.cjs +40 -19
  56. package/build/components/dataviews-layouts/table/index.cjs.map +2 -2
  57. package/build/dataviews/index.cjs +9 -2
  58. package/build/dataviews/index.cjs.map +3 -3
  59. package/build/dataviews-picker/index.cjs +1 -0
  60. package/build/dataviews-picker/index.cjs.map +2 -2
  61. package/build/hooks/use-data.cjs +46 -0
  62. package/build/hooks/use-data.cjs.map +7 -0
  63. package/build/hooks/use-delayed-loading.cjs +47 -0
  64. package/build/hooks/use-delayed-loading.cjs.map +7 -0
  65. package/build/types/dataform.cjs.map +1 -1
  66. package/build-module/components/dataform-controls/color.mjs +24 -31
  67. package/build-module/components/dataform-controls/color.mjs.map +2 -2
  68. package/build-module/components/dataform-controls/date.mjs.map +1 -1
  69. package/build-module/components/dataform-controls/datetime.mjs +13 -22
  70. package/build-module/components/dataform-controls/datetime.mjs.map +2 -2
  71. package/build-module/components/dataform-layouts/card/index.mjs +113 -161
  72. package/build-module/components/dataform-layouts/card/index.mjs.map +3 -3
  73. package/build-module/components/dataform-layouts/index.mjs +1 -1
  74. package/build-module/components/dataform-layouts/index.mjs.map +1 -1
  75. package/build-module/components/dataform-layouts/normalize-form.mjs +2 -1
  76. package/build-module/components/dataform-layouts/normalize-form.mjs.map +2 -2
  77. package/build-module/components/dataform-layouts/panel/dropdown.mjs +81 -67
  78. package/build-module/components/dataform-layouts/panel/dropdown.mjs.map +2 -2
  79. package/build-module/components/dataform-layouts/panel/index.mjs +14 -178
  80. package/build-module/components/dataform-layouts/panel/index.mjs.map +2 -2
  81. package/build-module/components/dataform-layouts/panel/modal.mjs +12 -9
  82. package/build-module/components/dataform-layouts/panel/modal.mjs.map +2 -2
  83. package/build-module/components/dataform-layouts/panel/summary-button.mjs +117 -58
  84. package/build-module/components/dataform-layouts/panel/summary-button.mjs.map +2 -2
  85. package/build-module/components/dataform-layouts/panel/utils/get-first-validation-error.mjs +38 -0
  86. package/build-module/components/dataform-layouts/panel/utils/get-first-validation-error.mjs.map +7 -0
  87. package/build-module/components/dataform-layouts/panel/utils/get-label-classname.mjs +14 -0
  88. package/build-module/components/dataform-layouts/panel/utils/get-label-classname.mjs.map +7 -0
  89. package/build-module/components/dataform-layouts/panel/utils/get-label-content.mjs +15 -0
  90. package/build-module/components/dataform-layouts/panel/utils/get-label-content.mjs.map +7 -0
  91. package/build-module/components/dataform-layouts/panel/utils/use-field-from-form-field.mjs +46 -0
  92. package/build-module/components/dataform-layouts/panel/utils/use-field-from-form-field.mjs.map +7 -0
  93. package/build-module/components/dataviews-bulk-actions/index.mjs +2 -2
  94. package/build-module/components/dataviews-bulk-actions/index.mjs.map +2 -2
  95. package/build-module/components/dataviews-context/index.mjs +1 -0
  96. package/build-module/components/dataviews-context/index.mjs.map +2 -2
  97. package/build-module/components/dataviews-filters/filter.mjs.map +1 -1
  98. package/build-module/components/dataviews-filters/search-widget.mjs +25 -11
  99. package/build-module/components/dataviews-filters/search-widget.mjs.map +2 -2
  100. package/build-module/components/dataviews-filters/toggle.mjs +6 -2
  101. package/build-module/components/dataviews-filters/toggle.mjs.map +2 -2
  102. package/build-module/components/dataviews-footer/index.mjs +28 -12
  103. package/build-module/components/dataviews-footer/index.mjs.map +2 -2
  104. package/build-module/components/dataviews-item-actions/index.mjs +0 -1
  105. package/build-module/components/dataviews-item-actions/index.mjs.map +2 -2
  106. package/build-module/components/dataviews-layout/index.mjs +12 -0
  107. package/build-module/components/dataviews-layout/index.mjs.map +2 -2
  108. package/build-module/components/dataviews-layouts/activity/index.mjs +41 -26
  109. package/build-module/components/dataviews-layouts/activity/index.mjs.map +2 -2
  110. package/build-module/components/dataviews-layouts/grid/composite-grid.mjs +2 -0
  111. package/build-module/components/dataviews-layouts/grid/composite-grid.mjs.map +2 -2
  112. package/build-module/components/dataviews-layouts/grid/index.mjs +19 -14
  113. package/build-module/components/dataviews-layouts/grid/index.mjs.map +2 -2
  114. package/build-module/components/dataviews-layouts/list/index.mjs +13 -9
  115. package/build-module/components/dataviews-layouts/list/index.mjs.map +2 -2
  116. package/build-module/components/dataviews-layouts/picker-table/index.mjs +1 -1
  117. package/build-module/components/dataviews-layouts/picker-table/index.mjs.map +2 -2
  118. package/build-module/components/dataviews-layouts/table/index.mjs +40 -19
  119. package/build-module/components/dataviews-layouts/table/index.mjs.map +2 -2
  120. package/build-module/dataviews/index.mjs +9 -2
  121. package/build-module/dataviews/index.mjs.map +2 -2
  122. package/build-module/dataviews-picker/index.mjs +1 -0
  123. package/build-module/dataviews-picker/index.mjs.map +2 -2
  124. package/build-module/hooks/use-data.mjs +25 -0
  125. package/build-module/hooks/use-data.mjs.map +7 -0
  126. package/build-module/hooks/use-delayed-loading.mjs +22 -0
  127. package/build-module/hooks/use-delayed-loading.mjs.map +7 -0
  128. package/build-style/style-rtl.css +190 -31
  129. package/build-style/style.css +190 -31
  130. package/build-types/components/dataform-controls/color.d.ts.map +1 -1
  131. package/build-types/components/dataform-controls/datetime.d.ts.map +1 -1
  132. package/build-types/components/dataform-controls/utils/use-disabled-date-matchers.d.ts +16 -0
  133. package/build-types/components/dataform-controls/utils/use-disabled-date-matchers.d.ts.map +1 -0
  134. package/build-types/components/dataform-layouts/card/index.d.ts +1 -10
  135. package/build-types/components/dataform-layouts/card/index.d.ts.map +1 -1
  136. package/build-types/components/dataform-layouts/normalize-form.d.ts.map +1 -1
  137. package/build-types/components/dataform-layouts/panel/dropdown.d.ts +2 -13
  138. package/build-types/components/dataform-layouts/panel/dropdown.d.ts.map +1 -1
  139. package/build-types/components/dataform-layouts/panel/index.d.ts +1 -1
  140. package/build-types/components/dataform-layouts/panel/index.d.ts.map +1 -1
  141. package/build-types/components/dataform-layouts/panel/modal.d.ts +2 -11
  142. package/build-types/components/dataform-layouts/panel/modal.d.ts.map +1 -1
  143. package/build-types/components/dataform-layouts/panel/summary-button.d.ts +6 -5
  144. package/build-types/components/dataform-layouts/panel/summary-button.d.ts.map +1 -1
  145. package/build-types/components/dataform-layouts/panel/utils/get-first-validation-error.d.ts +4 -0
  146. package/build-types/components/dataform-layouts/panel/utils/get-first-validation-error.d.ts.map +1 -0
  147. package/build-types/components/dataform-layouts/panel/utils/get-label-classname.d.ts +4 -0
  148. package/build-types/components/dataform-layouts/panel/utils/get-label-classname.d.ts.map +1 -0
  149. package/build-types/components/dataform-layouts/panel/utils/get-label-content.d.ts +3 -0
  150. package/build-types/components/dataform-layouts/panel/utils/get-label-content.d.ts.map +1 -0
  151. package/build-types/components/dataform-layouts/panel/utils/use-field-from-form-field.d.ts +23 -0
  152. package/build-types/components/dataform-layouts/panel/utils/use-field-from-form-field.d.ts.map +1 -0
  153. package/build-types/components/dataviews-context/index.d.ts +1 -0
  154. package/build-types/components/dataviews-context/index.d.ts.map +1 -1
  155. package/build-types/components/dataviews-filters/filter.d.ts +1 -1
  156. package/build-types/components/dataviews-filters/filter.d.ts.map +1 -1
  157. package/build-types/components/dataviews-filters/search-widget.d.ts.map +1 -1
  158. package/build-types/components/dataviews-filters/toggle.d.ts.map +1 -1
  159. package/build-types/components/dataviews-footer/index.d.ts +1 -1
  160. package/build-types/components/dataviews-footer/index.d.ts.map +1 -1
  161. package/build-types/components/dataviews-item-actions/index.d.ts.map +1 -1
  162. package/build-types/components/dataviews-layout/index.d.ts +1 -1
  163. package/build-types/components/dataviews-layout/index.d.ts.map +1 -1
  164. package/build-types/components/dataviews-layouts/activity/index.d.ts.map +1 -1
  165. package/build-types/components/dataviews-layouts/grid/composite-grid.d.ts +2 -1
  166. package/build-types/components/dataviews-layouts/grid/composite-grid.d.ts.map +1 -1
  167. package/build-types/components/dataviews-layouts/grid/index.d.ts.map +1 -1
  168. package/build-types/components/dataviews-layouts/list/index.d.ts.map +1 -1
  169. package/build-types/components/dataviews-layouts/picker-activity/index.d.ts +3 -0
  170. package/build-types/components/dataviews-layouts/picker-activity/index.d.ts.map +1 -0
  171. package/build-types/components/dataviews-layouts/table/index.d.ts.map +1 -1
  172. package/build-types/components/dataviews-layouts/table/use-scroll-state.d.ts +25 -0
  173. package/build-types/components/dataviews-layouts/table/use-scroll-state.d.ts.map +1 -0
  174. package/build-types/components/dataviews-layouts/utils/grid-config-options.d.ts +2 -0
  175. package/build-types/components/dataviews-layouts/utils/grid-config-options.d.ts.map +1 -0
  176. package/build-types/components/dataviews-layouts/utils/use-infinite-scroll.d.ts +22 -0
  177. package/build-types/components/dataviews-layouts/utils/use-infinite-scroll.d.ts.map +1 -0
  178. package/build-types/dataform/stories/index.story.d.ts +9 -1
  179. package/build-types/dataform/stories/index.story.d.ts.map +1 -1
  180. package/build-types/dataform/stories/layout-panel.d.ts +3 -1
  181. package/build-types/dataform/stories/layout-panel.d.ts.map +1 -1
  182. package/build-types/dataviews/index.d.ts.map +1 -1
  183. package/build-types/dataviews/stories/empty.d.ts.map +1 -1
  184. package/build-types/dataviews/stories/fixtures.d.ts +1 -0
  185. package/build-types/dataviews/stories/fixtures.d.ts.map +1 -1
  186. package/build-types/dataviews/stories/free-composition.d.ts.map +1 -1
  187. package/build-types/dataviews/stories/layout-table.d.ts.map +1 -1
  188. package/build-types/dataviews/stories/minimal-ui.d.ts.map +1 -1
  189. package/build-types/dataviews/stories/with-card.d.ts.map +1 -1
  190. package/build-types/dataviews-picker/index.d.ts.map +1 -1
  191. package/build-types/field-types/utils/is-valid-date-boundary.d.ts +7 -0
  192. package/build-types/field-types/utils/is-valid-date-boundary.d.ts.map +1 -0
  193. package/build-types/hooks/test/use-data.d.ts +2 -0
  194. package/build-types/hooks/test/use-data.d.ts.map +1 -0
  195. package/build-types/hooks/use-data.d.ts +12 -0
  196. package/build-types/hooks/use-data.d.ts.map +1 -0
  197. package/build-types/hooks/use-delayed-loading.d.ts +4 -0
  198. package/build-types/hooks/use-delayed-loading.d.ts.map +1 -0
  199. package/build-types/hooks/use-infinite-scroll.d.ts +21 -0
  200. package/build-types/hooks/use-infinite-scroll.d.ts.map +1 -0
  201. package/build-types/hooks/use-selected-items.d.ts +19 -0
  202. package/build-types/hooks/use-selected-items.d.ts.map +1 -0
  203. package/build-types/types/dataform.d.ts +3 -0
  204. package/build-types/types/dataform.d.ts.map +1 -1
  205. package/build-wp/index.js +2898 -2198
  206. package/package.json +21 -21
  207. package/src/components/dataform-controls/color.tsx +29 -36
  208. package/src/components/dataform-controls/date.tsx +2 -2
  209. package/src/components/dataform-controls/datetime.tsx +19 -34
  210. package/src/components/dataform-controls/style.scss +4 -0
  211. package/src/components/dataform-layouts/card/index.tsx +118 -185
  212. package/src/components/dataform-layouts/index.tsx +1 -1
  213. package/src/components/dataform-layouts/normalize-form.ts +1 -0
  214. package/src/components/dataform-layouts/panel/dropdown.tsx +95 -96
  215. package/src/components/dataform-layouts/panel/index.tsx +10 -245
  216. package/src/components/dataform-layouts/panel/modal.tsx +16 -20
  217. package/src/components/dataform-layouts/panel/style.scss +110 -27
  218. package/src/components/dataform-layouts/panel/summary-button.tsx +140 -62
  219. package/src/components/dataform-layouts/panel/utils/get-first-validation-error.ts +47 -0
  220. package/src/components/dataform-layouts/panel/utils/get-label-classname.ts +18 -0
  221. package/src/components/dataform-layouts/panel/utils/get-label-content.tsx +24 -0
  222. package/src/components/dataform-layouts/panel/utils/use-field-from-form-field.ts +78 -0
  223. package/src/components/dataform-layouts/regular/style.scss +7 -0
  224. package/src/components/dataform-layouts/test/normalize-form.ts +5 -0
  225. package/src/components/dataviews-bulk-actions/index.tsx +2 -2
  226. package/src/components/dataviews-context/index.ts +2 -0
  227. package/src/components/dataviews-filters/filter.tsx +1 -1
  228. package/src/components/dataviews-filters/search-widget.tsx +10 -2
  229. package/src/components/dataviews-filters/style.scss +8 -0
  230. package/src/components/dataviews-filters/toggle.tsx +10 -3
  231. package/src/components/dataviews-footer/index.tsx +39 -12
  232. package/src/components/dataviews-footer/style.scss +6 -1
  233. package/src/components/dataviews-item-actions/index.tsx +0 -3
  234. package/src/components/dataviews-item-actions/style.scss +7 -0
  235. package/src/components/dataviews-layout/index.tsx +24 -0
  236. package/src/components/dataviews-layouts/activity/index.tsx +29 -22
  237. package/src/components/dataviews-layouts/activity/style.scss +5 -0
  238. package/src/components/dataviews-layouts/grid/composite-grid.tsx +5 -1
  239. package/src/components/dataviews-layouts/grid/index.tsx +19 -22
  240. package/src/components/dataviews-layouts/grid/style.scss +5 -0
  241. package/src/components/dataviews-layouts/list/index.tsx +18 -18
  242. package/src/components/dataviews-layouts/list/style.scss +5 -0
  243. package/src/components/dataviews-layouts/picker-table/index.tsx +1 -1
  244. package/src/components/dataviews-layouts/table/index.tsx +48 -22
  245. package/src/components/dataviews-layouts/table/style.scss +8 -2
  246. package/src/dataform/stories/index.story.tsx +5 -0
  247. package/src/dataform/stories/layout-panel.tsx +19 -2
  248. package/src/dataform/test/dataform.tsx +2 -2
  249. package/src/dataviews/index.tsx +11 -3
  250. package/src/dataviews/stories/empty.tsx +1 -7
  251. package/src/dataviews/stories/fixtures.tsx +89 -0
  252. package/src/dataviews/stories/free-composition.tsx +0 -5
  253. package/src/dataviews/stories/layout-table.tsx +1 -7
  254. package/src/dataviews/stories/minimal-ui.tsx +0 -5
  255. package/src/dataviews/stories/with-card.tsx +1 -7
  256. package/src/dataviews/style.scss +25 -0
  257. package/src/dataviews-picker/index.tsx +2 -1
  258. package/src/hooks/use-data.ts +45 -0
  259. package/src/hooks/use-delayed-loading.ts +21 -0
  260. package/src/types/dataform.ts +4 -0
@@ -206,7 +206,12 @@ function ListBox( { view, filter, onChangeView }: SearchWidgetProps ) {
206
206
  selected={ currentValue.includes( element.value ) }
207
207
  />
208
208
  ) }
209
- <span>{ element.label }</span>
209
+ <span
210
+ className="dataviews-filters__search-widget-listitem-value"
211
+ title={ element.label }
212
+ >
213
+ { element.label }
214
+ </span>
210
215
  </Composite.Hover>
211
216
  ) ) }
212
217
  </Composite>
@@ -307,7 +312,10 @@ function ComboboxList( { view, filter, onChangeView }: SearchWidgetProps ) {
307
312
  ) }
308
313
  />
309
314
  ) }
310
- <span>
315
+ <span
316
+ className="dataviews-filters__search-widget-listitem-value"
317
+ title={ element.label }
318
+ >
311
319
  <Ariakit.ComboboxItemValue
312
320
  className="dataviews-filters__search-widget-filter-combobox-item-value"
313
321
  value={ element.label }
@@ -231,6 +231,13 @@
231
231
  }
232
232
  }
233
233
 
234
+ .dataviews-filters__search-widget-listitem-value {
235
+ overflow: hidden;
236
+ text-overflow: ellipsis;
237
+ white-space: nowrap;
238
+ min-width: 0;
239
+ }
240
+
234
241
  .dataviews-filters__search-widget-listitem-description {
235
242
  display: block;
236
243
  overflow: hidden;
@@ -275,6 +282,7 @@
275
282
 
276
283
  .dataviews-filters__search-widget-listitem-multi-selection {
277
284
  --checkbox-size: 24px; // Width & height for small viewports.
285
+ flex-shrink: 0;
278
286
 
279
287
  @include checkbox-control;
280
288
  position: relative;
@@ -31,13 +31,13 @@ function FiltersToggle() {
31
31
  },
32
32
  [ onChangeView, setIsShowingFilter ]
33
33
  );
34
- const visibleFilters = filters.filter( ( filter ) => filter.isVisible );
35
34
 
36
- const hasVisibleFilters = !! visibleFilters.length;
37
35
  if ( filters.length === 0 ) {
38
36
  return null;
39
37
  }
40
38
 
39
+ const hasVisibleFilters = filters.some( ( filter ) => filter.isVisible );
40
+
41
41
  const addFilterButtonProps = {
42
42
  label: __( 'Add filter' ),
43
43
  'aria-expanded': false,
@@ -54,12 +54,19 @@ function FiltersToggle() {
54
54
  setIsShowingFilter( ! isShowingFilter );
55
55
  },
56
56
  };
57
+ // When there are primary or locked filters, the filter bar is always
58
+ // visible and cannot be hidden, so the toggle button should be disabled.
59
+ const hasPrimaryOrLockedFilters = filters.some(
60
+ ( filter ) => filter.isPrimary || filter.isLocked
61
+ );
57
62
  const buttonComponent = (
58
63
  <Button
59
64
  ref={ buttonRef }
60
65
  className="dataviews-filters__visibility-toggle"
61
66
  size="compact"
62
67
  icon={ funnel }
68
+ disabled={ hasPrimaryOrLockedFilters }
69
+ accessibleWhenDisabled
63
70
  { ...( hasVisibleFilters
64
71
  ? toggleFiltersButtonProps
65
72
  : addFilterButtonProps ) }
@@ -92,7 +99,7 @@ function FilterVisibilityToggle( {
92
99
  filtersCount,
93
100
  children,
94
101
  }: {
95
- buttonRef: React.RefObject< HTMLButtonElement >;
102
+ buttonRef: React.RefObject< HTMLButtonElement | null >;
96
103
  filtersCount?: number;
97
104
  children: React.ReactNode;
98
105
  } ) {
@@ -1,3 +1,8 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import clsx from 'clsx';
5
+
1
6
  /**
2
7
  * WordPress dependencies
3
8
  */
@@ -14,6 +19,7 @@ import {
14
19
  useSomeItemHasAPossibleBulkAction,
15
20
  } from '../dataviews-bulk-actions';
16
21
  import { LAYOUT_GRID, LAYOUT_TABLE } from '../../constants';
22
+ import { useDelayedLoading } from '../../hooks/use-delayed-loading';
17
23
 
18
24
  const EMPTY_ARRAY: [] = [];
19
25
 
@@ -23,30 +29,51 @@ export default function DataViewsFooter() {
23
29
  paginationInfo: { totalItems = 0, totalPages },
24
30
  data,
25
31
  actions = EMPTY_ARRAY,
32
+ isLoading,
33
+ hasInitiallyLoaded,
34
+ hasInfiniteScrollHandler,
26
35
  } = useContext( DataViewsContext );
36
+
37
+ const isRefreshing =
38
+ !! isLoading &&
39
+ hasInitiallyLoaded &&
40
+ ! hasInfiniteScrollHandler &&
41
+ !! data?.length;
42
+
43
+ const isDelayedRefreshing = useDelayedLoading( !! isRefreshing );
44
+
27
45
  const hasBulkActions =
28
46
  useSomeItemHasAPossibleBulkAction( actions, data ) &&
29
47
  [ LAYOUT_TABLE, LAYOUT_GRID ].includes( view.type );
30
48
 
31
49
  if (
32
- ! totalItems ||
33
- ! totalPages ||
34
- ( totalPages <= 1 && ! hasBulkActions )
50
+ ! isRefreshing &&
51
+ ( ! totalItems ||
52
+ ! totalPages ||
53
+ ( totalPages <= 1 && ! hasBulkActions ) )
35
54
  ) {
36
55
  return null;
37
56
  }
38
57
  return (
39
- !! totalItems && (
40
- <Stack
41
- direction="row"
42
- justify="end"
43
- align="center"
58
+ ( !! totalItems || isRefreshing ) && (
59
+ <div
44
60
  className="dataviews-footer"
45
- gap="sm"
61
+ // @ts-ignore
62
+ inert={ isRefreshing ? 'true' : undefined }
46
63
  >
47
- { hasBulkActions && <BulkActionsFooter /> }
48
- <DataViewsPagination />
49
- </Stack>
64
+ <Stack
65
+ direction="row"
66
+ justify="end"
67
+ align="center"
68
+ className={ clsx( 'dataviews-footer__content', {
69
+ 'is-refreshing': isDelayedRefreshing,
70
+ } ) }
71
+ gap="sm"
72
+ >
73
+ { hasBulkActions && <BulkActionsFooter /> }
74
+ <DataViewsPagination />
75
+ </Stack>
76
+ </div>
50
77
  )
51
78
  );
52
79
  }
@@ -1,6 +1,7 @@
1
1
  @use "@wordpress/base-styles/colors" as *;
2
2
  @use "@wordpress/base-styles/variables" as *;
3
3
  @use "@wordpress/base-styles/z-index" as *;
4
+ @use "../../dataviews/style" as *;
4
5
 
5
6
  .dataviews-footer {
6
7
  position: sticky;
@@ -16,10 +17,14 @@
16
17
  }
17
18
 
18
19
  z-index: z-index(".dataviews-footer");
20
+
21
+ .is-refreshing {
22
+ @include dataviews-refreshing();
23
+ }
19
24
  }
20
25
 
21
26
  @container (max-width: 560px) {
22
- .dataviews-footer {
27
+ .dataviews-footer__content {
23
28
  flex-direction: column !important;
24
29
 
25
30
  .dataviews-bulk-actions-footer__container {
@@ -171,9 +171,6 @@ export function ActionsMenuGroup< Item >( {
171
171
  return (
172
172
  <Menu.Group>
173
173
  { renderActionGroup( primaryActions ) }
174
- { primaryActions.length > 0 && regularActions.length > 0 && (
175
- <Menu.Separator />
176
- ) }
177
174
  { renderActionGroup( regularActions ) }
178
175
  </Menu.Group>
179
176
  );
@@ -5,3 +5,10 @@
5
5
  .dataviews-action-modal {
6
6
  z-index: z-index(".dataviews-action-modal");
7
7
  }
8
+
9
+ // TODO: the way forward here would be to use the new unstyle button coming
10
+ // from wordpress/ui package, but we're not ready to use it yet.
11
+ // See https://github.com/WordPress/gutenberg/pull/75721/
12
+ .dataviews-item-actions .components-button:not(.dataviews-all-actions-button) {
13
+ padding: 0 $grid-unit-05;
14
+ }
@@ -7,6 +7,7 @@ import type { ComponentType } from 'react';
7
7
  * WordPress dependencies
8
8
  */
9
9
  import { useContext } from '@wordpress/element';
10
+ import { Spinner } from '@wordpress/components';
10
11
  import { __ } from '@wordpress/i18n';
11
12
 
12
13
  /**
@@ -14,6 +15,7 @@ import { __ } from '@wordpress/i18n';
14
15
  */
15
16
  import DataViewsContext from '../dataviews-context';
16
17
  import { VIEW_LAYOUTS } from '../dataviews-layouts';
18
+ import { useDelayedLoading } from '../../hooks/use-delayed-loading';
17
19
  import type { ViewBaseProps } from '../../types';
18
20
 
19
21
  type DataViewsLayoutProps = {
@@ -27,6 +29,7 @@ export default function DataViewsLayout( { className }: DataViewsLayoutProps ) {
27
29
  fields,
28
30
  getItemId,
29
31
  getItemLevel,
32
+ hasInitiallyLoaded,
30
33
  isLoading,
31
34
  view,
32
35
  onChangeView,
@@ -40,6 +43,27 @@ export default function DataViewsLayout( { className }: DataViewsLayoutProps ) {
40
43
  empty = <p>{ __( 'No results' ) }</p>,
41
44
  } = useContext( DataViewsContext );
42
45
 
46
+ const isDelayedInitialLoading = useDelayedLoading( ! hasInitiallyLoaded, {
47
+ delay: 200,
48
+ } );
49
+ // Until the initial data load completes, show a spinner (or nothing if fast).
50
+ // After that, render the layout component which preserves previous data
51
+ // while loading subsequent requests.
52
+ if ( ! hasInitiallyLoaded ) {
53
+ // If the initial data load is fast, don't show the loading state at all.
54
+ if ( ! isDelayedInitialLoading ) {
55
+ return null;
56
+ }
57
+ // If the initial data load takes more than 200ms, show the loading state.
58
+ return (
59
+ <div className="dataviews-loading">
60
+ <p>
61
+ <Spinner />
62
+ </p>
63
+ </div>
64
+ );
65
+ }
66
+
43
67
  const ViewComponent = VIEW_LAYOUTS.find(
44
68
  ( v ) => v.type === view.type && defaultLayouts[ v.type ]
45
69
  )?.component as ComponentType< ViewBaseProps< any > >;
@@ -16,41 +16,40 @@ import type { ViewActivityProps } from '../../../types';
16
16
  import getDataByGroup from '../utils/get-data-by-group';
17
17
  import ActivityGroup from './activity-group';
18
18
  import ActivityItems from './activity-items';
19
+ import { useDelayedLoading } from '../../../hooks/use-delayed-loading';
19
20
 
20
21
  export default function ViewActivity< Item >(
21
22
  props: ViewActivityProps< Item >
22
23
  ) {
23
24
  const { empty, data, fields, isLoading, view, className } = props;
24
25
 
25
- // Handle empty/loading states
26
- const hasData = data?.length;
26
+ const isDelayedLoading = useDelayedLoading( !! isLoading );
27
+ const hasData = !! data?.length;
28
+
29
+ // Check if data should be grouped
30
+ const groupField = view.groupBy?.field
31
+ ? fields.find( ( field ) => field.id === view.groupBy?.field )
32
+ : null;
33
+ const dataByGroup =
34
+ hasData && groupField ? getDataByGroup( data, groupField ) : null;
35
+
36
+ const isInfiniteScroll = view.infiniteScrollEnabled && ! dataByGroup;
27
37
  if ( ! hasData ) {
28
38
  return (
29
39
  <div
30
- className={ clsx( {
31
- 'dataviews-loading': isLoading,
32
- 'dataviews-no-results': ! hasData && ! isLoading,
40
+ className={ clsx( 'dataviews-no-results', {
41
+ 'is-refreshing': isDelayedLoading,
33
42
  } ) }
34
43
  >
35
- { ! hasData &&
36
- ( isLoading ? (
37
- <p>
38
- <Spinner />
39
- </p>
40
- ) : (
41
- empty
42
- ) ) }
44
+ { empty }
43
45
  </div>
44
46
  );
45
47
  }
46
48
 
47
- const wrapperClassName = clsx( 'dataviews-view-activity', className );
48
-
49
- // Check if data should be grouped
50
- const groupField = view.groupBy?.field
51
- ? fields.find( ( field ) => field.id === view.groupBy?.field )
52
- : null;
53
- const dataByGroup = groupField ? getDataByGroup( data, groupField ) : null;
49
+ const isInert = ! isInfiniteScroll && !! isLoading;
50
+ const wrapperClassName = clsx( 'dataviews-view-activity', className, {
51
+ 'is-refreshing': ! isInfiniteScroll && isDelayedLoading,
52
+ } );
54
53
 
55
54
  // Convert dataByGroup entries into array.
56
55
  const groupedEntries = dataByGroup
@@ -60,7 +59,13 @@ export default function ViewActivity< Item >(
60
59
  // Render grouped activity
61
60
  if ( hasData && groupField && dataByGroup ) {
62
61
  return (
63
- <Stack direction="column" gap="sm" className={ wrapperClassName }>
62
+ <Stack
63
+ direction="column"
64
+ gap="sm"
65
+ className={ wrapperClassName }
66
+ // @ts-ignore
67
+ inert={ isInert ? 'true' : undefined }
68
+ >
64
69
  { groupedEntries.map(
65
70
  ( [ groupName, groupData ]: [ string, Item[] ] ) => (
66
71
  <ActivityGroup< Item >
@@ -87,10 +92,12 @@ export default function ViewActivity< Item >(
87
92
  <div
88
93
  className={ wrapperClassName }
89
94
  role={ view.infiniteScrollEnabled ? 'feed' : undefined }
95
+ // @ts-ignore
96
+ inert={ isInert ? 'true' : undefined }
90
97
  >
91
98
  <ActivityItems< Item > { ...props } />
92
99
  </div>
93
- { hasData && isLoading && (
100
+ { isInfiniteScroll && isLoading && (
94
101
  <p className="dataviews-loading-more">
95
102
  <Spinner />
96
103
  </p>
@@ -1,5 +1,6 @@
1
1
  @use "@wordpress/base-styles/colors" as *;
2
2
  @use "@wordpress/base-styles/variables" as *;
3
+ @use "../../../dataviews/style" as *;
3
4
 
4
5
  .dataviews-view-activity {
5
6
  margin: 0 0 auto;
@@ -211,6 +212,10 @@
211
212
  }
212
213
  }
213
214
 
215
+ &.is-refreshing {
216
+ @include dataviews-refreshing();
217
+ }
218
+
214
219
  & + .dataviews-pagination {
215
220
  justify-content: space-between;
216
221
  }
@@ -287,12 +287,13 @@ const GridItem = forwardRef( function GridItem< Item >(
287
287
  props: GridItemProps< Item > & {
288
288
  ref?: React.ForwardedRef< HTMLDivElement >;
289
289
  }
290
- ) => JSX.Element;
290
+ ) => React.ReactNode;
291
291
 
292
292
  interface CompositeGridProps< Item > {
293
293
  data: Item[];
294
294
  isInfiniteScroll: boolean;
295
295
  className?: string;
296
+ inert?: string;
296
297
  isLoading?: boolean;
297
298
  view: ViewGridType;
298
299
  fields: NormalizedField< Item >[];
@@ -313,6 +314,7 @@ export default function CompositeGrid< Item >( {
313
314
  data,
314
315
  isInfiniteScroll,
315
316
  className,
317
+ inert,
316
318
  isLoading,
317
319
  view,
318
320
  fields,
@@ -375,6 +377,8 @@ export default function CompositeGrid< Item >( {
375
377
  aria-busy={ isLoading }
376
378
  aria-rowcount={ isInfiniteScroll ? undefined : totalRows }
377
379
  ref={ resizeObserverRef }
380
+ // @ts-ignore
381
+ inert={ inert }
378
382
  >
379
383
  { chunk( data, gridColumns ).map( ( row, i ) => (
380
384
  <Composite.Row
@@ -16,6 +16,7 @@ import { Stack } from '@wordpress/ui';
16
16
  import type { ViewGridProps } from '../../../types';
17
17
  import getDataByGroup from '../utils/get-data-by-group';
18
18
  import CompositeGrid from './composite-grid';
19
+ import { useDelayedLoading } from '../../../hooks/use-delayed-loading';
19
20
 
20
21
  function ViewGrid< Item >( {
21
22
  actions,
@@ -32,14 +33,29 @@ function ViewGrid< Item >( {
32
33
  className,
33
34
  empty,
34
35
  }: ViewGridProps< Item > ) {
36
+ const isDelayedLoading = useDelayedLoading( !! isLoading );
35
37
  const hasData = !! data?.length;
36
38
  const groupField = view.groupBy?.field
37
39
  ? fields.find( ( f ) => f.id === view.groupBy?.field )
38
40
  : null;
39
41
  const dataByGroup = groupField ? getDataByGroup( data, groupField ) : null;
40
42
  const isInfiniteScroll = view.infiniteScrollEnabled && ! dataByGroup;
43
+ if ( ! hasData ) {
44
+ return (
45
+ <div
46
+ className={ clsx( 'dataviews-no-results', {
47
+ 'is-refreshing': isDelayedLoading,
48
+ } ) }
49
+ >
50
+ { empty }
51
+ </div>
52
+ );
53
+ }
41
54
  const gridProps = {
42
- className,
55
+ className: clsx( className, {
56
+ 'is-refreshing': ! isInfiniteScroll && isDelayedLoading,
57
+ } ),
58
+ inert: ! isInfiniteScroll && !! isLoading ? 'true' : undefined,
43
59
  isLoading,
44
60
  view,
45
61
  fields,
@@ -87,7 +103,7 @@ function ViewGrid< Item >( {
87
103
  }
88
104
  {
89
105
  // Render a single grid with all data.
90
- hasData && ! dataByGroup && (
106
+ ! dataByGroup && (
91
107
  <CompositeGrid
92
108
  { ...gridProps }
93
109
  data={ data }
@@ -95,26 +111,7 @@ function ViewGrid< Item >( {
95
111
  />
96
112
  )
97
113
  }
98
- {
99
- // Render empty state.
100
- ! hasData && (
101
- <div
102
- className={ clsx( {
103
- 'dataviews-loading': isLoading,
104
- 'dataviews-no-results': ! isLoading,
105
- } ) }
106
- >
107
- { isLoading ? (
108
- <p>
109
- <Spinner />
110
- </p>
111
- ) : (
112
- empty
113
- ) }
114
- </div>
115
- )
116
- }
117
- { hasData && isLoading && (
114
+ { isInfiniteScroll && isLoading && (
118
115
  <p className="dataviews-loading-more">
119
116
  <Spinner />
120
117
  </p>
@@ -3,6 +3,7 @@
3
3
  @use "@wordpress/base-styles/variables" as *;
4
4
  @use "@wordpress/base-styles/z-index" as *;
5
5
  @use "../utils/grid-items.scss" as *;
6
+ @use "../../../dataviews/style" as *;
6
7
 
7
8
  .dataviews-view-grid {
8
9
  padding: 0 $grid-unit-30 $grid-unit-30;
@@ -164,6 +165,10 @@
164
165
  padding-bottom: $grid-unit-15;
165
166
  }
166
167
  }
168
+
169
+ &.is-refreshing {
170
+ @include dataviews-refreshing();
171
+ }
167
172
  }
168
173
 
169
174
  .dataviews-view-grid__field-value:empty,
@@ -33,6 +33,7 @@ import { Stack } from '@wordpress/ui';
33
33
  import { unlock } from '../../../lock-unlock';
34
34
  import { ActionsMenuGroup, ActionModal } from '../../dataviews-item-actions';
35
35
  import DataViewsContext from '../../dataviews-context';
36
+ import { useDelayedLoading } from '../../../hooks/use-delayed-loading';
36
37
  import type {
37
38
  Action,
38
39
  NormalizedField,
@@ -389,6 +390,7 @@ export default function ViewList< Item >( props: ViewListProps< Item > ) {
389
390
  empty,
390
391
  } = props;
391
392
  const baseId = useInstanceId( ViewList, 'view-list' );
393
+ const isDelayedLoading = useDelayedLoading( !! isLoading );
392
394
 
393
395
  const selectedItem = data?.findLast( ( item ) =>
394
396
  selection.includes( getItemId( item ) )
@@ -511,32 +513,25 @@ export default function ViewList< Item >( props: ViewListProps< Item > ) {
511
513
  [ selectCompositeItem, activeItemIndex ]
512
514
  );
513
515
 
514
- const hasData = data?.length;
516
+ const hasData = !! data?.length;
517
+ const groupField = view.groupBy?.field
518
+ ? fields.find( ( field ) => field.id === view.groupBy?.field )
519
+ : null;
520
+ const dataByGroup =
521
+ hasData && groupField ? getDataByGroup( data, groupField ) : null;
522
+ const isInfiniteScroll = view.infiniteScrollEnabled && ! dataByGroup;
515
523
  if ( ! hasData ) {
516
524
  return (
517
525
  <div
518
- className={ clsx( {
519
- 'dataviews-loading': isLoading,
520
- 'dataviews-no-results': ! hasData && ! isLoading,
526
+ className={ clsx( 'dataviews-no-results', {
527
+ 'is-refreshing': isDelayedLoading,
521
528
  } ) }
522
529
  >
523
- { ! hasData &&
524
- ( isLoading ? (
525
- <p>
526
- <Spinner />
527
- </p>
528
- ) : (
529
- empty
530
- ) ) }
530
+ { empty }
531
531
  </div>
532
532
  );
533
533
  }
534
534
 
535
- const groupField = view.groupBy?.field
536
- ? fields.find( ( field ) => field.id === view.groupBy?.field )
537
- : null;
538
- const dataByGroup = groupField ? getDataByGroup( data, groupField ) : null;
539
-
540
535
  // Render data grouped by field
541
536
  if ( hasData && groupField && dataByGroup ) {
542
537
  return (
@@ -614,10 +609,15 @@ export default function ViewList< Item >( props: ViewListProps< Item > ) {
614
609
  [ 'compact', 'comfortable' ].includes(
615
610
  view.layout.density
616
611
  ),
612
+ 'is-refreshing': ! isInfiniteScroll && isDelayedLoading,
617
613
  } ) }
618
614
  role={ view.infiniteScrollEnabled ? 'feed' : 'grid' }
619
615
  activeId={ activeCompositeId }
620
616
  setActiveId={ setActiveCompositeId }
617
+ // @ts-ignore
618
+ inert={
619
+ ! isInfiniteScroll && !! isLoading ? 'true' : undefined
620
+ }
621
621
  >
622
622
  { data.map( ( item, index ) => {
623
623
  const id = generateCompositeItemIdPrefix( item );
@@ -646,7 +646,7 @@ export default function ViewList< Item >( props: ViewListProps< Item > ) {
646
646
  );
647
647
  } ) }
648
648
  </Composite>
649
- { hasData && isLoading && (
649
+ { isInfiniteScroll && isLoading && (
650
650
  <p className="dataviews-loading-more">
651
651
  <Spinner />
652
652
  </p>
@@ -1,5 +1,6 @@
1
1
  @use "@wordpress/base-styles/colors" as *;
2
2
  @use "@wordpress/base-styles/variables" as *;
3
+ @use "../../../dataviews/style" as *;
3
4
 
4
5
  div.dataviews-view-list {
5
6
  list-style-type: none;
@@ -271,6 +272,10 @@ div.dataviews-view-list {
271
272
  }
272
273
  }
273
274
  }
275
+
276
+ &.is-refreshing {
277
+ @include dataviews-refreshing();
278
+ }
274
279
  }
275
280
 
276
281
  .dataviews-view-list__group-header {
@@ -224,7 +224,7 @@ function ViewPickerTable< Item >( {
224
224
  const headerMenuRefs = useRef<
225
225
  Map< string, { node: HTMLButtonElement; fallback: string } >
226
226
  >( new Map() );
227
- const headerMenuToFocusRef = useRef< HTMLButtonElement >();
227
+ const headerMenuToFocusRef = useRef< HTMLButtonElement >( undefined );
228
228
  const [ nextHeaderMenuToFocus, setNextHeaderMenuToFocus ] =
229
229
  useState< HTMLButtonElement >();
230
230
  const isMultiselect = useIsMultiselectPicker( actions ) ?? false;