@wordpress/dataviews 4.22.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 +39 -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 +315 -13
  180. package/build-style/style.css +315 -13
  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
@@ -96,3 +96,30 @@
96
96
  }
97
97
  @include link-reset();
98
98
  }
99
+
100
+ /**
101
+ * Applying a consistent 24px padding when DataViews are placed within cards.
102
+ */
103
+ .components-card__body:has(> .dataviews-wrapper) {
104
+ padding: $grid-unit-10 0 0;
105
+ overflow: hidden; // Prevent cells with white backgrounds overflowing the card
106
+
107
+ .dataviews__view-actions,
108
+ .dataviews-filters__container,
109
+ .dataviews-footer,
110
+ .dataviews-view-grid,
111
+ .dataviews-loading,
112
+ .dataviews-no-results {
113
+ padding-inline: $grid-unit-30;
114
+ }
115
+
116
+ .dataviews-view-table tr td:first-child,
117
+ .dataviews-view-table tr th:first-child {
118
+ padding-inline-start: $grid-unit-30;
119
+ }
120
+
121
+ .dataviews-view-table tr td:last-child,
122
+ .dataviews-view-table tr th:last-child {
123
+ padding-inline-end: $grid-unit-30;
124
+ }
125
+ }
@@ -1,12 +1,23 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import type { ComponentProps, ReactElement } from 'react';
5
+
1
6
  /**
2
7
  * WordPress dependencies
3
8
  */
4
- import { createContext } from '@wordpress/element';
9
+ import { createContext, createRef } from '@wordpress/element';
5
10
 
6
11
  /**
7
12
  * Internal dependencies
8
13
  */
9
- import type { View, Action, NormalizedField } from '../../types';
14
+ import type {
15
+ View,
16
+ Action,
17
+ NormalizedField,
18
+ SupportedLayouts,
19
+ NormalizedFilter,
20
+ } from '../../types';
10
21
  import type { SetSelection } from '../../private-types';
11
22
  import { LAYOUT_TABLE } from '../../constants';
12
23
 
@@ -28,8 +39,19 @@ type DataViewsContextType< Item > = {
28
39
  getItemId: ( item: Item ) => string;
29
40
  getItemLevel?: ( item: Item ) => number;
30
41
  onClickItem?: ( item: Item ) => void;
42
+ renderItemLink?: (
43
+ props: {
44
+ item: Item;
45
+ } & ComponentProps< 'a' >
46
+ ) => ReactElement;
31
47
  isItemClickable: ( item: Item ) => boolean;
32
48
  containerWidth: number;
49
+ containerRef: React.MutableRefObject< HTMLDivElement | null >;
50
+ defaultLayouts: SupportedLayouts;
51
+ filters: NormalizedFilter[];
52
+ isShowingFilter: boolean;
53
+ setIsShowingFilter: ( value: boolean ) => void;
54
+ perPageSizes?: [ number, number, number, number ];
33
55
  };
34
56
 
35
57
  const DataViewsContext = createContext< DataViewsContextType< any > >( {
@@ -47,7 +69,13 @@ const DataViewsContext = createContext< DataViewsContextType< any > >( {
47
69
  openedFilter: null,
48
70
  getItemId: ( item ) => item.id,
49
71
  isItemClickable: () => true,
72
+ renderItemLink: undefined,
50
73
  containerWidth: 0,
74
+ containerRef: createRef(),
75
+ defaultLayouts: { list: {}, grid: {}, table: {} },
76
+ filters: [],
77
+ isShowingFilter: false,
78
+ setIsShowingFilter: () => {},
51
79
  } );
52
80
 
53
81
  export default DataViewsContext;
@@ -0,0 +1,603 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import clsx from 'clsx';
5
+ import type { RefObject } from 'react';
6
+
7
+ /**
8
+ * WordPress dependencies
9
+ */
10
+ import {
11
+ Dropdown,
12
+ __experimentalVStack as VStack,
13
+ __experimentalHStack as HStack,
14
+ FlexItem,
15
+ SelectControl,
16
+ Tooltip,
17
+ Icon,
18
+ } from '@wordpress/components';
19
+ import { __, sprintf } from '@wordpress/i18n';
20
+ import { useRef, createInterpolateElement } from '@wordpress/element';
21
+ import { closeSmall } from '@wordpress/icons';
22
+
23
+ const ENTER = 'Enter';
24
+ const SPACE = ' ';
25
+
26
+ /**
27
+ * Internal dependencies
28
+ */
29
+ import SearchWidget from './search-widget';
30
+ import InputWidget from './input-widget';
31
+ import {
32
+ OPERATORS,
33
+ OPERATOR_IS,
34
+ OPERATOR_IS_NOT,
35
+ OPERATOR_IS_ANY,
36
+ OPERATOR_IS_NONE,
37
+ OPERATOR_IS_ALL,
38
+ OPERATOR_IS_NOT_ALL,
39
+ OPERATOR_LESS_THAN,
40
+ OPERATOR_GREATER_THAN,
41
+ OPERATOR_LESS_THAN_OR_EQUAL,
42
+ OPERATOR_GREATER_THAN_OR_EQUAL,
43
+ OPERATOR_CONTAINS,
44
+ OPERATOR_NOT_CONTAINS,
45
+ OPERATOR_STARTS_WITH,
46
+ OPERATOR_BEFORE,
47
+ OPERATOR_AFTER,
48
+ OPERATOR_BEFORE_INC,
49
+ OPERATOR_AFTER_INC,
50
+ OPERATOR_BETWEEN,
51
+ OPERATOR_ON,
52
+ OPERATOR_NOT_ON,
53
+ OPERATOR_IN_THE_PAST,
54
+ OPERATOR_OVER,
55
+ } from '../../constants';
56
+ import type {
57
+ Filter,
58
+ NormalizedFilter,
59
+ Operator,
60
+ Option,
61
+ View,
62
+ NormalizedField,
63
+ } from '../../types';
64
+
65
+ interface FilterTextProps {
66
+ activeElements: Option[];
67
+ filterInView?: Filter;
68
+ filter: NormalizedFilter;
69
+ }
70
+
71
+ interface OperatorSelectorProps {
72
+ filter: NormalizedFilter;
73
+ view: View;
74
+ onChangeView: ( view: View ) => void;
75
+ }
76
+
77
+ interface FilterProps extends OperatorSelectorProps {
78
+ addFilterRef: RefObject< HTMLButtonElement >;
79
+ openedFilter: string | null;
80
+ fields: NormalizedField< any >[];
81
+ }
82
+
83
+ const FilterText = ( {
84
+ activeElements,
85
+ filterInView,
86
+ filter,
87
+ }: FilterTextProps ) => {
88
+ if ( activeElements === undefined || activeElements.length === 0 ) {
89
+ return filter.name;
90
+ }
91
+
92
+ const filterTextWrappers = {
93
+ Name: <span className="dataviews-filters__summary-filter-text-name" />,
94
+ Value: (
95
+ <span className="dataviews-filters__summary-filter-text-value" />
96
+ ),
97
+ };
98
+
99
+ if ( filterInView?.operator === OPERATOR_IS_ANY ) {
100
+ return createInterpolateElement(
101
+ sprintf(
102
+ /* translators: 1: Filter name. 2: Filter value. e.g.: "Author is any: Admin, Editor". */
103
+ __( '<Name>%1$s is any: </Name><Value>%2$s</Value>' ),
104
+ filter.name,
105
+ activeElements.map( ( element ) => element.label ).join( ', ' )
106
+ ),
107
+ filterTextWrappers
108
+ );
109
+ }
110
+
111
+ if ( filterInView?.operator === OPERATOR_IS_NONE ) {
112
+ return createInterpolateElement(
113
+ sprintf(
114
+ /* translators: 1: Filter name. 2: Filter value. e.g.: "Author is none: Admin, Editor". */
115
+ __( '<Name>%1$s is none: </Name><Value>%2$s</Value>' ),
116
+ filter.name,
117
+ activeElements.map( ( element ) => element.label ).join( ', ' )
118
+ ),
119
+ filterTextWrappers
120
+ );
121
+ }
122
+
123
+ if ( filterInView?.operator === OPERATOR_IS_ALL ) {
124
+ return createInterpolateElement(
125
+ sprintf(
126
+ /* translators: 1: Filter name. 2: Filter value. e.g.: "Author is all: Admin, Editor". */
127
+ __( '<Name>%1$s is all: </Name><Value>%2$s</Value>' ),
128
+ filter.name,
129
+ activeElements.map( ( element ) => element.label ).join( ', ' )
130
+ ),
131
+ filterTextWrappers
132
+ );
133
+ }
134
+
135
+ if ( filterInView?.operator === OPERATOR_IS_NOT_ALL ) {
136
+ return createInterpolateElement(
137
+ sprintf(
138
+ /* translators: 1: Filter name. 2: Filter value. e.g.: "Author is not all: Admin, Editor". */
139
+ __( '<Name>%1$s is not all: </Name><Value>%2$s</Value>' ),
140
+ filter.name,
141
+ activeElements.map( ( element ) => element.label ).join( ', ' )
142
+ ),
143
+ filterTextWrappers
144
+ );
145
+ }
146
+
147
+ if ( filterInView?.operator === OPERATOR_IS ) {
148
+ return createInterpolateElement(
149
+ sprintf(
150
+ /* translators: 1: Filter name. 2: Filter value. e.g.: "Author is: Admin". */
151
+ __( '<Name>%1$s is: </Name><Value>%2$s</Value>' ),
152
+ filter.name,
153
+ activeElements[ 0 ].label
154
+ ),
155
+ filterTextWrappers
156
+ );
157
+ }
158
+
159
+ if ( filterInView?.operator === OPERATOR_IS_NOT ) {
160
+ return createInterpolateElement(
161
+ sprintf(
162
+ /* translators: 1: Filter name. 2: Filter value. e.g.: "Author is not: Admin". */
163
+ __( '<Name>%1$s is not: </Name><Value>%2$s</Value>' ),
164
+ filter.name,
165
+ activeElements[ 0 ].label
166
+ ),
167
+ filterTextWrappers
168
+ );
169
+ }
170
+
171
+ if ( filterInView?.operator === OPERATOR_LESS_THAN ) {
172
+ return createInterpolateElement(
173
+ sprintf(
174
+ /* translators: 1: Filter name. 2: Filter value. e.g.: "Price is less than: 10". */
175
+ __( '<Name>%1$s is less than: </Name><Value>%2$s</Value>' ),
176
+ filter.name,
177
+ activeElements[ 0 ].label
178
+ ),
179
+ filterTextWrappers
180
+ );
181
+ }
182
+
183
+ if ( filterInView?.operator === OPERATOR_GREATER_THAN ) {
184
+ return createInterpolateElement(
185
+ sprintf(
186
+ /* translators: 1: Filter name. 2: Filter value. e.g.: "Price is greater than: 10". */
187
+ __( '<Name>%1$s is greater than: </Name><Value>%2$s</Value>' ),
188
+ filter.name,
189
+ activeElements[ 0 ].label
190
+ ),
191
+ filterTextWrappers
192
+ );
193
+ }
194
+
195
+ if ( filterInView?.operator === OPERATOR_LESS_THAN_OR_EQUAL ) {
196
+ return createInterpolateElement(
197
+ sprintf(
198
+ /* translators: 1: Filter name. 2: Filter value. e.g.: "Price is less than or equal to: 10". */
199
+ __(
200
+ '<Name>%1$s is less than or equal to: </Name><Value>%2$s</Value>'
201
+ ),
202
+ filter.name,
203
+ activeElements[ 0 ].label
204
+ ),
205
+ filterTextWrappers
206
+ );
207
+ }
208
+
209
+ if ( filterInView?.operator === OPERATOR_GREATER_THAN_OR_EQUAL ) {
210
+ return createInterpolateElement(
211
+ sprintf(
212
+ /* translators: 1: Filter name. 2: Filter value. e.g.: "Price is greater than or equal to: 10". */
213
+ __(
214
+ '<Name>%1$s is greater than or equal to: </Name><Value>%2$s</Value>'
215
+ ),
216
+ filter.name,
217
+ activeElements[ 0 ].label
218
+ ),
219
+ filterTextWrappers
220
+ );
221
+ }
222
+
223
+ if ( filterInView?.operator === OPERATOR_CONTAINS ) {
224
+ return createInterpolateElement(
225
+ sprintf(
226
+ /* translators: 1: Filter name. 2: Filter value. e.g.: "Title contains: Mars". */
227
+ __( '<Name>%1$s contains: </Name><Value>%2$s</Value>' ),
228
+ filter.name,
229
+ activeElements[ 0 ].label
230
+ ),
231
+ filterTextWrappers
232
+ );
233
+ }
234
+
235
+ if ( filterInView?.operator === OPERATOR_NOT_CONTAINS ) {
236
+ return createInterpolateElement(
237
+ sprintf(
238
+ /* translators: 1: Filter name. 2: Filter value. e.g.: "Description doesn't contain: photo". */
239
+ __( "<Name>%1$s doesn't contain: </Name><Value>%2$s</Value>" ),
240
+ filter.name,
241
+ activeElements[ 0 ].label
242
+ ),
243
+ filterTextWrappers
244
+ );
245
+ }
246
+
247
+ if ( filterInView?.operator === OPERATOR_STARTS_WITH ) {
248
+ return createInterpolateElement(
249
+ sprintf(
250
+ /* translators: 1: Filter name. 2: Filter value. e.g.: "Title starts with: Mar". */
251
+ __( '<Name>%1$s starts with: </Name><Value>%2$s</Value>' ),
252
+ filter.name,
253
+ activeElements[ 0 ].label
254
+ ),
255
+ filterTextWrappers
256
+ );
257
+ }
258
+
259
+ if ( filterInView?.operator === OPERATOR_BEFORE ) {
260
+ return createInterpolateElement(
261
+ sprintf(
262
+ /* translators: 1: Filter name. 2: Filter value. e.g.: "Date is before: 2024-01-01". */
263
+ __( '<Name>%1$s is before: </Name><Value>%2$s</Value>' ),
264
+ filter.name,
265
+ activeElements[ 0 ].label
266
+ ),
267
+ filterTextWrappers
268
+ );
269
+ }
270
+
271
+ if ( filterInView?.operator === OPERATOR_AFTER ) {
272
+ return createInterpolateElement(
273
+ sprintf(
274
+ /* translators: 1: Filter name. 2: Filter value. e.g.: "Date is after: 2024-01-01". */
275
+ __( '<Name>%1$s is after: </Name><Value>%2$s</Value>' ),
276
+ filter.name,
277
+ activeElements[ 0 ].label
278
+ ),
279
+ filterTextWrappers
280
+ );
281
+ }
282
+
283
+ if ( filterInView?.operator === OPERATOR_BEFORE_INC ) {
284
+ return createInterpolateElement(
285
+ sprintf(
286
+ /* translators: 1: Filter name. 2: Filter value. e.g.: "Date is on or before: 2024-01-01". */
287
+ __( '<Name>%1$s is on or before: </Name><Value>%2$s</Value>' ),
288
+ filter.name,
289
+ activeElements[ 0 ].label
290
+ ),
291
+ filterTextWrappers
292
+ );
293
+ }
294
+
295
+ if ( filterInView?.operator === OPERATOR_AFTER_INC ) {
296
+ return createInterpolateElement(
297
+ sprintf(
298
+ /* translators: 1: Filter name. 2: Filter value. e.g.: "Date is on or after: 2024-01-01". */
299
+ __( '<Name>%1$s is on or after: </Name><Value>%2$s</Value>' ),
300
+ filter.name,
301
+ activeElements[ 0 ].label
302
+ ),
303
+ filterTextWrappers
304
+ );
305
+ }
306
+
307
+ if ( filterInView?.operator === OPERATOR_BETWEEN ) {
308
+ const { label } = activeElements[ 0 ];
309
+
310
+ return createInterpolateElement(
311
+ sprintf(
312
+ /* translators: 1: Filter name. 2: Min value. 3: Max value. e.g.: "Item count between (inc): 10-180". */
313
+ __(
314
+ '<Name>%1$s between (inc): </Name><Value>%2$s-%3$s</Value>'
315
+ ),
316
+ filter.name,
317
+ label[ 0 ],
318
+ label[ 1 ]
319
+ ),
320
+ filterTextWrappers
321
+ );
322
+ }
323
+
324
+ if ( filterInView?.operator === OPERATOR_ON ) {
325
+ return createInterpolateElement(
326
+ sprintf(
327
+ /* translators: 1: Filter name. 2: Filter value. e.g.: "Date is: 2024-01-01". */
328
+ __( '<Name>%1$s is: </Name><Value>%2$s</Value>' ),
329
+ filter.name,
330
+ activeElements[ 0 ].label
331
+ ),
332
+ filterTextWrappers
333
+ );
334
+ }
335
+
336
+ if ( filterInView?.operator === OPERATOR_NOT_ON ) {
337
+ return createInterpolateElement(
338
+ sprintf(
339
+ /* translators: 1: Filter name. 2: Filter value. e.g.: "Date is not: 2024-01-01". */
340
+ __( '<Name>%1$s is not: </Name><Value>%2$s</Value>' ),
341
+ filter.name,
342
+ activeElements[ 0 ].label
343
+ ),
344
+ filterTextWrappers
345
+ );
346
+ }
347
+
348
+ if ( filterInView?.operator === OPERATOR_IN_THE_PAST ) {
349
+ return createInterpolateElement(
350
+ sprintf(
351
+ /* translators: 1: Filter name. 2: Filter value. e.g.: "Date is in the past: 1 days". */
352
+ __( '<Name>%1$s is in the past: </Name><Value>%2$s</Value>' ),
353
+ filter.name,
354
+ `${ activeElements[ 0 ].value.value } ${ activeElements[ 0 ].value.unit }`
355
+ ),
356
+ filterTextWrappers
357
+ );
358
+ }
359
+
360
+ if ( filterInView?.operator === OPERATOR_OVER ) {
361
+ return createInterpolateElement(
362
+ sprintf(
363
+ /* translators: 1: Filter name. 2: Filter value. e.g.: "Date is over: 1 days ago". */
364
+ __( '<Name>%1$s is over: </Name><Value>%2$s</Value> ago' ),
365
+ filter.name,
366
+ `${ activeElements[ 0 ].value.value } ${ activeElements[ 0 ].value.unit }`
367
+ ),
368
+ filterTextWrappers
369
+ );
370
+ }
371
+ return sprintf(
372
+ /* translators: 1: Filter name e.g.: "Unknown status for Author". */
373
+ __( 'Unknown status for %1$s' ),
374
+ filter.name
375
+ );
376
+ };
377
+
378
+ function OperatorSelector( {
379
+ filter,
380
+ view,
381
+ onChangeView,
382
+ }: OperatorSelectorProps ) {
383
+ const operatorOptions = filter.operators?.map( ( operator ) => ( {
384
+ value: operator,
385
+ label: OPERATORS[ operator ]?.label,
386
+ } ) );
387
+ const currentFilter = view.filters?.find(
388
+ ( _filter ) => _filter.field === filter.field
389
+ );
390
+ const value = currentFilter?.operator || filter.operators[ 0 ];
391
+ return (
392
+ operatorOptions.length > 1 && (
393
+ <HStack
394
+ spacing={ 2 }
395
+ justify="flex-start"
396
+ className="dataviews-filters__summary-operators-container"
397
+ >
398
+ <FlexItem className="dataviews-filters__summary-operators-filter-name">
399
+ { filter.name }
400
+ </FlexItem>
401
+
402
+ <SelectControl
403
+ className="dataviews-filters__summary-operators-filter-select"
404
+ label={ __( 'Conditions' ) }
405
+ value={ value }
406
+ options={ operatorOptions }
407
+ onChange={ ( newValue ) => {
408
+ const operator = newValue as Operator;
409
+ const currentOperator = currentFilter?.operator;
410
+ const newFilters = currentFilter
411
+ ? [
412
+ ...( view.filters ?? [] ).map(
413
+ ( _filter ) => {
414
+ if (
415
+ _filter.field === filter.field
416
+ ) {
417
+ // Reset the value only when switching between operators that have different value types.
418
+ const OPERATORS_SHOULD_RESET_VALUE =
419
+ [
420
+ OPERATOR_BETWEEN,
421
+ OPERATOR_IN_THE_PAST,
422
+ OPERATOR_OVER,
423
+ ];
424
+ const shouldResetValue =
425
+ currentOperator &&
426
+ ( OPERATORS_SHOULD_RESET_VALUE.includes(
427
+ currentOperator
428
+ ) ||
429
+ OPERATORS_SHOULD_RESET_VALUE.includes(
430
+ operator
431
+ ) );
432
+
433
+ return {
434
+ ..._filter,
435
+ value: shouldResetValue
436
+ ? undefined
437
+ : _filter.value,
438
+ operator,
439
+ };
440
+ }
441
+ return _filter;
442
+ }
443
+ ),
444
+ ]
445
+ : [
446
+ ...( view.filters ?? [] ),
447
+ {
448
+ field: filter.field,
449
+ operator,
450
+ value: undefined,
451
+ },
452
+ ];
453
+ onChangeView( {
454
+ ...view,
455
+ page: 1,
456
+ filters: newFilters,
457
+ } );
458
+ } }
459
+ size="small"
460
+ variant="minimal"
461
+ __nextHasNoMarginBottom
462
+ hideLabelFromVision
463
+ />
464
+ </HStack>
465
+ )
466
+ );
467
+ }
468
+
469
+ export default function Filter( {
470
+ addFilterRef,
471
+ openedFilter,
472
+ fields,
473
+ ...commonProps
474
+ }: FilterProps ) {
475
+ const toggleRef = useRef< HTMLDivElement >( null );
476
+ const { filter, view, onChangeView } = commonProps;
477
+ const filterInView = view.filters?.find(
478
+ ( f ) => f.field === filter.field
479
+ );
480
+
481
+ let activeElements: Option[] = [];
482
+
483
+ if ( filter.elements.length > 0 ) {
484
+ activeElements = filter.elements.filter( ( element ) => {
485
+ if ( filter.singleSelection ) {
486
+ return element.value === filterInView?.value;
487
+ }
488
+ return filterInView?.value?.includes( element.value );
489
+ } );
490
+ } else if ( filterInView?.value !== undefined ) {
491
+ activeElements = [
492
+ {
493
+ value: filterInView.value,
494
+ label: filterInView.value,
495
+ },
496
+ ];
497
+ }
498
+
499
+ const isPrimary = filter.isPrimary;
500
+ const hasValues = filterInView?.value !== undefined;
501
+ const canResetOrRemove = ! isPrimary || hasValues;
502
+ return (
503
+ <Dropdown
504
+ defaultOpen={ openedFilter === filter.field }
505
+ contentClassName="dataviews-filters__summary-popover"
506
+ popoverProps={ { placement: 'bottom-start', role: 'dialog' } }
507
+ onClose={ () => {
508
+ toggleRef.current?.focus();
509
+ } }
510
+ renderToggle={ ( { isOpen, onToggle } ) => (
511
+ <div className="dataviews-filters__summary-chip-container">
512
+ <Tooltip
513
+ text={ sprintf(
514
+ /* translators: 1: Filter name. */
515
+ __( 'Filter by: %1$s' ),
516
+ filter.name.toLowerCase()
517
+ ) }
518
+ placement="top"
519
+ >
520
+ <div
521
+ className={ clsx(
522
+ 'dataviews-filters__summary-chip',
523
+ {
524
+ 'has-reset': canResetOrRemove,
525
+ 'has-values': hasValues,
526
+ }
527
+ ) }
528
+ role="button"
529
+ tabIndex={ 0 }
530
+ onClick={ onToggle }
531
+ onKeyDown={ ( event ) => {
532
+ if ( [ ENTER, SPACE ].includes( event.key ) ) {
533
+ onToggle();
534
+ event.preventDefault();
535
+ }
536
+ } }
537
+ aria-pressed={ isOpen }
538
+ aria-expanded={ isOpen }
539
+ ref={ toggleRef }
540
+ >
541
+ <FilterText
542
+ activeElements={ activeElements }
543
+ filterInView={ filterInView }
544
+ filter={ filter }
545
+ />
546
+ </div>
547
+ </Tooltip>
548
+ { canResetOrRemove && (
549
+ <Tooltip
550
+ text={ isPrimary ? __( 'Reset' ) : __( 'Remove' ) }
551
+ placement="top"
552
+ >
553
+ <button
554
+ className={ clsx(
555
+ 'dataviews-filters__summary-chip-remove',
556
+ { 'has-values': hasValues }
557
+ ) }
558
+ onClick={ () => {
559
+ onChangeView( {
560
+ ...view,
561
+ page: 1,
562
+ filters: view.filters?.filter(
563
+ ( _filter ) =>
564
+ _filter.field !== filter.field
565
+ ),
566
+ } );
567
+ // If the filter is not primary and can be removed, it will be added
568
+ // back to the available filters from `Add filter` component.
569
+ if ( ! isPrimary ) {
570
+ addFilterRef.current?.focus();
571
+ } else {
572
+ // If is primary, focus the toggle button.
573
+ toggleRef.current?.focus();
574
+ }
575
+ } }
576
+ >
577
+ <Icon icon={ closeSmall } />
578
+ </button>
579
+ </Tooltip>
580
+ ) }
581
+ </div>
582
+ ) }
583
+ renderContent={ () => {
584
+ return (
585
+ <VStack spacing={ 0 } justify="flex-start">
586
+ <OperatorSelector { ...commonProps } />
587
+ { commonProps.filter.elements.length > 0 ? (
588
+ <SearchWidget
589
+ { ...commonProps }
590
+ filter={ {
591
+ ...commonProps.filter,
592
+ elements: commonProps.filter.elements,
593
+ } }
594
+ />
595
+ ) : (
596
+ <InputWidget { ...commonProps } fields={ fields } />
597
+ ) }
598
+ </VStack>
599
+ );
600
+ } }
601
+ />
602
+ );
603
+ }