@wordpress/dataviews 4.21.0 → 5.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 (343) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/README.md +147 -32
  3. package/build/components/dataviews/index.js +71 -37
  4. package/build/components/dataviews/index.js.map +1 -1
  5. package/build/components/dataviews-context/index.js +15 -1
  6. package/build/components/dataviews-context/index.js.map +1 -1
  7. package/build/components/dataviews-filters/{filter-summary.js → filter.js} +108 -17
  8. package/build/components/dataviews-filters/filter.js.map +1 -0
  9. package/build/components/dataviews-filters/index.js +21 -20
  10. package/build/components/dataviews-filters/index.js.map +1 -1
  11. package/build/components/dataviews-filters/input-widget.js +76 -0
  12. package/build/components/dataviews-filters/input-widget.js.map +1 -0
  13. package/build/components/dataviews-filters/search-widget.js +33 -39
  14. package/build/components/dataviews-filters/search-widget.js.map +1 -1
  15. package/build/components/dataviews-filters/utils.js +25 -0
  16. package/build/components/dataviews-filters/utils.js.map +1 -0
  17. package/build/components/dataviews-item-actions/index.js +1 -1
  18. package/build/components/dataviews-item-actions/index.js.map +1 -1
  19. package/build/components/dataviews-layout/index.js +7 -2
  20. package/build/components/dataviews-layout/index.js.map +1 -1
  21. package/build/components/dataviews-pagination/index.js +4 -3
  22. package/build/components/dataviews-pagination/index.js.map +1 -1
  23. package/build/components/dataviews-selection-checkbox/index.js.map +1 -1
  24. package/build/components/dataviews-view-config/index.js +10 -19
  25. package/build/components/dataviews-view-config/index.js.map +1 -1
  26. package/build/constants.js +83 -2
  27. package/build/constants.js.map +1 -1
  28. package/build/dataform-controls/boolean.js +42 -0
  29. package/build/dataform-controls/boolean.js.map +1 -0
  30. package/build/dataform-controls/checkbox.js +44 -0
  31. package/build/dataform-controls/checkbox.js.map +1 -0
  32. package/build/dataform-controls/datetime.js +96 -2
  33. package/build/dataform-controls/datetime.js.map +1 -1
  34. package/build/dataform-controls/email.js +48 -0
  35. package/build/dataform-controls/email.js.map +1 -0
  36. package/build/dataform-controls/index.js +9 -1
  37. package/build/dataform-controls/index.js.map +1 -1
  38. package/build/dataform-controls/integer.js +49 -1
  39. package/build/dataform-controls/integer.js.map +1 -1
  40. package/build/dataform-controls/select.js +1 -0
  41. package/build/dataform-controls/select.js.map +1 -1
  42. package/build/dataform-controls/text.js +3 -1
  43. package/build/dataform-controls/text.js.map +1 -1
  44. package/build/dataform-controls/toggle-group.js +52 -0
  45. package/build/dataform-controls/toggle-group.js.map +1 -0
  46. package/build/dataforms-layouts/data-form-layout.js +1 -1
  47. package/build/dataforms-layouts/data-form-layout.js.map +1 -1
  48. package/build/dataforms-layouts/panel/index.js +14 -5
  49. package/build/dataforms-layouts/panel/index.js.map +1 -1
  50. package/build/dataforms-layouts/regular/index.js +23 -4
  51. package/build/dataforms-layouts/regular/index.js.map +1 -1
  52. package/build/dataviews-layouts/grid/index.js +89 -27
  53. package/build/dataviews-layouts/grid/index.js.map +1 -1
  54. package/build/dataviews-layouts/list/index.js +11 -6
  55. package/build/dataviews-layouts/list/index.js.map +1 -1
  56. package/build/dataviews-layouts/table/column-header-menu.js +9 -7
  57. package/build/dataviews-layouts/table/column-header-menu.js.map +1 -1
  58. package/build/dataviews-layouts/table/column-primary.js +18 -13
  59. package/build/dataviews-layouts/table/column-primary.js.map +1 -1
  60. package/build/dataviews-layouts/table/index.js +46 -14
  61. package/build/dataviews-layouts/table/index.js.map +1 -1
  62. package/build/dataviews-layouts/table/use-is-horizontal-scroll-end.js +65 -0
  63. package/build/dataviews-layouts/table/use-is-horizontal-scroll-end.js.map +1 -0
  64. package/build/dataviews-layouts/utils/item-click-wrapper.js +77 -0
  65. package/build/dataviews-layouts/utils/item-click-wrapper.js.map +1 -0
  66. package/build/field-types/array.js +62 -0
  67. package/build/field-types/array.js.map +1 -0
  68. package/build/field-types/boolean.js +71 -0
  69. package/build/field-types/boolean.js.map +1 -0
  70. package/build/field-types/date.js +57 -0
  71. package/build/field-types/date.js.map +1 -0
  72. package/build/field-types/datetime.js +19 -1
  73. package/build/field-types/datetime.js.map +1 -1
  74. package/build/field-types/email.js +60 -0
  75. package/build/field-types/email.js.map +1 -0
  76. package/build/field-types/index.js +42 -1
  77. package/build/field-types/index.js.map +1 -1
  78. package/build/field-types/integer.js +23 -1
  79. package/build/field-types/integer.js.map +1 -1
  80. package/build/field-types/media.js +31 -0
  81. package/build/field-types/media.js.map +1 -0
  82. package/build/field-types/text.js +23 -1
  83. package/build/field-types/text.js.map +1 -1
  84. package/build/filter-and-sort-data-view.js +174 -11
  85. package/build/filter-and-sort-data-view.js.map +1 -1
  86. package/build/normalize-fields.js +72 -11
  87. package/build/normalize-fields.js.map +1 -1
  88. package/build/types.js.map +1 -1
  89. package/build/utils.js +11 -19
  90. package/build/utils.js.map +1 -1
  91. package/build-module/components/dataviews/index.js +74 -40
  92. package/build-module/components/dataviews/index.js.map +1 -1
  93. package/build-module/components/dataviews-context/index.js +16 -2
  94. package/build-module/components/dataviews-context/index.js.map +1 -1
  95. package/build-module/components/dataviews-filters/filter.js +309 -0
  96. package/build-module/components/dataviews-filters/filter.js.map +1 -0
  97. package/build-module/components/dataviews-filters/index.js +22 -21
  98. package/build-module/components/dataviews-filters/index.js.map +1 -1
  99. package/build-module/components/dataviews-filters/input-widget.js +69 -0
  100. package/build-module/components/dataviews-filters/input-widget.js.map +1 -0
  101. package/build-module/components/dataviews-filters/search-widget.js +31 -37
  102. package/build-module/components/dataviews-filters/search-widget.js.map +1 -1
  103. package/build-module/components/dataviews-filters/utils.js +18 -0
  104. package/build-module/components/dataviews-filters/utils.js.map +1 -0
  105. package/build-module/components/dataviews-item-actions/index.js +1 -1
  106. package/build-module/components/dataviews-item-actions/index.js.map +1 -1
  107. package/build-module/components/dataviews-layout/index.js +7 -2
  108. package/build-module/components/dataviews-layout/index.js.map +1 -1
  109. package/build-module/components/dataviews-pagination/index.js +4 -4
  110. package/build-module/components/dataviews-pagination/index.js.map +1 -1
  111. package/build-module/components/dataviews-selection-checkbox/index.js.map +1 -1
  112. package/build-module/components/dataviews-view-config/index.js +9 -20
  113. package/build-module/components/dataviews-view-config/index.js.map +1 -1
  114. package/build-module/constants.js +82 -1
  115. package/build-module/constants.js.map +1 -1
  116. package/build-module/dataform-controls/boolean.js +35 -0
  117. package/build-module/dataform-controls/boolean.js.map +1 -0
  118. package/build-module/dataform-controls/checkbox.js +37 -0
  119. package/build-module/dataform-controls/checkbox.js.map +1 -0
  120. package/build-module/dataform-controls/datetime.js +98 -3
  121. package/build-module/dataform-controls/datetime.js.map +1 -1
  122. package/build-module/dataform-controls/email.js +41 -0
  123. package/build-module/dataform-controls/email.js.map +1 -0
  124. package/build-module/dataform-controls/index.js +9 -1
  125. package/build-module/dataform-controls/index.js.map +1 -1
  126. package/build-module/dataform-controls/integer.js +51 -3
  127. package/build-module/dataform-controls/integer.js.map +1 -1
  128. package/build-module/dataform-controls/select.js +1 -0
  129. package/build-module/dataform-controls/select.js.map +1 -1
  130. package/build-module/dataform-controls/text.js +3 -1
  131. package/build-module/dataform-controls/text.js.map +1 -1
  132. package/build-module/dataform-controls/toggle-group.js +45 -0
  133. package/build-module/dataform-controls/toggle-group.js.map +1 -0
  134. package/build-module/dataforms-layouts/data-form-layout.js +1 -1
  135. package/build-module/dataforms-layouts/data-form-layout.js.map +1 -1
  136. package/build-module/dataforms-layouts/panel/index.js +14 -5
  137. package/build-module/dataforms-layouts/panel/index.js.map +1 -1
  138. package/build-module/dataforms-layouts/regular/index.js +23 -4
  139. package/build-module/dataforms-layouts/regular/index.js.map +1 -1
  140. package/build-module/dataviews-layouts/grid/index.js +90 -29
  141. package/build-module/dataviews-layouts/grid/index.js.map +1 -1
  142. package/build-module/dataviews-layouts/list/index.js +11 -6
  143. package/build-module/dataviews-layouts/list/index.js.map +1 -1
  144. package/build-module/dataviews-layouts/table/column-header-menu.js +9 -7
  145. package/build-module/dataviews-layouts/table/column-header-menu.js.map +1 -1
  146. package/build-module/dataviews-layouts/table/column-primary.js +18 -12
  147. package/build-module/dataviews-layouts/table/column-primary.js.map +1 -1
  148. package/build-module/dataviews-layouts/table/index.js +47 -16
  149. package/build-module/dataviews-layouts/table/index.js.map +1 -1
  150. package/build-module/dataviews-layouts/table/use-is-horizontal-scroll-end.js +58 -0
  151. package/build-module/dataviews-layouts/table/use-is-horizontal-scroll-end.js.map +1 -0
  152. package/build-module/dataviews-layouts/utils/item-click-wrapper.js +71 -0
  153. package/build-module/dataviews-layouts/utils/item-click-wrapper.js.map +1 -0
  154. package/build-module/field-types/array.js +57 -0
  155. package/build-module/field-types/array.js.map +1 -0
  156. package/build-module/field-types/boolean.js +65 -0
  157. package/build-module/field-types/boolean.js.map +1 -0
  158. package/build-module/field-types/date.js +51 -0
  159. package/build-module/field-types/date.js.map +1 -0
  160. package/build-module/field-types/datetime.js +19 -1
  161. package/build-module/field-types/datetime.js.map +1 -1
  162. package/build-module/field-types/email.js +54 -0
  163. package/build-module/field-types/email.js.map +1 -0
  164. package/build-module/field-types/index.js +42 -1
  165. package/build-module/field-types/index.js.map +1 -1
  166. package/build-module/field-types/integer.js +23 -1
  167. package/build-module/field-types/integer.js.map +1 -1
  168. package/build-module/field-types/media.js +25 -0
  169. package/build-module/field-types/media.js.map +1 -0
  170. package/build-module/field-types/text.js +23 -1
  171. package/build-module/field-types/text.js.map +1 -1
  172. package/build-module/filter-and-sort-data-view.js +175 -12
  173. package/build-module/filter-and-sort-data-view.js.map +1 -1
  174. package/build-module/normalize-fields.js +72 -11
  175. package/build-module/normalize-fields.js.map +1 -1
  176. package/build-module/types.js.map +1 -1
  177. package/build-module/utils.js +10 -17
  178. package/build-module/utils.js.map +1 -1
  179. package/build-style/style-rtl.css +317 -15
  180. package/build-style/style.css +317 -15
  181. package/build-types/components/dataform/stories/index.story.d.ts.map +1 -1
  182. package/build-types/components/dataviews/index.d.ts +24 -3
  183. package/build-types/components/dataviews/index.d.ts.map +1 -1
  184. package/build-types/components/dataviews/stories/fixtures.d.ts +10 -1
  185. package/build-types/components/dataviews/stories/fixtures.d.ts.map +1 -1
  186. package/build-types/components/dataviews/stories/index.story.d.ts +23 -4
  187. package/build-types/components/dataviews/stories/index.story.d.ts.map +1 -1
  188. package/build-types/components/dataviews-context/index.d.ts +14 -1
  189. package/build-types/components/dataviews-context/index.d.ts.map +1 -1
  190. package/build-types/components/dataviews-filters/filter.d.ts +15 -0
  191. package/build-types/components/dataviews-filters/filter.d.ts.map +1 -0
  192. package/build-types/components/dataviews-filters/index.d.ts +3 -8
  193. package/build-types/components/dataviews-filters/index.d.ts.map +1 -1
  194. package/build-types/components/dataviews-filters/input-widget.d.ts +13 -0
  195. package/build-types/components/dataviews-filters/input-widget.d.ts.map +1 -0
  196. package/build-types/components/dataviews-filters/search-widget.d.ts +4 -5
  197. package/build-types/components/dataviews-filters/search-widget.d.ts.map +1 -1
  198. package/build-types/components/dataviews-filters/utils.d.ts +6 -0
  199. package/build-types/components/dataviews-filters/utils.d.ts.map +1 -0
  200. package/build-types/components/dataviews-layout/index.d.ts +5 -1
  201. package/build-types/components/dataviews-layout/index.d.ts.map +1 -1
  202. package/build-types/components/dataviews-pagination/index.d.ts +1 -1
  203. package/build-types/components/dataviews-pagination/index.d.ts.map +1 -1
  204. package/build-types/components/dataviews-selection-checkbox/index.d.ts +2 -2
  205. package/build-types/components/dataviews-selection-checkbox/index.d.ts.map +1 -1
  206. package/build-types/components/dataviews-view-config/index.d.ts +3 -4
  207. package/build-types/components/dataviews-view-config/index.d.ts.map +1 -1
  208. package/build-types/components/stories/index.story.d.ts +63 -0
  209. package/build-types/components/stories/index.story.d.ts.map +1 -0
  210. package/build-types/constants.d.ts +20 -3
  211. package/build-types/constants.d.ts.map +1 -1
  212. package/build-types/dataform-controls/boolean.d.ts +6 -0
  213. package/build-types/dataform-controls/boolean.d.ts.map +1 -0
  214. package/build-types/dataform-controls/checkbox.d.ts +6 -0
  215. package/build-types/dataform-controls/checkbox.d.ts.map +1 -0
  216. package/build-types/dataform-controls/datetime.d.ts +1 -1
  217. package/build-types/dataform-controls/datetime.d.ts.map +1 -1
  218. package/build-types/dataform-controls/email.d.ts +6 -0
  219. package/build-types/dataform-controls/email.d.ts.map +1 -0
  220. package/build-types/dataform-controls/index.d.ts +1 -1
  221. package/build-types/dataform-controls/index.d.ts.map +1 -1
  222. package/build-types/dataform-controls/integer.d.ts +1 -4
  223. package/build-types/dataform-controls/integer.d.ts.map +1 -1
  224. package/build-types/dataform-controls/select.d.ts.map +1 -1
  225. package/build-types/dataform-controls/text.d.ts.map +1 -1
  226. package/build-types/dataform-controls/toggle-group.d.ts +6 -0
  227. package/build-types/dataform-controls/toggle-group.d.ts.map +1 -0
  228. package/build-types/dataforms-layouts/panel/index.d.ts.map +1 -1
  229. package/build-types/dataforms-layouts/regular/index.d.ts.map +1 -1
  230. package/build-types/dataviews-layouts/grid/index.d.ts +2 -1
  231. package/build-types/dataviews-layouts/grid/index.d.ts.map +1 -1
  232. package/build-types/dataviews-layouts/index.d.ts +3 -3
  233. package/build-types/dataviews-layouts/list/index.d.ts.map +1 -1
  234. package/build-types/dataviews-layouts/table/column-header-menu.d.ts.map +1 -1
  235. package/build-types/dataviews-layouts/table/column-primary.d.ts +8 -1
  236. package/build-types/dataviews-layouts/table/column-primary.d.ts.map +1 -1
  237. package/build-types/dataviews-layouts/table/index.d.ts +1 -1
  238. package/build-types/dataviews-layouts/table/index.d.ts.map +1 -1
  239. package/build-types/dataviews-layouts/table/use-is-horizontal-scroll-end.d.ts +19 -0
  240. package/build-types/dataviews-layouts/table/use-is-horizontal-scroll-end.d.ts.map +1 -0
  241. package/build-types/dataviews-layouts/utils/item-click-wrapper.d.ts +15 -0
  242. package/build-types/dataviews-layouts/utils/item-click-wrapper.d.ts.map +1 -0
  243. package/build-types/field-types/array.d.ts +7 -0
  244. package/build-types/field-types/array.d.ts.map +1 -0
  245. package/build-types/field-types/boolean.d.ts +19 -0
  246. package/build-types/field-types/boolean.d.ts.map +1 -0
  247. package/build-types/field-types/date.d.ts +16 -0
  248. package/build-types/field-types/date.d.ts.map +1 -0
  249. package/build-types/field-types/datetime.d.ts +7 -1
  250. package/build-types/field-types/datetime.d.ts.map +1 -1
  251. package/build-types/field-types/email.d.ts +19 -0
  252. package/build-types/field-types/email.d.ts.map +1 -0
  253. package/build-types/field-types/index.d.ts +2 -10
  254. package/build-types/field-types/index.d.ts.map +1 -1
  255. package/build-types/field-types/integer.d.ts +7 -1
  256. package/build-types/field-types/integer.d.ts.map +1 -1
  257. package/build-types/field-types/media.d.ts +16 -0
  258. package/build-types/field-types/media.d.ts.map +1 -0
  259. package/build-types/field-types/text.d.ts +7 -1
  260. package/build-types/field-types/text.d.ts.map +1 -1
  261. package/build-types/filter-and-sort-data-view.d.ts.map +1 -1
  262. package/build-types/normalize-fields.d.ts.map +1 -1
  263. package/build-types/types.d.ts +74 -8
  264. package/build-types/types.d.ts.map +1 -1
  265. package/build-types/utils.d.ts +5 -2
  266. package/build-types/utils.d.ts.map +1 -1
  267. package/build-wp/index.js +3299 -1182
  268. package/package.json +18 -12
  269. package/src/components/dataform/stories/index.story.tsx +41 -20
  270. package/src/components/dataviews/index.tsx +108 -43
  271. package/src/components/dataviews/stories/fixtures.tsx +135 -69
  272. package/src/components/dataviews/stories/index.story.tsx +265 -7
  273. package/src/components/dataviews/stories/style.css +24 -3
  274. package/src/components/dataviews/style.scss +27 -0
  275. package/src/components/dataviews-context/index.ts +30 -2
  276. package/src/components/dataviews-filters/filter.tsx +603 -0
  277. package/src/components/dataviews-filters/index.tsx +23 -29
  278. package/src/components/dataviews-filters/input-widget.tsx +91 -0
  279. package/src/components/dataviews-filters/search-widget.tsx +51 -48
  280. package/src/components/dataviews-filters/style.scss +117 -14
  281. package/src/components/dataviews-filters/utils.ts +25 -0
  282. package/src/components/dataviews-item-actions/index.tsx +1 -1
  283. package/src/components/dataviews-layout/index.tsx +8 -1
  284. package/src/components/dataviews-pagination/index.tsx +4 -4
  285. package/src/components/dataviews-selection-checkbox/index.tsx +2 -2
  286. package/src/components/dataviews-view-config/index.tsx +10 -18
  287. package/src/components/stories/index.story.tsx +372 -0
  288. package/src/constants.ts +116 -1
  289. package/src/dataform-controls/boolean.tsx +30 -0
  290. package/src/dataform-controls/checkbox.tsx +31 -0
  291. package/src/dataform-controls/datetime.tsx +106 -2
  292. package/src/dataform-controls/email.tsx +42 -0
  293. package/src/dataform-controls/index.tsx +8 -0
  294. package/src/dataform-controls/integer.tsx +75 -1
  295. package/src/dataform-controls/select.tsx +1 -0
  296. package/src/dataform-controls/style.scss +5 -0
  297. package/src/dataform-controls/text.tsx +2 -1
  298. package/src/dataform-controls/toggle-group.tsx +59 -0
  299. package/src/dataforms-layouts/data-form-layout.tsx +1 -1
  300. package/src/dataforms-layouts/panel/index.tsx +19 -7
  301. package/src/dataforms-layouts/panel/style.scss +8 -1
  302. package/src/dataforms-layouts/regular/index.tsx +50 -17
  303. package/src/dataforms-layouts/regular/style.scss +4 -1
  304. package/src/dataviews-layouts/grid/index.tsx +180 -68
  305. package/src/dataviews-layouts/grid/style.scss +8 -0
  306. package/src/dataviews-layouts/list/index.tsx +12 -5
  307. package/src/dataviews-layouts/table/column-header-menu.tsx +10 -8
  308. package/src/dataviews-layouts/table/column-primary.tsx +26 -13
  309. package/src/dataviews-layouts/table/index.tsx +74 -10
  310. package/src/dataviews-layouts/table/style.scss +37 -1
  311. package/src/dataviews-layouts/table/use-is-horizontal-scroll-end.ts +82 -0
  312. package/src/dataviews-layouts/utils/item-click-wrapper.tsx +93 -0
  313. package/src/field-types/array.tsx +75 -0
  314. package/src/field-types/boolean.tsx +66 -0
  315. package/src/field-types/date.ts +56 -0
  316. package/src/field-types/datetime.tsx +46 -2
  317. package/src/field-types/email.tsx +79 -0
  318. package/src/field-types/index.tsx +50 -3
  319. package/src/field-types/integer.tsx +53 -2
  320. package/src/field-types/media.tsx +28 -0
  321. package/src/field-types/text.tsx +41 -2
  322. package/src/filter-and-sort-data-view.ts +270 -10
  323. package/src/normalize-fields.ts +116 -13
  324. package/src/test/dataviews.tsx +20 -2
  325. package/src/test/filter-and-sort-data-view.js +601 -25
  326. package/src/test/normalize-fields.ts +155 -0
  327. package/src/types.ts +112 -9
  328. package/src/utils.ts +10 -33
  329. package/tsconfig.json +2 -0
  330. package/tsconfig.tsbuildinfo +1 -1
  331. package/build/components/dataviews-filters/filter-summary.js.map +0 -1
  332. package/build/dataviews-layouts/utils/get-clickable-item-props.js +0 -36
  333. package/build/dataviews-layouts/utils/get-clickable-item-props.js.map +0 -1
  334. package/build-module/components/dataviews-filters/filter-summary.js +0 -218
  335. package/build-module/components/dataviews-filters/filter-summary.js.map +0 -1
  336. package/build-module/dataviews-layouts/utils/get-clickable-item-props.js +0 -30
  337. package/build-module/dataviews-layouts/utils/get-clickable-item-props.js.map +0 -1
  338. package/build-types/components/dataviews-filters/filter-summary.d.ts +0 -14
  339. package/build-types/components/dataviews-filters/filter-summary.d.ts.map +0 -1
  340. package/build-types/dataviews-layouts/utils/get-clickable-item-props.d.ts +0 -19
  341. package/build-types/dataviews-layouts/utils/get-clickable-item-props.d.ts.map +0 -1
  342. package/src/components/dataviews-filters/filter-summary.tsx +0 -338
  343. package/src/dataviews-layouts/utils/get-clickable-item-props.ts +0 -39
@@ -2,17 +2,25 @@
2
2
  * External dependencies
3
3
  */
4
4
  import clsx from 'clsx';
5
+ import type { ComponentProps, ReactElement } from 'react';
5
6
 
6
7
  /**
7
8
  * WordPress dependencies
8
9
  */
9
10
  import { __ } from '@wordpress/i18n';
10
11
  import { Spinner } from '@wordpress/components';
11
- import { useEffect, useId, useRef, useState } from '@wordpress/element';
12
+ import {
13
+ useContext,
14
+ useEffect,
15
+ useId,
16
+ useRef,
17
+ useState,
18
+ } from '@wordpress/element';
12
19
 
13
20
  /**
14
21
  * Internal dependencies
15
22
  */
23
+ import DataViewsContext from '../../components/dataviews-context';
16
24
  import DataViewsSelectionCheckbox from '../../components/dataviews-selection-checkbox';
17
25
  import ItemActions from '../../components/dataviews-item-actions';
18
26
  import { sortValues } from '../../constants';
@@ -30,11 +38,13 @@ import type {
30
38
  import type { SetSelection } from '../../private-types';
31
39
  import ColumnHeaderMenu from './column-header-menu';
32
40
  import ColumnPrimary from './column-primary';
41
+ import { useIsHorizontalScrollEnd } from './use-is-horizontal-scroll-end';
33
42
 
34
43
  interface TableColumnFieldProps< Item > {
35
44
  fields: NormalizedField< Item >[];
36
45
  column: string;
37
46
  item: Item;
47
+ align?: 'start' | 'center' | 'end';
38
48
  }
39
49
 
40
50
  interface TableRowProps< Item > {
@@ -53,12 +63,19 @@ interface TableRowProps< Item > {
53
63
  onChangeSelection: SetSelection;
54
64
  isItemClickable: ( item: Item ) => boolean;
55
65
  onClickItem?: ( item: Item ) => void;
66
+ renderItemLink?: (
67
+ props: {
68
+ item: Item;
69
+ } & ComponentProps< 'a' >
70
+ ) => ReactElement;
71
+ isActionsColumnSticky?: boolean;
56
72
  }
57
73
 
58
74
  function TableColumnField< Item >( {
59
75
  item,
60
76
  fields,
61
77
  column,
78
+ align,
62
79
  }: TableColumnFieldProps< Item > ) {
63
80
  const field = fields.find( ( f ) => f.id === column );
64
81
 
@@ -66,9 +83,14 @@ function TableColumnField< Item >( {
66
83
  return null;
67
84
  }
68
85
 
86
+ const className = clsx( 'dataviews-view-table__cell-content-wrapper', {
87
+ 'dataviews-view-table__cell-align-end': align === 'end',
88
+ 'dataviews-view-table__cell-align-center': align === 'center',
89
+ } );
90
+
69
91
  return (
70
- <div className="dataviews-view-table__cell-content-wrapper">
71
- <field.render { ...{ item } } />
92
+ <div className={ className }>
93
+ <field.render item={ item } field={ field } />
72
94
  </div>
73
95
  );
74
96
  }
@@ -88,7 +110,9 @@ function TableRow< Item >( {
88
110
  getItemId,
89
111
  isItemClickable,
90
112
  onClickItem,
113
+ renderItemLink,
91
114
  onChangeSelection,
115
+ isActionsColumnSticky,
92
116
  }: TableRowProps< Item > ) {
93
117
  const hasPossibleBulkAction = useHasAPossibleBulkAction( actions, item );
94
118
  const isSelected = hasPossibleBulkAction && selection.includes( id );
@@ -165,20 +189,29 @@ function TableRow< Item >( {
165
189
  }
166
190
  isItemClickable={ isItemClickable }
167
191
  onClickItem={ onClickItem }
192
+ renderItemLink={ renderItemLink }
168
193
  />
169
194
  </td>
170
195
  ) }
171
196
  { columns.map( ( column: string ) => {
172
197
  // Explicit picks the supported styles.
173
- const { width, maxWidth, minWidth } =
198
+ const { width, maxWidth, minWidth, align } =
174
199
  view.layout?.styles?.[ column ] ?? {};
175
200
 
176
201
  return (
177
- <td key={ column } style={ { width, maxWidth, minWidth } }>
202
+ <td
203
+ key={ column }
204
+ style={ {
205
+ width,
206
+ maxWidth,
207
+ minWidth,
208
+ } }
209
+ >
178
210
  <TableColumnField
179
211
  fields={ fields }
180
212
  item={ item }
181
213
  column={ column }
214
+ align={ align }
182
215
  />
183
216
  </td>
184
217
  );
@@ -192,7 +225,11 @@ function TableRow< Item >( {
192
225
 
193
226
  /* eslint-disable jsx-a11y/no-noninteractive-element-interactions, jsx-a11y/click-events-have-key-events */
194
227
  <td
195
- className="dataviews-view-table__actions-column"
228
+ className={ clsx( 'dataviews-view-table__actions-column', {
229
+ 'dataviews-view-table__actions-column--sticky': true,
230
+ 'dataviews-view-table__actions-column--stuck':
231
+ isActionsColumnSticky,
232
+ } ) }
196
233
  onClick={ ( e ) => e.stopPropagation() }
197
234
  >
198
235
  <ItemActions item={ item } actions={ actions } />
@@ -216,8 +253,11 @@ function ViewTable< Item >( {
216
253
  setOpenedFilter,
217
254
  onClickItem,
218
255
  isItemClickable,
256
+ renderItemLink,
219
257
  view,
258
+ className,
220
259
  }: ViewTableProps< Item > ) {
260
+ const { containerRef } = useContext( DataViewsContext );
221
261
  const headerMenuRefs = useRef<
222
262
  Map< string, { node: HTMLButtonElement; fallback: string } >
223
263
  >( new Map() );
@@ -235,6 +275,11 @@ function ViewTable< Item >( {
235
275
 
236
276
  const tableNoticeId = useId();
237
277
 
278
+ const isHorizontalScrollEnd = useIsHorizontalScrollEnd( {
279
+ scrollContainerRef: containerRef,
280
+ enabled: !! actions?.length,
281
+ } );
282
+
238
283
  if ( nextHeaderMenuToFocus ) {
239
284
  // If we need to force focus, we short-circuit rendering here
240
285
  // to prevent any additional work while we handle that.
@@ -281,7 +326,7 @@ function ViewTable< Item >( {
281
326
  return (
282
327
  <>
283
328
  <table
284
- className={ clsx( 'dataviews-view-table', {
329
+ className={ clsx( 'dataviews-view-table', className, {
285
330
  [ `has-${ view.layout?.density }-density` ]:
286
331
  view.layout?.density &&
287
332
  [ 'compact', 'comfortable' ].includes(
@@ -328,12 +373,17 @@ function ViewTable< Item >( {
328
373
  ) }
329
374
  { columns.map( ( column, index ) => {
330
375
  // Explicit picks the supported styles.
331
- const { width, maxWidth, minWidth } =
376
+ const { width, maxWidth, minWidth, align } =
332
377
  view.layout?.styles?.[ column ] ?? {};
333
378
  return (
334
379
  <th
335
380
  key={ column }
336
- style={ { width, maxWidth, minWidth } }
381
+ style={ {
382
+ width,
383
+ maxWidth,
384
+ minWidth,
385
+ textAlign: align,
386
+ } }
337
387
  aria-sort={
338
388
  view.sort?.direction &&
339
389
  view.sort?.field === column
@@ -355,7 +405,17 @@ function ViewTable< Item >( {
355
405
  );
356
406
  } ) }
357
407
  { !! actions?.length && (
358
- <th className="dataviews-view-table__actions-column">
408
+ <th
409
+ className={ clsx(
410
+ 'dataviews-view-table__actions-column',
411
+ {
412
+ 'dataviews-view-table__actions-column--sticky':
413
+ true,
414
+ 'dataviews-view-table__actions-column--stuck':
415
+ ! isHorizontalScrollEnd,
416
+ }
417
+ ) }
418
+ >
359
419
  <span className="dataviews-view-table-header">
360
420
  { __( 'Actions' ) }
361
421
  </span>
@@ -387,7 +447,11 @@ function ViewTable< Item >( {
387
447
  getItemId={ getItemId }
388
448
  onChangeSelection={ onChangeSelection }
389
449
  onClickItem={ onClickItem }
450
+ renderItemLink={ renderItemLink }
390
451
  isItemClickable={ isItemClickable }
452
+ isActionsColumnSticky={
453
+ ! isHorizontalScrollEnd
454
+ }
391
455
  />
392
456
  ) ) }
393
457
  </tbody>
@@ -22,6 +22,25 @@
22
22
  text-align: right;
23
23
  }
24
24
 
25
+ &.dataviews-view-table__actions-column--sticky {
26
+ position: sticky;
27
+ right: 0;
28
+ background-color: $white;
29
+ }
30
+
31
+ &.dataviews-view-table__actions-column--stuck {
32
+ &::after {
33
+ display: block;
34
+ content: "";
35
+ position: absolute;
36
+ top: 0;
37
+ bottom: 0;
38
+ left: 0;
39
+ width: 1px;
40
+ background-color: $gray-100;
41
+ }
42
+ }
43
+
25
44
  &.dataviews-view-table__checkbox-column {
26
45
  padding-right: 0;
27
46
  width: 1%;
@@ -52,7 +71,8 @@
52
71
  border-bottom: 0;
53
72
  }
54
73
 
55
- &.is-hovered {
74
+ &.is-hovered,
75
+ &.is-hovered .dataviews-view-table__actions-column--sticky {
56
76
  background-color: #f8f8f8;
57
77
  }
58
78
 
@@ -99,6 +119,14 @@
99
119
  &:hover {
100
120
  background-color: rgba(var(--wp-admin-theme-color--rgb), 0.08);
101
121
  }
122
+
123
+ .dataviews-view-table__actions-column--sticky {
124
+ background-color: color-mix(in srgb, rgb(var(--wp-admin-theme-color--rgb)) 4%, $white);
125
+ }
126
+
127
+ &:hover .dataviews-view-table__actions-column--sticky {
128
+ background-color: color-mix(in srgb, rgb(var(--wp-admin-theme-color--rgb)) 8%, $white);
129
+ }
102
130
  }
103
131
  }
104
132
  thead {
@@ -131,6 +159,14 @@
131
159
  min-height: $grid-unit-40;
132
160
  display: flex;
133
161
  align-items: center;
162
+
163
+ &.dataviews-view-table__cell-align-end {
164
+ justify-content: flex-end;
165
+ }
166
+
167
+ &.dataviews-view-table__cell-align-center {
168
+ justify-content: center;
169
+ }
134
170
  }
135
171
 
136
172
  .components-v-stack > .dataviews-view-table__cell-content-wrapper:not(:first-child) {
@@ -0,0 +1,82 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import type { MutableRefObject } from 'react';
5
+
6
+ /**
7
+ * WordPress dependencies
8
+ */
9
+ import { useDebounce } from '@wordpress/compose';
10
+ import { useCallback, useEffect, useState } from '@wordpress/element';
11
+ import { isRTL } from '@wordpress/i18n';
12
+
13
+ const isScrolledToEnd = ( element: Element ) => {
14
+ if ( isRTL() ) {
15
+ const scrollLeft = Math.abs( element.scrollLeft );
16
+ return scrollLeft <= 1;
17
+ }
18
+
19
+ return element.scrollLeft + element.clientWidth >= element.scrollWidth - 1;
20
+ };
21
+
22
+ /**
23
+ * A hook to check if a given scroll container has reached the horizontal scroll end.
24
+ *
25
+ * The current way receives "refs" as arguments, but it lacks a mechanism to detect when a ref has changed.
26
+ * As a result, when the "ref" is updated and attached to a new div, the computation should trigger again.
27
+ * However, this isn't possible in the current setup because the hook is unaware that the ref has changed.
28
+ *
29
+ * See https://github.com/Automattic/wp-calypso/pull/103005#discussion_r2077567912.
30
+ *
31
+ * @param {Object} params The parameters for the hook.
32
+ * @param {MutableRefObject<HTMLDivElement | null>} params.scrollContainerRef The ref to the scroll container element.
33
+ * @param {boolean} [params.enabled=false] Whether the hook is enabled.
34
+ * @return {boolean} - Returns true if the scroll container is scrolled to the end or false otherwise.
35
+ */
36
+ export function useIsHorizontalScrollEnd( {
37
+ scrollContainerRef,
38
+ enabled = false,
39
+ }: {
40
+ scrollContainerRef: React.MutableRefObject< HTMLDivElement | null >;
41
+ enabled?: boolean;
42
+ } ): boolean {
43
+ const [ isHorizontalScrollEnd, setIsHorizontalScrollEnd ] =
44
+ useState( false );
45
+
46
+ const handleIsHorizontalScrollEnd = useDebounce(
47
+ useCallback( () => {
48
+ const scrollContainer = scrollContainerRef.current;
49
+ if ( scrollContainer ) {
50
+ setIsHorizontalScrollEnd( isScrolledToEnd( scrollContainer ) );
51
+ }
52
+ }, [ scrollContainerRef, setIsHorizontalScrollEnd ] ),
53
+ 200
54
+ );
55
+
56
+ useEffect( () => {
57
+ if (
58
+ typeof window === 'undefined' ||
59
+ ! enabled ||
60
+ ! scrollContainerRef.current
61
+ ) {
62
+ return () => {};
63
+ }
64
+
65
+ handleIsHorizontalScrollEnd();
66
+ scrollContainerRef.current.addEventListener(
67
+ 'scroll',
68
+ handleIsHorizontalScrollEnd
69
+ );
70
+ window.addEventListener( 'resize', handleIsHorizontalScrollEnd );
71
+
72
+ return () => {
73
+ scrollContainerRef.current?.removeEventListener(
74
+ 'scroll',
75
+ handleIsHorizontalScrollEnd
76
+ );
77
+ window.removeEventListener( 'resize', handleIsHorizontalScrollEnd );
78
+ };
79
+ }, [ scrollContainerRef, enabled ] );
80
+
81
+ return isHorizontalScrollEnd;
82
+ }
@@ -0,0 +1,93 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import type { ReactNode, ReactElement, ComponentProps } from 'react';
5
+
6
+ function getClickableItemProps< Item >( {
7
+ item,
8
+ isItemClickable,
9
+ onClickItem,
10
+ className,
11
+ }: {
12
+ item: Item;
13
+ isItemClickable: ( item: Item ) => boolean;
14
+ onClickItem?: ( item: Item ) => void;
15
+ className?: string;
16
+ } ) {
17
+ if ( ! isItemClickable( item ) || ! onClickItem ) {
18
+ return { className };
19
+ }
20
+
21
+ return {
22
+ className: className
23
+ ? `${ className } ${ className }--clickable`
24
+ : undefined,
25
+ role: 'button',
26
+ tabIndex: 0,
27
+ onClick: ( event: React.MouseEvent ) => {
28
+ // Prevents onChangeSelection from triggering.
29
+ event.stopPropagation();
30
+ onClickItem( item );
31
+ },
32
+ onKeyDown: ( event: React.KeyboardEvent ) => {
33
+ if (
34
+ event.key === 'Enter' ||
35
+ event.key === '' ||
36
+ event.key === ' '
37
+ ) {
38
+ // Prevents onChangeSelection from triggering.
39
+ event.stopPropagation();
40
+ onClickItem( item );
41
+ }
42
+ },
43
+ };
44
+ }
45
+
46
+ export function ItemClickWrapper< Item >( {
47
+ item,
48
+ isItemClickable,
49
+ onClickItem,
50
+ renderItemLink,
51
+ className,
52
+ children,
53
+ ...extraProps
54
+ }: {
55
+ item: Item;
56
+ isItemClickable: ( item: Item ) => boolean;
57
+ onClickItem?: ( item: Item ) => void;
58
+ renderItemLink?: (
59
+ props: {
60
+ item: Item;
61
+ } & ComponentProps< 'a' >
62
+ ) => ReactElement;
63
+ className?: string;
64
+ children: ReactNode;
65
+ } ) {
66
+ if ( ! isItemClickable( item ) ) {
67
+ return children;
68
+ }
69
+
70
+ // If we have a renderItemLink, use it
71
+ if ( renderItemLink ) {
72
+ return renderItemLink( {
73
+ item,
74
+ className: `${ className } ${ className }--clickable`,
75
+ ...extraProps,
76
+ children,
77
+ } );
78
+ }
79
+
80
+ // Otherwise use the classic click handler approach
81
+ const clickProps = getClickableItemProps( {
82
+ item,
83
+ isItemClickable,
84
+ onClickItem,
85
+ className,
86
+ } );
87
+
88
+ return (
89
+ <div { ...clickProps } { ...extraProps }>
90
+ { children }
91
+ </div>
92
+ );
93
+ }
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Internal dependencies
3
+ */
4
+ import type {
5
+ DataViewRenderFieldProps,
6
+ SortDirection,
7
+ ValidationContext,
8
+ FieldTypeDefinition,
9
+ } from '../types';
10
+ import {
11
+ OPERATOR_IS_ALL,
12
+ OPERATOR_IS_ANY,
13
+ OPERATOR_IS_NONE,
14
+ OPERATOR_IS_NOT_ALL,
15
+ } from '../constants';
16
+
17
+ // Sort arrays by length, then alphabetically by joined string
18
+ function sort( valueA: any, valueB: any, direction: SortDirection ) {
19
+ const arrA = Array.isArray( valueA ) ? valueA : [];
20
+ const arrB = Array.isArray( valueB ) ? valueB : [];
21
+ if ( arrA.length !== arrB.length ) {
22
+ return direction === 'asc'
23
+ ? arrA.length - arrB.length
24
+ : arrB.length - arrA.length;
25
+ }
26
+
27
+ const joinedA = arrA.join( ',' );
28
+ const joinedB = arrB.join( ',' );
29
+ return direction === 'asc'
30
+ ? joinedA.localeCompare( joinedB )
31
+ : joinedB.localeCompare( joinedA );
32
+ }
33
+
34
+ function isValid( value: any, context?: ValidationContext ) {
35
+ if ( ! Array.isArray( value ) ) {
36
+ return false;
37
+ }
38
+
39
+ // Only allow strings for now. Can be extended to other types in the future.
40
+ if ( ! value.every( ( v ) => typeof v === 'string' ) ) {
41
+ return false;
42
+ }
43
+
44
+ if ( context?.elements ) {
45
+ const validValues = context.elements.map( ( f ) => f.value );
46
+ if ( ! value.every( ( v ) => validValues.includes( v ) ) ) {
47
+ return false;
48
+ }
49
+ }
50
+ return true;
51
+ }
52
+
53
+ function render( { item, field }: DataViewRenderFieldProps< any > ) {
54
+ const value = field.getValue( { item } ) || [];
55
+ return value.join( ', ' );
56
+ }
57
+
58
+ const arrayFieldType: FieldTypeDefinition< any > = {
59
+ sort,
60
+ isValid,
61
+ Edit: null, // Not implemented yet
62
+ render,
63
+ enableSorting: true,
64
+ filterBy: {
65
+ defaultOperators: [ OPERATOR_IS_ANY, OPERATOR_IS_NONE ],
66
+ validOperators: [
67
+ OPERATOR_IS_ANY,
68
+ OPERATOR_IS_NONE,
69
+ OPERATOR_IS_ALL,
70
+ OPERATOR_IS_NOT_ALL,
71
+ ],
72
+ },
73
+ };
74
+
75
+ export default arrayFieldType;
@@ -0,0 +1,66 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { __ } from '@wordpress/i18n';
5
+
6
+ /**
7
+ * Internal dependencies
8
+ */
9
+ import type {
10
+ DataViewRenderFieldProps,
11
+ SortDirection,
12
+ FieldTypeDefinition,
13
+ } from '../types';
14
+ import { renderFromElements } from '../utils';
15
+ import { OPERATOR_IS, OPERATOR_IS_NOT } from '../constants';
16
+
17
+ function sort( a: any, b: any, direction: SortDirection ) {
18
+ const boolA = Boolean( a );
19
+ const boolB = Boolean( b );
20
+
21
+ if ( boolA === boolB ) {
22
+ return 0;
23
+ }
24
+
25
+ // In ascending order, false comes before true
26
+ if ( direction === 'asc' ) {
27
+ return boolA ? 1 : -1;
28
+ }
29
+
30
+ // In descending order, true comes before false
31
+ return boolA ? -1 : 1;
32
+ }
33
+
34
+ function isValid( value: any ) {
35
+ if ( ! [ true, false, undefined ].includes( value ) ) {
36
+ return false;
37
+ }
38
+
39
+ return true;
40
+ }
41
+
42
+ export default {
43
+ sort,
44
+ isValid,
45
+ Edit: 'boolean',
46
+ render: ( { item, field }: DataViewRenderFieldProps< any > ) => {
47
+ if ( field.elements ) {
48
+ return renderFromElements( { item, field } );
49
+ }
50
+
51
+ if ( field.getValue( { item } ) === true ) {
52
+ return __( 'True' );
53
+ }
54
+
55
+ if ( field.getValue( { item } ) === false ) {
56
+ return __( 'False' );
57
+ }
58
+
59
+ return null;
60
+ },
61
+ enableSorting: true,
62
+ filterBy: {
63
+ defaultOperators: [ OPERATOR_IS, OPERATOR_IS_NOT ],
64
+ validOperators: [ OPERATOR_IS, OPERATOR_IS_NOT ],
65
+ },
66
+ } satisfies FieldTypeDefinition< any >;
@@ -0,0 +1,56 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { dateI18n, getDate, getSettings } from '@wordpress/date';
5
+
6
+ /**
7
+ * Internal dependencies
8
+ */
9
+ import type {
10
+ DataViewRenderFieldProps,
11
+ SortDirection,
12
+ ValidationContext,
13
+ FieldTypeDefinition,
14
+ } from '../types';
15
+ import { renderFromElements } from '../utils';
16
+
17
+ const getFormattedDate = ( dateToDisplay: string | null ) =>
18
+ dateI18n( getSettings().formats.date, getDate( dateToDisplay ) );
19
+
20
+ function sort( a: any, b: any, direction: SortDirection ) {
21
+ const timeA = new Date( a ).getTime();
22
+ const timeB = new Date( b ).getTime();
23
+
24
+ return direction === 'asc' ? timeA - timeB : timeB - timeA;
25
+ }
26
+
27
+ function isValid( value: any, context?: ValidationContext ) {
28
+ if ( context?.elements ) {
29
+ const validValues = context?.elements.map( ( f ) => f.value );
30
+ if ( ! validValues.includes( value ) ) {
31
+ return false;
32
+ }
33
+ }
34
+
35
+ return true;
36
+ }
37
+
38
+ export default {
39
+ sort,
40
+ isValid,
41
+ Edit: null,
42
+ render: ( { item, field }: DataViewRenderFieldProps< any > ) => {
43
+ if ( field.elements ) {
44
+ return renderFromElements( { item, field } );
45
+ }
46
+
47
+ const value = field.getValue( { item } );
48
+ if ( ! value ) {
49
+ return '';
50
+ }
51
+
52
+ return getFormattedDate( value );
53
+ },
54
+ enableSorting: true,
55
+ filterBy: false,
56
+ } satisfies FieldTypeDefinition< any >;
@@ -1,7 +1,23 @@
1
1
  /**
2
2
  * Internal dependencies
3
3
  */
4
- import type { SortDirection, ValidationContext } from '../types';
4
+ import type {
5
+ DataViewRenderFieldProps,
6
+ SortDirection,
7
+ ValidationContext,
8
+ FieldTypeDefinition,
9
+ } from '../types';
10
+ import { renderFromElements } from '../utils';
11
+ import {
12
+ OPERATOR_ON,
13
+ OPERATOR_NOT_ON,
14
+ OPERATOR_BEFORE,
15
+ OPERATOR_AFTER,
16
+ OPERATOR_BEFORE_INC,
17
+ OPERATOR_AFTER_INC,
18
+ OPERATOR_IN_THE_PAST,
19
+ OPERATOR_OVER,
20
+ } from '../constants';
5
21
 
6
22
  function sort( a: any, b: any, direction: SortDirection ) {
7
23
  const timeA = new Date( a ).getTime();
@@ -25,4 +41,32 @@ export default {
25
41
  sort,
26
42
  isValid,
27
43
  Edit: 'datetime',
28
- };
44
+ render: ( { item, field }: DataViewRenderFieldProps< any > ) => {
45
+ return field.elements
46
+ ? renderFromElements( { item, field } )
47
+ : field.getValue( { item } );
48
+ },
49
+ enableSorting: true,
50
+ filterBy: {
51
+ defaultOperators: [
52
+ OPERATOR_ON,
53
+ OPERATOR_NOT_ON,
54
+ OPERATOR_BEFORE,
55
+ OPERATOR_AFTER,
56
+ OPERATOR_BEFORE_INC,
57
+ OPERATOR_AFTER_INC,
58
+ OPERATOR_IN_THE_PAST,
59
+ OPERATOR_OVER,
60
+ ],
61
+ validOperators: [
62
+ OPERATOR_ON,
63
+ OPERATOR_NOT_ON,
64
+ OPERATOR_BEFORE,
65
+ OPERATOR_AFTER,
66
+ OPERATOR_BEFORE_INC,
67
+ OPERATOR_AFTER_INC,
68
+ OPERATOR_IN_THE_PAST,
69
+ OPERATOR_OVER,
70
+ ],
71
+ },
72
+ } satisfies FieldTypeDefinition< any >;