@wordpress/dataviews 13.1.1-next.v.202603102151.0 → 14.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 (247) hide show
  1. package/CHANGELOG.md +18 -1
  2. package/README.md +19 -3
  3. package/build/components/dataform-controls/datetime.cjs +8 -4
  4. package/build/components/dataform-controls/datetime.cjs.map +2 -2
  5. package/build/components/dataform-layouts/card/index.cjs +132 -128
  6. package/build/components/dataform-layouts/card/index.cjs.map +3 -3
  7. package/build/components/dataviews-bulk-actions/index.cjs +28 -5
  8. package/build/components/dataviews-bulk-actions/index.cjs.map +2 -2
  9. package/build/components/dataviews-context/index.cjs +2 -2
  10. package/build/components/dataviews-context/index.cjs.map +2 -2
  11. package/build/components/dataviews-footer/index.cjs +2 -3
  12. package/build/components/dataviews-footer/index.cjs.map +2 -2
  13. package/build/components/dataviews-layout/index.cjs +12 -3
  14. package/build/components/dataviews-layout/index.cjs.map +2 -2
  15. package/build/components/dataviews-layouts/grid/composite-grid.cjs +378 -245
  16. package/build/components/dataviews-layouts/grid/composite-grid.cjs.map +2 -2
  17. package/build/components/dataviews-layouts/index.cjs +3 -3
  18. package/build/components/dataviews-layouts/index.cjs.map +3 -3
  19. package/build/components/dataviews-layouts/picker-grid/index.cjs +76 -32
  20. package/build/components/dataviews-layouts/picker-grid/index.cjs.map +2 -2
  21. package/build/components/dataviews-layouts/picker-table/index.cjs +34 -22
  22. package/build/components/dataviews-layouts/picker-table/index.cjs.map +2 -2
  23. package/build/components/dataviews-layouts/table/index.cjs +97 -88
  24. package/build/components/dataviews-layouts/table/index.cjs.map +2 -2
  25. package/build/components/dataviews-layouts/table/{use-is-horizontal-scroll-end.cjs → use-scroll-state.cjs} +29 -33
  26. package/build/components/dataviews-layouts/table/use-scroll-state.cjs.map +7 -0
  27. package/build/components/dataviews-layouts/utils/density-picker.cjs.map +2 -2
  28. package/build/components/dataviews-layouts/utils/grid-config-options.cjs +45 -0
  29. package/build/components/dataviews-layouts/utils/grid-config-options.cjs.map +7 -0
  30. package/build/components/dataviews-layouts/utils/use-infinite-scroll.cjs +62 -0
  31. package/build/components/dataviews-layouts/utils/use-infinite-scroll.cjs.map +7 -0
  32. package/build/components/dataviews-picker-footer/index.cjs +23 -4
  33. package/build/components/dataviews-picker-footer/index.cjs.map +2 -2
  34. package/build/components/dataviews-search/index.cjs +2 -1
  35. package/build/components/dataviews-search/index.cjs.map +2 -2
  36. package/build/components/dataviews-selection-checkbox/index.cjs +3 -2
  37. package/build/components/dataviews-selection-checkbox/index.cjs.map +2 -2
  38. package/build/components/dataviews-view-config/index.cjs +0 -2
  39. package/build/components/dataviews-view-config/index.cjs.map +3 -3
  40. package/build/components/dataviews-view-config/infinite-scroll-toggle.cjs +0 -3
  41. package/build/components/dataviews-view-config/infinite-scroll-toggle.cjs.map +2 -2
  42. package/build/dataviews/index.cjs +38 -34
  43. package/build/dataviews/index.cjs.map +3 -3
  44. package/build/dataviews-picker/index.cjs +26 -25
  45. package/build/dataviews-picker/index.cjs.map +3 -3
  46. package/build/hooks/index.cjs +11 -2
  47. package/build/hooks/index.cjs.map +2 -2
  48. package/build/hooks/use-data.cjs +146 -9
  49. package/build/hooks/use-data.cjs.map +2 -2
  50. package/build/hooks/use-infinite-scroll.cjs +208 -0
  51. package/build/hooks/use-infinite-scroll.cjs.map +7 -0
  52. package/build/hooks/use-selected-items.cjs +57 -0
  53. package/build/hooks/use-selected-items.cjs.map +7 -0
  54. package/build/types/dataviews.cjs.map +1 -1
  55. package/build/types/field-api.cjs.map +1 -1
  56. package/build/utils/filter-sort-and-paginate.cjs +5 -1
  57. package/build/utils/filter-sort-and-paginate.cjs.map +2 -2
  58. package/build/utils/get-footer-message.cjs +8 -8
  59. package/build/utils/get-footer-message.cjs.map +2 -2
  60. package/build-module/components/dataform-controls/datetime.mjs +8 -4
  61. package/build-module/components/dataform-controls/datetime.mjs.map +2 -2
  62. package/build-module/components/dataform-layouts/card/index.mjs +132 -133
  63. package/build-module/components/dataform-layouts/card/index.mjs.map +2 -2
  64. package/build-module/components/dataviews-bulk-actions/index.mjs +28 -5
  65. package/build-module/components/dataviews-bulk-actions/index.mjs.map +2 -2
  66. package/build-module/components/dataviews-context/index.mjs +2 -2
  67. package/build-module/components/dataviews-context/index.mjs.map +2 -2
  68. package/build-module/components/dataviews-footer/index.mjs +2 -3
  69. package/build-module/components/dataviews-footer/index.mjs.map +2 -2
  70. package/build-module/components/dataviews-layout/index.mjs +12 -3
  71. package/build-module/components/dataviews-layout/index.mjs.map +2 -2
  72. package/build-module/components/dataviews-layouts/grid/composite-grid.mjs +387 -246
  73. package/build-module/components/dataviews-layouts/grid/composite-grid.mjs.map +2 -2
  74. package/build-module/components/dataviews-layouts/index.mjs +3 -3
  75. package/build-module/components/dataviews-layouts/index.mjs.map +2 -2
  76. package/build-module/components/dataviews-layouts/picker-grid/index.mjs +80 -33
  77. package/build-module/components/dataviews-layouts/picker-grid/index.mjs.map +2 -2
  78. package/build-module/components/dataviews-layouts/picker-table/index.mjs +34 -22
  79. package/build-module/components/dataviews-layouts/picker-table/index.mjs.map +2 -2
  80. package/build-module/components/dataviews-layouts/table/index.mjs +97 -88
  81. package/build-module/components/dataviews-layouts/table/index.mjs.map +2 -2
  82. package/build-module/components/dataviews-layouts/table/use-scroll-state.mjs +46 -0
  83. package/build-module/components/dataviews-layouts/table/use-scroll-state.mjs.map +7 -0
  84. package/build-module/components/dataviews-layouts/utils/density-picker.mjs.map +2 -2
  85. package/build-module/components/dataviews-layouts/utils/grid-config-options.mjs +14 -0
  86. package/build-module/components/dataviews-layouts/utils/grid-config-options.mjs.map +7 -0
  87. package/build-module/components/dataviews-layouts/utils/use-infinite-scroll.mjs +26 -0
  88. package/build-module/components/dataviews-layouts/utils/use-infinite-scroll.mjs.map +7 -0
  89. package/build-module/components/dataviews-picker-footer/index.mjs +23 -4
  90. package/build-module/components/dataviews-picker-footer/index.mjs.map +2 -2
  91. package/build-module/components/dataviews-search/index.mjs +2 -1
  92. package/build-module/components/dataviews-search/index.mjs.map +2 -2
  93. package/build-module/components/dataviews-selection-checkbox/index.mjs +3 -2
  94. package/build-module/components/dataviews-selection-checkbox/index.mjs.map +2 -2
  95. package/build-module/components/dataviews-view-config/index.mjs +0 -2
  96. package/build-module/components/dataviews-view-config/index.mjs.map +2 -2
  97. package/build-module/components/dataviews-view-config/infinite-scroll-toggle.mjs +0 -3
  98. package/build-module/components/dataviews-view-config/infinite-scroll-toggle.mjs.map +2 -2
  99. package/build-module/dataviews/index.mjs +46 -36
  100. package/build-module/dataviews/index.mjs.map +2 -2
  101. package/build-module/dataviews-picker/index.mjs +34 -27
  102. package/build-module/dataviews-picker/index.mjs.map +2 -2
  103. package/build-module/hooks/index.mjs +7 -1
  104. package/build-module/hooks/index.mjs.map +2 -2
  105. package/build-module/hooks/use-data.mjs +147 -10
  106. package/build-module/hooks/use-data.mjs.map +2 -2
  107. package/build-module/hooks/use-infinite-scroll.mjs +188 -0
  108. package/build-module/hooks/use-infinite-scroll.mjs.map +7 -0
  109. package/build-module/hooks/use-selected-items.mjs +36 -0
  110. package/build-module/hooks/use-selected-items.mjs.map +7 -0
  111. package/build-module/utils/filter-sort-and-paginate.mjs +5 -1
  112. package/build-module/utils/filter-sort-and-paginate.mjs.map +2 -2
  113. package/build-module/utils/get-footer-message.mjs +8 -8
  114. package/build-module/utils/get-footer-message.mjs.map +2 -2
  115. package/build-style/style-rtl.css +107 -41
  116. package/build-style/style.css +107 -41
  117. package/build-types/components/dataform-controls/datetime.d.ts +1 -1
  118. package/build-types/components/dataform-controls/datetime.d.ts.map +1 -1
  119. package/build-types/components/dataform-layouts/card/index.d.ts.map +1 -1
  120. package/build-types/components/dataviews-bulk-actions/index.d.ts +2 -1
  121. package/build-types/components/dataviews-bulk-actions/index.d.ts.map +1 -1
  122. package/build-types/components/dataviews-context/index.d.ts +1 -1
  123. package/build-types/components/dataviews-context/index.d.ts.map +1 -1
  124. package/build-types/components/dataviews-footer/index.d.ts.map +1 -1
  125. package/build-types/components/dataviews-layout/index.d.ts.map +1 -1
  126. package/build-types/components/dataviews-layouts/grid/composite-grid.d.ts.map +1 -1
  127. package/build-types/components/dataviews-layouts/index.d.ts +3 -3
  128. package/build-types/components/dataviews-layouts/index.d.ts.map +1 -1
  129. package/build-types/components/dataviews-layouts/picker-grid/index.d.ts.map +1 -1
  130. package/build-types/components/dataviews-layouts/picker-table/index.d.ts.map +1 -1
  131. package/build-types/components/dataviews-layouts/table/index.d.ts.map +1 -1
  132. package/build-types/components/dataviews-layouts/table/use-scroll-state.d.ts +25 -0
  133. package/build-types/components/dataviews-layouts/table/use-scroll-state.d.ts.map +1 -0
  134. package/build-types/components/dataviews-layouts/utils/density-picker.d.ts.map +1 -1
  135. package/build-types/components/dataviews-layouts/utils/grid-config-options.d.ts +2 -0
  136. package/build-types/components/dataviews-layouts/utils/grid-config-options.d.ts.map +1 -0
  137. package/build-types/components/dataviews-layouts/utils/use-infinite-scroll.d.ts +22 -0
  138. package/build-types/components/dataviews-layouts/utils/use-infinite-scroll.d.ts.map +1 -0
  139. package/build-types/components/dataviews-picker-footer/index.d.ts.map +1 -1
  140. package/build-types/components/dataviews-search/index.d.ts.map +1 -1
  141. package/build-types/components/dataviews-selection-checkbox/index.d.ts.map +1 -1
  142. package/build-types/components/dataviews-view-config/index.d.ts.map +1 -1
  143. package/build-types/components/dataviews-view-config/infinite-scroll-toggle.d.ts +1 -1
  144. package/build-types/components/dataviews-view-config/infinite-scroll-toggle.d.ts.map +1 -1
  145. package/build-types/dataviews/index.d.ts +0 -1
  146. package/build-types/dataviews/index.d.ts.map +1 -1
  147. package/build-types/dataviews/stories/empty.d.ts +1 -2
  148. package/build-types/dataviews/stories/empty.d.ts.map +1 -1
  149. package/build-types/dataviews/stories/fixtures.d.ts.map +1 -1
  150. package/build-types/dataviews/stories/free-composition.d.ts.map +1 -1
  151. package/build-types/dataviews/stories/index.story.d.ts +18 -10
  152. package/build-types/dataviews/stories/index.story.d.ts.map +1 -1
  153. package/build-types/dataviews/stories/infinite-scroll.d.ts.map +1 -1
  154. package/build-types/dataviews/stories/layout-activity.d.ts.map +1 -1
  155. package/build-types/dataviews/stories/layout-custom.d.ts +3 -1
  156. package/build-types/dataviews/stories/layout-custom.d.ts.map +1 -1
  157. package/build-types/dataviews/stories/layout-grid.d.ts.map +1 -1
  158. package/build-types/dataviews/stories/layout-list.d.ts.map +1 -1
  159. package/build-types/dataviews/stories/layout-table.d.ts.map +1 -1
  160. package/build-types/dataviews/stories/with-card.d.ts +3 -1
  161. package/build-types/dataviews/stories/with-card.d.ts.map +1 -1
  162. package/build-types/dataviews-picker/index.d.ts +0 -1
  163. package/build-types/dataviews-picker/index.d.ts.map +1 -1
  164. package/build-types/dataviews-picker/stories/fixtures.d.ts.map +1 -1
  165. package/build-types/dataviews-picker/stories/index.story.d.ts.map +1 -1
  166. package/build-types/field-types/stories/index.story.d.ts.map +1 -1
  167. package/build-types/hooks/index.d.ts +3 -0
  168. package/build-types/hooks/index.d.ts.map +1 -1
  169. package/build-types/hooks/test/use-data.d.ts +2 -0
  170. package/build-types/hooks/test/use-data.d.ts.map +1 -0
  171. package/build-types/hooks/use-data.d.ts +41 -3
  172. package/build-types/hooks/use-data.d.ts.map +1 -1
  173. package/build-types/hooks/use-infinite-scroll.d.ts +21 -0
  174. package/build-types/hooks/use-infinite-scroll.d.ts.map +1 -0
  175. package/build-types/hooks/use-selected-items.d.ts +19 -0
  176. package/build-types/hooks/use-selected-items.d.ts.map +1 -0
  177. package/build-types/types/dataviews.d.ts +15 -1
  178. package/build-types/types/dataviews.d.ts.map +1 -1
  179. package/build-types/types/field-api.d.ts +15 -4
  180. package/build-types/types/field-api.d.ts.map +1 -1
  181. package/build-types/utils/filter-sort-and-paginate.d.ts.map +1 -1
  182. package/build-types/utils/get-footer-message.d.ts +3 -2
  183. package/build-types/utils/get-footer-message.d.ts.map +1 -1
  184. package/build-wp/index.js +3202 -2761
  185. package/package.json +19 -19
  186. package/src/components/dataform-controls/datetime.tsx +19 -11
  187. package/src/components/dataform-layouts/card/index.tsx +171 -146
  188. package/src/components/dataform-layouts/card/style.scss +8 -5
  189. package/src/components/dataviews-bulk-actions/index.tsx +28 -1
  190. package/src/components/dataviews-context/index.ts +2 -2
  191. package/src/components/dataviews-footer/index.tsx +1 -6
  192. package/src/components/dataviews-layout/index.tsx +41 -19
  193. package/src/components/dataviews-layout/style.scss +8 -0
  194. package/src/components/dataviews-layouts/grid/composite-grid.tsx +433 -278
  195. package/src/components/dataviews-layouts/grid/style.scss +22 -2
  196. package/src/components/dataviews-layouts/index.ts +3 -3
  197. package/src/components/dataviews-layouts/picker-grid/index.tsx +70 -17
  198. package/src/components/dataviews-layouts/picker-grid/style.scss +10 -0
  199. package/src/components/dataviews-layouts/picker-table/index.tsx +42 -22
  200. package/src/components/dataviews-layouts/table/index.tsx +10 -4
  201. package/src/components/dataviews-layouts/table/style.scss +13 -0
  202. package/src/components/dataviews-layouts/table/use-scroll-state.ts +79 -0
  203. package/src/components/dataviews-layouts/utils/density-picker.tsx +12 -2
  204. package/src/components/dataviews-layouts/utils/grid-config-options.tsx +14 -0
  205. package/src/components/dataviews-layouts/utils/grid-items.scss +9 -1
  206. package/src/components/dataviews-layouts/utils/use-infinite-scroll.ts +64 -0
  207. package/src/components/dataviews-picker-footer/index.tsx +21 -1
  208. package/src/components/dataviews-search/index.tsx +2 -1
  209. package/src/components/dataviews-selection-checkbox/index.tsx +4 -2
  210. package/src/components/dataviews-view-config/index.tsx +0 -2
  211. package/src/components/dataviews-view-config/infinite-scroll-toggle.tsx +0 -5
  212. package/src/dataviews/index.tsx +58 -45
  213. package/src/dataviews/stories/empty.tsx +1 -3
  214. package/src/dataviews/stories/fixtures.tsx +288 -0
  215. package/src/dataviews/stories/free-composition.tsx +44 -45
  216. package/src/dataviews/stories/index.story.tsx +31 -8
  217. package/src/dataviews/stories/infinite-scroll.tsx +7 -93
  218. package/src/dataviews/stories/layout-activity.tsx +1 -0
  219. package/src/dataviews/stories/layout-custom.tsx +7 -3
  220. package/src/dataviews/stories/layout-grid.tsx +1 -0
  221. package/src/dataviews/stories/layout-list.tsx +1 -0
  222. package/src/dataviews/stories/layout-table.tsx +1 -0
  223. package/src/dataviews/stories/style.css +0 -5
  224. package/src/dataviews/stories/with-card.tsx +35 -24
  225. package/src/dataviews/style.scss +5 -8
  226. package/src/dataviews/test/dataviews.tsx +54 -1
  227. package/src/dataviews-picker/index.tsx +41 -35
  228. package/src/dataviews-picker/stories/fixtures.tsx +270 -0
  229. package/src/dataviews-picker/stories/index.story.tsx +62 -129
  230. package/src/field-types/stories/index.story.tsx +12 -0
  231. package/src/hooks/index.ts +3 -0
  232. package/src/hooks/test/use-data.ts +791 -0
  233. package/src/hooks/use-data.ts +288 -21
  234. package/src/hooks/use-infinite-scroll.ts +304 -0
  235. package/src/hooks/use-selected-items.ts +72 -0
  236. package/src/style.scss +1 -0
  237. package/src/types/dataviews.ts +18 -1
  238. package/src/types/field-api.ts +16 -3
  239. package/src/utils/filter-sort-and-paginate.ts +13 -1
  240. package/src/utils/get-footer-message.ts +12 -9
  241. package/src/utils/test/filter-sort-and-paginate.js +78 -54
  242. package/build/components/dataviews-layouts/table/use-is-horizontal-scroll-end.cjs.map +0 -7
  243. package/build-module/components/dataviews-layouts/table/use-is-horizontal-scroll-end.mjs +0 -50
  244. package/build-module/components/dataviews-layouts/table/use-is-horizontal-scroll-end.mjs.map +0 -7
  245. package/build-types/components/dataviews-layouts/table/use-is-horizontal-scroll-end.d.ts +0 -19
  246. package/build-types/components/dataviews-layouts/table/use-is-horizontal-scroll-end.d.ts.map +0 -1
  247. package/src/components/dataviews-layouts/table/use-is-horizontal-scroll-end.ts +0 -82
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wordpress/dataviews",
3
- "version": "13.1.1-next.v.202603102151.0+59e17f9ec",
3
+ "version": "14.0.0",
4
4
  "description": "DataViews is a component that provides an API to render datasets using different types of layouts (table, grid, list, etc.).",
5
5
  "author": "The WordPress Contributors",
6
6
  "license": "GPL-2.0-or-later",
@@ -53,20 +53,20 @@
53
53
  "sideEffects": false,
54
54
  "dependencies": {
55
55
  "@ariakit/react": "^0.4.21",
56
- "@wordpress/base-styles": "^6.17.1-next.v.202603102151.0+59e17f9ec",
57
- "@wordpress/components": "^32.4.1-next.v.202603102151.0+59e17f9ec",
58
- "@wordpress/compose": "^7.41.1-next.v.202603102151.0+59e17f9ec",
59
- "@wordpress/data": "^10.41.1-next.v.202603102151.0+59e17f9ec",
60
- "@wordpress/date": "^5.41.1-next.v.202603102151.0+59e17f9ec",
61
- "@wordpress/deprecated": "^4.41.1-next.v.202603102151.0+59e17f9ec",
62
- "@wordpress/element": "^6.41.1-next.v.202603102151.0+59e17f9ec",
63
- "@wordpress/i18n": "^6.14.1-next.v.202603102151.0+59e17f9ec",
64
- "@wordpress/icons": "^12.0.1-next.v.202603102151.0+59e17f9ec",
65
- "@wordpress/keycodes": "^4.41.1-next.v.202603102151.0+59e17f9ec",
66
- "@wordpress/primitives": "^4.41.1-next.v.202603102151.0+59e17f9ec",
67
- "@wordpress/private-apis": "^1.41.1-next.v.202603102151.0+59e17f9ec",
68
- "@wordpress/ui": "^0.9.1-next.v.202603102151.0+59e17f9ec",
69
- "@wordpress/warning": "^3.41.1-next.v.202603102151.0+59e17f9ec",
56
+ "@wordpress/base-styles": "^6.19.0",
57
+ "@wordpress/components": "^32.5.0",
58
+ "@wordpress/compose": "^7.43.0",
59
+ "@wordpress/data": "^10.43.0",
60
+ "@wordpress/date": "^5.43.0",
61
+ "@wordpress/deprecated": "^4.43.0",
62
+ "@wordpress/element": "^6.43.0",
63
+ "@wordpress/i18n": "^6.16.0",
64
+ "@wordpress/icons": "^12.1.0",
65
+ "@wordpress/keycodes": "^4.43.0",
66
+ "@wordpress/primitives": "^4.43.0",
67
+ "@wordpress/private-apis": "^1.43.0",
68
+ "@wordpress/ui": "^0.10.0",
69
+ "@wordpress/warning": "^3.43.0",
70
70
  "clsx": "^2.1.1",
71
71
  "colord": "^2.7.0",
72
72
  "date-fns": "^4.1.0",
@@ -75,12 +75,12 @@
75
75
  "remove-accents": "^0.5.0"
76
76
  },
77
77
  "devDependencies": {
78
- "@storybook/addon-docs": "^10.1.11",
79
- "@storybook/react-vite": "^10.1.11",
78
+ "@storybook/addon-docs": "^10.2.8",
79
+ "@storybook/react-vite": "^10.2.8",
80
80
  "@testing-library/jest-dom": "^6.9.1",
81
81
  "@types/jest": "^29.5.14",
82
82
  "esbuild": "^0.27.2",
83
- "storybook": "^10.1.11"
83
+ "storybook": "^10.2.8"
84
84
  },
85
85
  "peerDependencies": {
86
86
  "react": "^18.0.0",
@@ -92,5 +92,5 @@
92
92
  "scripts": {
93
93
  "build:wp": "node build.cjs"
94
94
  },
95
- "gitHead": "86db21e727d89e8f0dbba9300d2f97fd22b08693"
95
+ "gitHead": "2cea90674d11aa521ec3f71652fb3a6a4c383969"
96
96
  }
@@ -37,7 +37,9 @@ function CalendarDateTimeControl< Item >( {
37
37
  hideLabelFromVision,
38
38
  markWhenOptional,
39
39
  validity,
40
+ config,
40
41
  }: DataFormControlProps< Item > ) {
42
+ const { compact } = config || {};
41
43
  const { id, label, description, setValue, getValue, isValid } = field;
42
44
  const fieldValue = getValue( { item: data } );
43
45
  const value = typeof fieldValue === 'string' ? fieldValue : undefined;
@@ -179,17 +181,21 @@ function CalendarDateTimeControl< Item >( {
179
181
  onChange={ handleManualDateTimeChange }
180
182
  />
181
183
  { /* Calendar widget */ }
182
- <DateCalendar
183
- style={ { width: '100%' } }
184
- selected={
185
- value ? parseDateTime( value ) || undefined : undefined
186
- }
187
- onSelect={ onSelectDate }
188
- month={ calendarMonth }
189
- onMonthChange={ setCalendarMonth }
190
- timeZone={ timezoneString || undefined }
191
- weekStartsOn={ weekStartsOn }
192
- />
184
+ { ! compact && (
185
+ <DateCalendar
186
+ style={ { width: '100%' } }
187
+ selected={
188
+ value
189
+ ? parseDateTime( value ) || undefined
190
+ : undefined
191
+ }
192
+ onSelect={ onSelectDate }
193
+ month={ calendarMonth }
194
+ onMonthChange={ setCalendarMonth }
195
+ timeZone={ timezoneString || undefined }
196
+ weekStartsOn={ weekStartsOn }
197
+ />
198
+ ) }
193
199
  </Stack>
194
200
  </BaseControl>
195
201
  );
@@ -203,6 +209,7 @@ export default function DateTime< Item >( {
203
209
  markWhenOptional,
204
210
  operator,
205
211
  validity,
212
+ config,
206
213
  }: DataFormControlProps< Item > ) {
207
214
  if ( operator === OPERATOR_IN_THE_PAST || operator === OPERATOR_OVER ) {
208
215
  return (
@@ -225,6 +232,7 @@ export default function DateTime< Item >( {
225
232
  hideLabelFromVision={ hideLabelFromVision }
226
233
  markWhenOptional={ markWhenOptional }
227
234
  validity={ validity }
235
+ config={ config }
228
236
  />
229
237
  );
230
238
  }
@@ -1,13 +1,6 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
- import {
5
- Button,
6
- Card,
7
- CardBody,
8
- CardHeader as OriginalCardHeader,
9
- } from '@wordpress/components';
10
- import { useInstanceId } from '@wordpress/compose';
11
4
  import {
12
5
  useCallback,
13
6
  useContext,
@@ -16,7 +9,10 @@ import {
16
9
  useRef,
17
10
  useState,
18
11
  } from '@wordpress/element';
19
- import { chevronDown, chevronUp } from '@wordpress/icons';
12
+ // TODO: enable in the ESlint rule once we complete
13
+ // https://github.com/WordPress/gutenberg/issues/76135.
14
+ // eslint-disable-next-line @wordpress/use-recommended-components
15
+ import { Card, CollapsibleCard, Stack } from '@wordpress/ui';
20
16
 
21
17
  /**
22
18
  * Internal dependencies
@@ -87,6 +83,113 @@ function isSummaryFieldVisible< Item >(
87
83
  return true;
88
84
  }
89
85
 
86
+ function HeaderContent< Item >( {
87
+ data,
88
+ fields,
89
+ label,
90
+ layout,
91
+ isOpen,
92
+ touched,
93
+ validity,
94
+ }: {
95
+ data: Item;
96
+ fields: NormalizedField< Item >[];
97
+ label: string | undefined;
98
+ layout: NormalizedCardLayout;
99
+ isOpen: boolean;
100
+ touched: boolean;
101
+ validity: FieldLayoutProps< Item >[ 'validity' ];
102
+ } ) {
103
+ const summaryFields = getSummaryFields< Item >( layout.summary, fields );
104
+
105
+ const visibleSummaryFields = summaryFields.filter( ( summaryField ) =>
106
+ isSummaryFieldVisible( summaryField, layout.summary, isOpen )
107
+ );
108
+
109
+ const hasBadge = touched && layout.isCollapsible;
110
+ const hasSummary = visibleSummaryFields.length > 0 && layout.withHeader;
111
+
112
+ return (
113
+ <Stack
114
+ align="center"
115
+ justify="space-between"
116
+ className="dataforms-layouts-card__field-header-content"
117
+ >
118
+ <Card.Title>{ label }</Card.Title>
119
+ { ( hasBadge || hasSummary ) && (
120
+ <CollapsibleCard.HeaderDescription className="dataforms-layouts-card__field-header-content-description">
121
+ { hasBadge && <ValidationBadge validity={ validity } /> }
122
+ { hasSummary && (
123
+ <div className="dataforms-layouts-card__field-summary">
124
+ { visibleSummaryFields.map( ( summaryField ) => (
125
+ <summaryField.render
126
+ key={ summaryField.id }
127
+ item={ data }
128
+ field={ summaryField }
129
+ />
130
+ ) ) }
131
+ </div>
132
+ ) }
133
+ </CollapsibleCard.HeaderDescription>
134
+ ) }
135
+ </Stack>
136
+ );
137
+ }
138
+
139
+ function BodyContent< Item >( {
140
+ data,
141
+ field,
142
+ form,
143
+ onChange,
144
+ hideLabelFromVision,
145
+ markWhenOptional,
146
+ validity,
147
+ withHeader,
148
+ }: {
149
+ data: Item;
150
+ field: FieldLayoutProps< Item >[ 'field' ];
151
+ form: NormalizedForm;
152
+ onChange: FieldLayoutProps< Item >[ 'onChange' ];
153
+ hideLabelFromVision?: boolean;
154
+ markWhenOptional?: boolean;
155
+ validity: FieldLayoutProps< Item >[ 'validity' ];
156
+ withHeader: boolean;
157
+ } ) {
158
+ if ( field.children ) {
159
+ return (
160
+ <>
161
+ { field.description && (
162
+ <div className="dataforms-layouts-card__field-description">
163
+ { field.description }
164
+ </div>
165
+ ) }
166
+ <DataFormLayout
167
+ data={ data }
168
+ form={ form }
169
+ onChange={ onChange }
170
+ validity={ validity?.children }
171
+ />
172
+ </>
173
+ );
174
+ }
175
+
176
+ const SingleFieldLayout = getFormFieldLayout( 'regular' )?.component;
177
+ if ( ! SingleFieldLayout ) {
178
+ return null;
179
+ }
180
+
181
+ return (
182
+ <SingleFieldLayout
183
+ data={ data }
184
+ field={ field }
185
+ onChange={ onChange }
186
+ hideLabelFromVision={ hideLabelFromVision || withHeader }
187
+ markWhenOptional={ markWhenOptional }
188
+ validity={ validity }
189
+ />
190
+ );
191
+ }
192
+
90
193
  export default function FormCardField< Item >( {
91
194
  data,
92
195
  field,
@@ -97,10 +200,7 @@ export default function FormCardField< Item >( {
97
200
  }: FieldLayoutProps< Item > ) {
98
201
  const { fields } = useContext( DataFormContext );
99
202
  const layout = field.layout as NormalizedCardLayout;
100
- const cardBodyRef = useRef< HTMLDivElement >( null );
101
- const instanceId = useInstanceId( FormCardField );
102
- const bodyId = `dataforms-layouts-card-card-body-${ instanceId }`;
103
- const titleId = `dataforms-layouts-card-card-title-${ instanceId }`;
203
+ const contentRef = useRef< HTMLDivElement >( null );
104
204
 
105
205
  const form: NormalizedForm = useMemo(
106
206
  () => ( {
@@ -111,7 +211,7 @@ export default function FormCardField< Item >( {
111
211
  );
112
212
 
113
213
  const { isOpened, isCollapsible } = layout;
114
- const [ internalIsOpen, setIsOpen ] = useState( isOpened );
214
+ const [ isOpen, setIsOpen ] = useState( isOpened );
115
215
  const [ touched, setTouched ] = useState( false );
116
216
 
117
217
  // Sync internal state when the isOpened prop changes.
@@ -120,67 +220,32 @@ export default function FormCardField< Item >( {
120
220
  setIsOpen( isOpened );
121
221
  }, [ isOpened ] );
122
222
 
123
- const toggle = useCallback( () => {
124
- setIsOpen( ( prev ) => {
125
- // Mark as touched when collapsing (going from open to closed)
126
- if ( prev ) {
127
- setTouched( true );
128
- }
129
- return ! prev;
130
- } );
223
+ const handleOpenChange = useCallback( ( open: boolean ) => {
224
+ // Mark as touched when collapsing (going from open to closed)
225
+ if ( ! open ) {
226
+ setTouched( true );
227
+ }
228
+ setIsOpen( open );
131
229
  }, [] );
132
230
 
133
- const isOpen = isCollapsible ? internalIsOpen : true;
134
-
135
231
  // Mark the card as touched when any field inside it is blurred.
136
232
  // This aligns with how validated controls show errors on blur.
137
233
  const handleBlur = useCallback( () => {
138
234
  setTouched( true );
139
- }, [ setTouched ] );
235
+ }, [] );
140
236
 
141
237
  // When the card is expanded after being touched (collapsed with errors),
142
238
  // trigger reportValidity to show field-level errors.
143
- useReportValidity( cardBodyRef, isOpen && touched );
144
-
145
- const summaryFields = getSummaryFields< Item >( layout.summary, fields );
146
-
147
- const visibleSummaryFields = summaryFields.filter( ( summaryField ) =>
148
- isSummaryFieldVisible( summaryField, layout.summary, isOpen )
239
+ useReportValidity(
240
+ contentRef,
241
+ ( isCollapsible ? isOpen : true ) && touched
149
242
  );
150
243
 
151
- const validationBadge =
152
- touched && layout.isCollapsible ? (
153
- <ValidationBadge validity={ validity } />
154
- ) : null;
155
-
156
- const sizeCard = {
157
- blockStart: 'medium' as const,
158
- blockEnd: 'medium' as const,
159
- inlineStart: 'medium' as const,
160
- inlineEnd: 'medium' as const,
161
- };
162
-
163
244
  let label = field.label;
164
245
  let withHeader: boolean;
165
- let bodyContent: React.ReactNode;
166
246
 
167
247
  if ( field.children ) {
168
248
  withHeader = !! label && layout.withHeader;
169
- bodyContent = (
170
- <>
171
- { field.description && (
172
- <div className="dataforms-layouts-card__field-description">
173
- { field.description }
174
- </div>
175
- ) }
176
- <DataFormLayout
177
- data={ data }
178
- form={ form }
179
- onChange={ onChange }
180
- validity={ validity?.children }
181
- />
182
- </>
183
- );
184
249
  } else {
185
250
  const fieldDefinition = fields.find(
186
251
  ( fieldDef ) => fieldDef.id === field.id
@@ -190,101 +255,61 @@ export default function FormCardField< Item >( {
190
255
  return null;
191
256
  }
192
257
 
193
- const SingleFieldLayout = getFormFieldLayout( 'regular' )?.component;
194
- if ( ! SingleFieldLayout ) {
195
- return null;
196
- }
197
-
198
258
  label = fieldDefinition.label;
199
259
  withHeader = !! label && layout.withHeader;
200
- bodyContent = (
201
- <SingleFieldLayout
202
- data={ data }
203
- field={ field }
204
- onChange={ onChange }
205
- hideLabelFromVision={ hideLabelFromVision || withHeader }
206
- markWhenOptional={ markWhenOptional }
207
- validity={ validity }
208
- />
209
- );
210
260
  }
211
261
 
212
- const sizeCardBody = {
213
- blockStart: withHeader ? ( 'none' as const ) : ( 'medium' as const ),
214
- blockEnd: 'medium' as const,
215
- inlineStart: 'medium' as const,
216
- inlineEnd: 'medium' as const,
217
- };
262
+ const bodyContent = (
263
+ <BodyContent
264
+ data={ data }
265
+ field={ field }
266
+ form={ form }
267
+ onChange={ onChange }
268
+ hideLabelFromVision={ hideLabelFromVision }
269
+ markWhenOptional={ markWhenOptional }
270
+ validity={ validity }
271
+ withHeader={ withHeader }
272
+ />
273
+ );
218
274
 
219
- return (
220
- <Card className="dataforms-layouts-card__field" size={ sizeCard }>
221
- { withHeader && (
222
- <OriginalCardHeader
223
- className="dataforms-layouts-card__field-header"
224
- onClick={ isCollapsible ? toggle : undefined }
225
- style={ {
226
- cursor: isCollapsible ? 'pointer' : undefined,
227
- } }
228
- isBorderless
229
- >
230
- <div
231
- style={ {
232
- // Match the expand/collapse button's height to avoid layout
233
- // differences when that button is not displayed.
234
- height: isCollapsible ? undefined : '40px',
235
- width: '100%',
236
- display: 'flex',
237
- justifyContent: 'space-between',
238
- alignItems: 'center',
239
- } }
240
- >
241
- <span
242
- id={ titleId }
243
- className="dataforms-layouts-card__field-header-label"
244
- >
245
- { label }
246
- </span>
247
- { validationBadge }
248
- { visibleSummaryFields.length > 0 &&
249
- layout.withHeader && (
250
- <div className="dataforms-layouts-card__field-summary">
251
- { visibleSummaryFields.map(
252
- ( summaryField ) => (
253
- <summaryField.render
254
- key={ summaryField.id }
255
- item={ data }
256
- field={ summaryField }
257
- />
258
- )
259
- ) }
260
- </div>
261
- ) }
262
- </div>
263
- { isCollapsible && (
264
- <Button
265
- __next40pxDefaultSize
266
- variant="tertiary"
267
- icon={ isOpen ? chevronUp : chevronDown }
268
- aria-expanded={ isOpen }
269
- aria-controls={ bodyId }
270
- aria-labelledby={ titleId }
271
- />
272
- ) }
273
- </OriginalCardHeader>
274
- ) }
275
- { ( isOpen || ! withHeader ) && (
276
- // If it doesn't have a header, keep it open.
277
- // Otherwise, the card will not be visible.
278
- <CardBody
279
- id={ bodyId }
280
- size={ sizeCardBody }
281
- className="dataforms-layouts-card__field-control"
282
- ref={ cardBodyRef }
275
+ const headerContent = (
276
+ <HeaderContent
277
+ data={ data }
278
+ fields={ fields }
279
+ label={ label }
280
+ layout={ layout }
281
+ isOpen={ isCollapsible ? !! isOpen : true }
282
+ touched={ touched }
283
+ validity={ validity }
284
+ />
285
+ );
286
+
287
+ if ( withHeader && isCollapsible ) {
288
+ return (
289
+ <CollapsibleCard.Root
290
+ className="dataforms-layouts-card__field"
291
+ open={ isOpen }
292
+ onOpenChange={ handleOpenChange }
293
+ >
294
+ <CollapsibleCard.Header>
295
+ { headerContent }
296
+ </CollapsibleCard.Header>
297
+ <CollapsibleCard.Content
298
+ ref={ contentRef }
283
299
  onBlur={ handleBlur }
284
300
  >
285
301
  { bodyContent }
286
- </CardBody>
287
- ) }
288
- </Card>
302
+ </CollapsibleCard.Content>
303
+ </CollapsibleCard.Root>
304
+ );
305
+ }
306
+
307
+ return (
308
+ <Card.Root className="dataforms-layouts-card__field">
309
+ { withHeader && <Card.Header>{ headerContent }</Card.Header> }
310
+ <Card.Content ref={ contentRef } onBlur={ handleBlur }>
311
+ { bodyContent }
312
+ </Card.Content>
313
+ </Card.Root>
289
314
  );
290
315
  }
@@ -1,15 +1,18 @@
1
1
  @use "@wordpress/base-styles/colors" as *;
2
2
  @use "@wordpress/base-styles/variables" as *;
3
- @use "@wordpress/base-styles/mixins" as *;
4
-
5
- .dataforms-layouts-card__field-header-label {
6
- @include heading-large();
7
- }
8
3
 
9
4
  .dataforms-layouts-card__field {
10
5
  width: 100%;
11
6
  }
12
7
 
8
+ .dataforms-layouts-card__field-header-content {
9
+ min-height: 24px; // TODO: use size / height DS token when available
10
+ }
11
+
12
+ .dataforms-layouts-card__field-header-content-description {
13
+ display: contents;
14
+ }
15
+
13
16
  .dataforms-layouts-card__field-description {
14
17
  color: $gray-700;
15
18
  display: block;
@@ -95,6 +95,7 @@ interface BulkSelectionCheckboxProps< Item > {
95
95
  data: Item[];
96
96
  actions: Action< Item >[];
97
97
  getItemId: ( item: Item ) => string;
98
+ disableSelectAll?: boolean;
98
99
  }
99
100
 
100
101
  export function BulkSelectionCheckbox< Item >( {
@@ -103,6 +104,7 @@ export function BulkSelectionCheckbox< Item >( {
103
104
  data,
104
105
  actions,
105
106
  getItemId,
107
+ disableSelectAll = false,
106
108
  }: BulkSelectionCheckboxProps< Item > ) {
107
109
  const selectableItems = useMemo( () => {
108
110
  return data.filter( ( item ) => {
@@ -118,7 +120,23 @@ export function BulkSelectionCheckbox< Item >( {
118
120
  selection.includes( getItemId( item ) ) &&
119
121
  selectableItems.includes( item )
120
122
  );
123
+ const hasSelection = selection.length > 0;
121
124
  const areAllSelected = selectedItems.length === selectableItems.length;
125
+
126
+ if ( disableSelectAll ) {
127
+ return (
128
+ <CheckboxControl
129
+ className="dataviews-view-table-selection-checkbox"
130
+ checked={ hasSelection }
131
+ disabled={ ! hasSelection }
132
+ onChange={ () => {
133
+ onChangeSelection( [] );
134
+ } }
135
+ aria-label={ __( 'Deselect all' ) }
136
+ />
137
+ );
138
+ }
139
+
122
140
  return (
123
141
  <CheckboxControl
124
142
  className="dataviews-view-table-selection-checkbox"
@@ -153,6 +171,7 @@ interface ToolbarContentProps< Item > {
153
171
  data: Item[];
154
172
  actions: Action< Item >[];
155
173
  getItemId: ( item: Item ) => string;
174
+ isInfiniteScroll: boolean;
156
175
  paginationInfo: {
157
176
  totalItems: number;
158
177
  totalPages: number;
@@ -241,6 +260,7 @@ function renderFooterContent< Item >(
241
260
  data: Item[],
242
261
  actions: Action< Item >[],
243
262
  getItemId: ( item: Item ) => string,
263
+ isInfiniteScroll: boolean,
244
264
  selection: string[],
245
265
  actionsToShow: Action< Item >[],
246
266
  selectedItems: Item[],
@@ -255,7 +275,8 @@ function renderFooterContent< Item >(
255
275
  const message = getFooterMessage(
256
276
  selection.length,
257
277
  data.length,
258
- paginationInfo.totalItems
278
+ paginationInfo.totalItems,
279
+ isInfiniteScroll
259
280
  );
260
281
  return (
261
282
  <Stack
@@ -270,6 +291,7 @@ function renderFooterContent< Item >(
270
291
  data={ data }
271
292
  actions={ actions }
272
293
  getItemId={ getItemId }
294
+ disableSelectAll={ isInfiniteScroll }
273
295
  />
274
296
  <span className="dataviews-bulk-actions-footer__item-count">
275
297
  { message }
@@ -315,6 +337,7 @@ function FooterContent< Item >( {
315
337
  onChangeSelection,
316
338
  data,
317
339
  getItemId,
340
+ isInfiniteScroll,
318
341
  paginationInfo,
319
342
  }: ToolbarContentProps< Item > ) {
320
343
  const [ actionInProgress, setActionInProgress ] = useState< string | null >(
@@ -365,6 +388,7 @@ function FooterContent< Item >( {
365
388
  data,
366
389
  actions,
367
390
  getItemId,
391
+ isInfiniteScroll,
368
392
  selection,
369
393
  actionsToShow,
370
394
  selectedItems,
@@ -378,6 +402,7 @@ function FooterContent< Item >( {
378
402
  data,
379
403
  actions,
380
404
  getItemId,
405
+ isInfiniteScroll,
381
406
  selection,
382
407
  actionsToShow,
383
408
  selectedItems,
@@ -398,6 +423,7 @@ export function BulkActionsFooter() {
398
423
  onChangeSelection,
399
424
  getItemId,
400
425
  paginationInfo,
426
+ view,
401
427
  } = useContext( DataViewsContext );
402
428
  return (
403
429
  <FooterContent
@@ -406,6 +432,7 @@ export function BulkActionsFooter() {
406
432
  data={ data }
407
433
  actions={ actions }
408
434
  getItemId={ getItemId }
435
+ isInfiniteScroll={ !! view.infiniteScrollEnabled }
409
436
  paginationInfo={ paginationInfo }
410
437
  />
411
438
  );
@@ -57,9 +57,9 @@ type DataViewsContextType< Item > = {
57
57
  config: { perPageSizes: number[] };
58
58
  empty?: ReactNode;
59
59
  hasInitiallyLoaded?: boolean;
60
- hasInfiniteScrollHandler: boolean;
61
60
  itemListLabel?: string;
62
61
  onReset?: ( () => void ) | false;
62
+ intersectionObserver?: IntersectionObserver | null;
63
63
  };
64
64
 
65
65
  const DataViewsContext = createContext< DataViewsContextType< any > >( {
@@ -86,10 +86,10 @@ const DataViewsContext = createContext< DataViewsContextType< any > >( {
86
86
  isShowingFilter: false,
87
87
  setIsShowingFilter: () => {},
88
88
  hasInitiallyLoaded: false,
89
- hasInfiniteScrollHandler: false,
90
89
  config: {
91
90
  perPageSizes: [],
92
91
  },
92
+ intersectionObserver: null,
93
93
  } );
94
94
 
95
95
  DataViewsContext.displayName = 'DataViewsContext';
@@ -31,14 +31,9 @@ export default function DataViewsFooter() {
31
31
  actions = EMPTY_ARRAY,
32
32
  isLoading,
33
33
  hasInitiallyLoaded,
34
- hasInfiniteScrollHandler,
35
34
  } = useContext( DataViewsContext );
36
35
 
37
- const isRefreshing =
38
- !! isLoading &&
39
- hasInitiallyLoaded &&
40
- ! hasInfiniteScrollHandler &&
41
- !! data?.length;
36
+ const isRefreshing = !! isLoading && hasInitiallyLoaded && !! data?.length;
42
37
 
43
38
  const isDelayedRefreshing = useDelayedLoading( !! isRefreshing );
44
39