@wordpress/dataviews 4.22.0 → 5.0.1-next.719a03cbe.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 (335) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/README.md +146 -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 +31 -25
  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/datetime.js +19 -1
  71. package/build/field-types/datetime.js.map +1 -1
  72. package/build/field-types/email.js +60 -0
  73. package/build/field-types/email.js.map +1 -0
  74. package/build/field-types/index.js +38 -1
  75. package/build/field-types/index.js.map +1 -1
  76. package/build/field-types/integer.js +23 -1
  77. package/build/field-types/integer.js.map +1 -1
  78. package/build/field-types/media.js +31 -0
  79. package/build/field-types/media.js.map +1 -0
  80. package/build/field-types/text.js +23 -1
  81. package/build/field-types/text.js.map +1 -1
  82. package/build/filter-and-sort-data-view.js +152 -1
  83. package/build/filter-and-sort-data-view.js.map +1 -1
  84. package/build/normalize-fields.js +72 -11
  85. package/build/normalize-fields.js.map +1 -1
  86. package/build/types.js.map +1 -1
  87. package/build/utils.js +11 -19
  88. package/build/utils.js.map +1 -1
  89. package/build-module/components/dataviews/index.js +74 -40
  90. package/build-module/components/dataviews/index.js.map +1 -1
  91. package/build-module/components/dataviews-context/index.js +16 -2
  92. package/build-module/components/dataviews-context/index.js.map +1 -1
  93. package/build-module/components/dataviews-filters/filter.js +309 -0
  94. package/build-module/components/dataviews-filters/filter.js.map +1 -0
  95. package/build-module/components/dataviews-filters/index.js +22 -21
  96. package/build-module/components/dataviews-filters/index.js.map +1 -1
  97. package/build-module/components/dataviews-filters/input-widget.js +69 -0
  98. package/build-module/components/dataviews-filters/input-widget.js.map +1 -0
  99. package/build-module/components/dataviews-filters/search-widget.js +31 -37
  100. package/build-module/components/dataviews-filters/search-widget.js.map +1 -1
  101. package/build-module/components/dataviews-filters/utils.js +18 -0
  102. package/build-module/components/dataviews-filters/utils.js.map +1 -0
  103. package/build-module/components/dataviews-item-actions/index.js +1 -1
  104. package/build-module/components/dataviews-item-actions/index.js.map +1 -1
  105. package/build-module/components/dataviews-layout/index.js +7 -2
  106. package/build-module/components/dataviews-layout/index.js.map +1 -1
  107. package/build-module/components/dataviews-pagination/index.js +4 -4
  108. package/build-module/components/dataviews-pagination/index.js.map +1 -1
  109. package/build-module/components/dataviews-selection-checkbox/index.js.map +1 -1
  110. package/build-module/components/dataviews-view-config/index.js +9 -20
  111. package/build-module/components/dataviews-view-config/index.js.map +1 -1
  112. package/build-module/constants.js +82 -1
  113. package/build-module/constants.js.map +1 -1
  114. package/build-module/dataform-controls/boolean.js +35 -0
  115. package/build-module/dataform-controls/boolean.js.map +1 -0
  116. package/build-module/dataform-controls/checkbox.js +37 -0
  117. package/build-module/dataform-controls/checkbox.js.map +1 -0
  118. package/build-module/dataform-controls/datetime.js +98 -3
  119. package/build-module/dataform-controls/datetime.js.map +1 -1
  120. package/build-module/dataform-controls/email.js +41 -0
  121. package/build-module/dataform-controls/email.js.map +1 -0
  122. package/build-module/dataform-controls/index.js +9 -1
  123. package/build-module/dataform-controls/index.js.map +1 -1
  124. package/build-module/dataform-controls/integer.js +51 -3
  125. package/build-module/dataform-controls/integer.js.map +1 -1
  126. package/build-module/dataform-controls/select.js +1 -0
  127. package/build-module/dataform-controls/select.js.map +1 -1
  128. package/build-module/dataform-controls/text.js +3 -1
  129. package/build-module/dataform-controls/text.js.map +1 -1
  130. package/build-module/dataform-controls/toggle-group.js +45 -0
  131. package/build-module/dataform-controls/toggle-group.js.map +1 -0
  132. package/build-module/dataforms-layouts/data-form-layout.js +1 -1
  133. package/build-module/dataforms-layouts/data-form-layout.js.map +1 -1
  134. package/build-module/dataforms-layouts/panel/index.js +14 -5
  135. package/build-module/dataforms-layouts/panel/index.js.map +1 -1
  136. package/build-module/dataforms-layouts/regular/index.js +23 -4
  137. package/build-module/dataforms-layouts/regular/index.js.map +1 -1
  138. package/build-module/dataviews-layouts/grid/index.js +31 -26
  139. package/build-module/dataviews-layouts/grid/index.js.map +1 -1
  140. package/build-module/dataviews-layouts/list/index.js +11 -6
  141. package/build-module/dataviews-layouts/list/index.js.map +1 -1
  142. package/build-module/dataviews-layouts/table/column-header-menu.js +9 -7
  143. package/build-module/dataviews-layouts/table/column-header-menu.js.map +1 -1
  144. package/build-module/dataviews-layouts/table/column-primary.js +18 -12
  145. package/build-module/dataviews-layouts/table/column-primary.js.map +1 -1
  146. package/build-module/dataviews-layouts/table/index.js +47 -16
  147. package/build-module/dataviews-layouts/table/index.js.map +1 -1
  148. package/build-module/dataviews-layouts/table/use-is-horizontal-scroll-end.js +58 -0
  149. package/build-module/dataviews-layouts/table/use-is-horizontal-scroll-end.js.map +1 -0
  150. package/build-module/dataviews-layouts/utils/item-click-wrapper.js +71 -0
  151. package/build-module/dataviews-layouts/utils/item-click-wrapper.js.map +1 -0
  152. package/build-module/field-types/array.js +57 -0
  153. package/build-module/field-types/array.js.map +1 -0
  154. package/build-module/field-types/boolean.js +65 -0
  155. package/build-module/field-types/boolean.js.map +1 -0
  156. package/build-module/field-types/datetime.js +19 -1
  157. package/build-module/field-types/datetime.js.map +1 -1
  158. package/build-module/field-types/email.js +54 -0
  159. package/build-module/field-types/email.js.map +1 -0
  160. package/build-module/field-types/index.js +38 -1
  161. package/build-module/field-types/index.js.map +1 -1
  162. package/build-module/field-types/integer.js +23 -1
  163. package/build-module/field-types/integer.js.map +1 -1
  164. package/build-module/field-types/media.js +25 -0
  165. package/build-module/field-types/media.js.map +1 -0
  166. package/build-module/field-types/text.js +23 -1
  167. package/build-module/field-types/text.js.map +1 -1
  168. package/build-module/filter-and-sort-data-view.js +153 -2
  169. package/build-module/filter-and-sort-data-view.js.map +1 -1
  170. package/build-module/normalize-fields.js +72 -11
  171. package/build-module/normalize-fields.js.map +1 -1
  172. package/build-module/types.js.map +1 -1
  173. package/build-module/utils.js +10 -17
  174. package/build-module/utils.js.map +1 -1
  175. package/build-style/style-rtl.css +307 -13
  176. package/build-style/style.css +307 -13
  177. package/build-types/components/dataform/stories/index.story.d.ts.map +1 -1
  178. package/build-types/components/dataviews/index.d.ts +24 -3
  179. package/build-types/components/dataviews/index.d.ts.map +1 -1
  180. package/build-types/components/dataviews/stories/fixtures.d.ts +9 -1
  181. package/build-types/components/dataviews/stories/fixtures.d.ts.map +1 -1
  182. package/build-types/components/dataviews/stories/index.story.d.ts +22 -4
  183. package/build-types/components/dataviews/stories/index.story.d.ts.map +1 -1
  184. package/build-types/components/dataviews-context/index.d.ts +14 -1
  185. package/build-types/components/dataviews-context/index.d.ts.map +1 -1
  186. package/build-types/components/dataviews-filters/filter.d.ts +15 -0
  187. package/build-types/components/dataviews-filters/filter.d.ts.map +1 -0
  188. package/build-types/components/dataviews-filters/index.d.ts +3 -8
  189. package/build-types/components/dataviews-filters/index.d.ts.map +1 -1
  190. package/build-types/components/dataviews-filters/input-widget.d.ts +13 -0
  191. package/build-types/components/dataviews-filters/input-widget.d.ts.map +1 -0
  192. package/build-types/components/dataviews-filters/search-widget.d.ts +4 -5
  193. package/build-types/components/dataviews-filters/search-widget.d.ts.map +1 -1
  194. package/build-types/components/dataviews-filters/utils.d.ts +6 -0
  195. package/build-types/components/dataviews-filters/utils.d.ts.map +1 -0
  196. package/build-types/components/dataviews-layout/index.d.ts +5 -1
  197. package/build-types/components/dataviews-layout/index.d.ts.map +1 -1
  198. package/build-types/components/dataviews-pagination/index.d.ts +1 -1
  199. package/build-types/components/dataviews-pagination/index.d.ts.map +1 -1
  200. package/build-types/components/dataviews-selection-checkbox/index.d.ts +2 -2
  201. package/build-types/components/dataviews-selection-checkbox/index.d.ts.map +1 -1
  202. package/build-types/components/dataviews-view-config/index.d.ts +3 -4
  203. package/build-types/components/dataviews-view-config/index.d.ts.map +1 -1
  204. package/build-types/components/stories/index.story.d.ts +59 -0
  205. package/build-types/components/stories/index.story.d.ts.map +1 -0
  206. package/build-types/constants.d.ts +20 -3
  207. package/build-types/constants.d.ts.map +1 -1
  208. package/build-types/dataform-controls/boolean.d.ts +6 -0
  209. package/build-types/dataform-controls/boolean.d.ts.map +1 -0
  210. package/build-types/dataform-controls/checkbox.d.ts +6 -0
  211. package/build-types/dataform-controls/checkbox.d.ts.map +1 -0
  212. package/build-types/dataform-controls/datetime.d.ts +1 -1
  213. package/build-types/dataform-controls/datetime.d.ts.map +1 -1
  214. package/build-types/dataform-controls/email.d.ts +6 -0
  215. package/build-types/dataform-controls/email.d.ts.map +1 -0
  216. package/build-types/dataform-controls/index.d.ts +1 -1
  217. package/build-types/dataform-controls/index.d.ts.map +1 -1
  218. package/build-types/dataform-controls/integer.d.ts +1 -4
  219. package/build-types/dataform-controls/integer.d.ts.map +1 -1
  220. package/build-types/dataform-controls/select.d.ts.map +1 -1
  221. package/build-types/dataform-controls/text.d.ts.map +1 -1
  222. package/build-types/dataform-controls/toggle-group.d.ts +6 -0
  223. package/build-types/dataform-controls/toggle-group.d.ts.map +1 -0
  224. package/build-types/dataforms-layouts/panel/index.d.ts.map +1 -1
  225. package/build-types/dataforms-layouts/regular/index.d.ts.map +1 -1
  226. package/build-types/dataviews-layouts/grid/index.d.ts +2 -1
  227. package/build-types/dataviews-layouts/grid/index.d.ts.map +1 -1
  228. package/build-types/dataviews-layouts/index.d.ts +3 -3
  229. package/build-types/dataviews-layouts/list/index.d.ts.map +1 -1
  230. package/build-types/dataviews-layouts/table/column-header-menu.d.ts.map +1 -1
  231. package/build-types/dataviews-layouts/table/column-primary.d.ts +8 -1
  232. package/build-types/dataviews-layouts/table/column-primary.d.ts.map +1 -1
  233. package/build-types/dataviews-layouts/table/index.d.ts +1 -1
  234. package/build-types/dataviews-layouts/table/index.d.ts.map +1 -1
  235. package/build-types/dataviews-layouts/table/use-is-horizontal-scroll-end.d.ts +19 -0
  236. package/build-types/dataviews-layouts/table/use-is-horizontal-scroll-end.d.ts.map +1 -0
  237. package/build-types/dataviews-layouts/utils/item-click-wrapper.d.ts +15 -0
  238. package/build-types/dataviews-layouts/utils/item-click-wrapper.d.ts.map +1 -0
  239. package/build-types/field-types/array.d.ts +7 -0
  240. package/build-types/field-types/array.d.ts.map +1 -0
  241. package/build-types/field-types/boolean.d.ts +19 -0
  242. package/build-types/field-types/boolean.d.ts.map +1 -0
  243. package/build-types/field-types/datetime.d.ts +7 -1
  244. package/build-types/field-types/datetime.d.ts.map +1 -1
  245. package/build-types/field-types/email.d.ts +19 -0
  246. package/build-types/field-types/email.d.ts.map +1 -0
  247. package/build-types/field-types/index.d.ts +2 -10
  248. package/build-types/field-types/index.d.ts.map +1 -1
  249. package/build-types/field-types/integer.d.ts +7 -1
  250. package/build-types/field-types/integer.d.ts.map +1 -1
  251. package/build-types/field-types/media.d.ts +16 -0
  252. package/build-types/field-types/media.d.ts.map +1 -0
  253. package/build-types/field-types/text.d.ts +7 -1
  254. package/build-types/field-types/text.d.ts.map +1 -1
  255. package/build-types/filter-and-sort-data-view.d.ts.map +1 -1
  256. package/build-types/normalize-fields.d.ts.map +1 -1
  257. package/build-types/types.d.ts +70 -8
  258. package/build-types/types.d.ts.map +1 -1
  259. package/build-types/utils.d.ts +5 -2
  260. package/build-types/utils.d.ts.map +1 -1
  261. package/build-wp/index.js +2545 -994
  262. package/package.json +18 -12
  263. package/src/components/dataform/stories/index.story.tsx +41 -20
  264. package/src/components/dataviews/index.tsx +108 -43
  265. package/src/components/dataviews/stories/fixtures.tsx +58 -13
  266. package/src/components/dataviews/stories/index.story.tsx +228 -7
  267. package/src/components/dataviews/stories/style.css +24 -3
  268. package/src/components/dataviews/style.scss +27 -0
  269. package/src/components/dataviews-context/index.ts +30 -2
  270. package/src/components/dataviews-filters/filter.tsx +603 -0
  271. package/src/components/dataviews-filters/index.tsx +23 -29
  272. package/src/components/dataviews-filters/input-widget.tsx +91 -0
  273. package/src/components/dataviews-filters/search-widget.tsx +51 -48
  274. package/src/components/dataviews-filters/style.scss +117 -14
  275. package/src/components/dataviews-filters/utils.ts +25 -0
  276. package/src/components/dataviews-item-actions/index.tsx +1 -1
  277. package/src/components/dataviews-layout/index.tsx +8 -1
  278. package/src/components/dataviews-pagination/index.tsx +4 -4
  279. package/src/components/dataviews-selection-checkbox/index.tsx +2 -2
  280. package/src/components/dataviews-view-config/index.tsx +10 -18
  281. package/src/components/stories/index.story.tsx +351 -0
  282. package/src/constants.ts +116 -1
  283. package/src/dataform-controls/boolean.tsx +30 -0
  284. package/src/dataform-controls/checkbox.tsx +31 -0
  285. package/src/dataform-controls/datetime.tsx +106 -2
  286. package/src/dataform-controls/email.tsx +42 -0
  287. package/src/dataform-controls/index.tsx +8 -0
  288. package/src/dataform-controls/integer.tsx +75 -1
  289. package/src/dataform-controls/select.tsx +1 -0
  290. package/src/dataform-controls/style.scss +5 -0
  291. package/src/dataform-controls/text.tsx +2 -1
  292. package/src/dataform-controls/toggle-group.tsx +59 -0
  293. package/src/dataforms-layouts/data-form-layout.tsx +1 -1
  294. package/src/dataforms-layouts/panel/index.tsx +19 -7
  295. package/src/dataforms-layouts/panel/style.scss +8 -1
  296. package/src/dataforms-layouts/regular/index.tsx +50 -17
  297. package/src/dataforms-layouts/regular/style.scss +4 -1
  298. package/src/dataviews-layouts/grid/index.tsx +47 -26
  299. package/src/dataviews-layouts/list/index.tsx +12 -5
  300. package/src/dataviews-layouts/table/column-header-menu.tsx +10 -8
  301. package/src/dataviews-layouts/table/column-primary.tsx +26 -13
  302. package/src/dataviews-layouts/table/index.tsx +74 -10
  303. package/src/dataviews-layouts/table/style.scss +37 -1
  304. package/src/dataviews-layouts/table/use-is-horizontal-scroll-end.ts +82 -0
  305. package/src/dataviews-layouts/utils/item-click-wrapper.tsx +93 -0
  306. package/src/field-types/array.tsx +75 -0
  307. package/src/field-types/boolean.tsx +66 -0
  308. package/src/field-types/datetime.tsx +46 -2
  309. package/src/field-types/email.tsx +79 -0
  310. package/src/field-types/index.tsx +45 -3
  311. package/src/field-types/integer.tsx +53 -2
  312. package/src/field-types/media.tsx +28 -0
  313. package/src/field-types/text.tsx +41 -2
  314. package/src/filter-and-sort-data-view.ts +243 -1
  315. package/src/normalize-fields.ts +116 -13
  316. package/src/test/dataviews.tsx +20 -2
  317. package/src/test/filter-and-sort-data-view.js +507 -0
  318. package/src/test/normalize-fields.ts +155 -0
  319. package/src/types.ts +106 -9
  320. package/src/utils.ts +10 -33
  321. package/tsconfig.json +2 -0
  322. package/tsconfig.tsbuildinfo +1 -1
  323. package/build/components/dataviews-filters/filter-summary.js.map +0 -1
  324. package/build/dataviews-layouts/utils/get-clickable-item-props.js +0 -36
  325. package/build/dataviews-layouts/utils/get-clickable-item-props.js.map +0 -1
  326. package/build-module/components/dataviews-filters/filter-summary.js +0 -218
  327. package/build-module/components/dataviews-filters/filter-summary.js.map +0 -1
  328. package/build-module/dataviews-layouts/utils/get-clickable-item-props.js +0 -30
  329. package/build-module/dataviews-layouts/utils/get-clickable-item-props.js.map +0 -1
  330. package/build-types/components/dataviews-filters/filter-summary.d.ts +0 -14
  331. package/build-types/components/dataviews-filters/filter-summary.d.ts.map +0 -1
  332. package/build-types/dataviews-layouts/utils/get-clickable-item-props.d.ts +0 -19
  333. package/build-types/dataviews-layouts/utils/get-clickable-item-props.d.ts.map +0 -1
  334. package/src/components/dataviews-filters/filter-summary.tsx +0 -338
  335. package/src/dataviews-layouts/utils/get-clickable-item-props.ts +0 -39
@@ -1,9 +1,25 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import type { FunctionComponent } from 'react';
5
+
1
6
  /**
2
7
  * Internal dependencies
3
8
  */
4
9
  import getFieldTypeDefinition from './field-types';
5
- import type { Field, NormalizedField } from './types';
10
+ import type {
11
+ DataViewRenderFieldProps,
12
+ Field,
13
+ FieldTypeDefinition,
14
+ NormalizedFilterByConfig,
15
+ NormalizedField,
16
+ } from './types';
6
17
  import { getControl } from './dataform-controls';
18
+ import {
19
+ ALL_OPERATORS,
20
+ OPERATOR_BETWEEN,
21
+ SINGLE_SELECTION_OPERATORS,
22
+ } from './constants';
7
23
 
8
24
  const getValueFromId =
9
25
  ( id: string ) =>
@@ -21,6 +37,83 @@ const getValueFromId =
21
37
  return value;
22
38
  };
23
39
 
40
+ function getFilterBy< Item >(
41
+ field: Field< Item >,
42
+ fieldTypeDefinition: FieldTypeDefinition< Item >
43
+ ): NormalizedFilterByConfig | false {
44
+ if ( field.filterBy === false ) {
45
+ return false;
46
+ }
47
+
48
+ if ( typeof field.filterBy === 'object' ) {
49
+ let operators = field.filterBy.operators;
50
+
51
+ // Assign default values if no operator was provided.
52
+ if ( ! operators || ! Array.isArray( operators ) ) {
53
+ operators = !! fieldTypeDefinition.filterBy
54
+ ? fieldTypeDefinition.filterBy.defaultOperators
55
+ : [];
56
+ }
57
+
58
+ // Make sure only valid operators are included.
59
+ let validOperators = ALL_OPERATORS;
60
+ if ( typeof fieldTypeDefinition.filterBy === 'object' ) {
61
+ validOperators = fieldTypeDefinition.filterBy.validOperators;
62
+ }
63
+ operators = operators.filter( ( operator ) =>
64
+ validOperators.includes( operator )
65
+ );
66
+
67
+ // The `between` operator is not supported when elements are provided.
68
+ if ( field.elements && operators.includes( OPERATOR_BETWEEN ) ) {
69
+ operators = operators.filter(
70
+ ( operator ) => operator !== OPERATOR_BETWEEN
71
+ );
72
+ }
73
+
74
+ // Do not allow mixing single & multiselection operators.
75
+ // Remove multiselection operators if any of the single selection ones is present.
76
+ const hasSingleSelectionOperator = operators.some( ( operator ) =>
77
+ SINGLE_SELECTION_OPERATORS.includes( operator )
78
+ );
79
+ if ( hasSingleSelectionOperator ) {
80
+ operators = operators.filter( ( operator ) =>
81
+ // The 'Between' operator is unique as it can be combined with single selection operators.
82
+ [ ...SINGLE_SELECTION_OPERATORS, OPERATOR_BETWEEN ].includes(
83
+ operator
84
+ )
85
+ );
86
+ }
87
+
88
+ // If no operators are left at this point,
89
+ // the filters should be disabled.
90
+ if ( operators.length === 0 ) {
91
+ return false;
92
+ }
93
+
94
+ return {
95
+ isPrimary: !! field.filterBy.isPrimary,
96
+ operators,
97
+ };
98
+ }
99
+
100
+ if ( fieldTypeDefinition.filterBy === false ) {
101
+ return false;
102
+ }
103
+
104
+ let defaultOperators = fieldTypeDefinition.filterBy.defaultOperators;
105
+ // The `between` operator is not supported when elements are provided.
106
+ if ( field.elements && defaultOperators.includes( OPERATOR_BETWEEN ) ) {
107
+ defaultOperators = defaultOperators.filter(
108
+ ( operator ) => operator !== OPERATOR_BETWEEN
109
+ );
110
+ }
111
+
112
+ return {
113
+ operators: defaultOperators,
114
+ };
115
+ }
116
+
24
117
  /**
25
118
  * Apply default values and normalize the fields config.
26
119
  *
@@ -31,8 +124,9 @@ export function normalizeFields< Item >(
31
124
  fields: Field< Item >[]
32
125
  ): NormalizedField< Item >[] {
33
126
  return fields.map( ( field ) => {
34
- const fieldTypeDefinition = getFieldTypeDefinition( field.type );
35
-
127
+ const fieldTypeDefinition = getFieldTypeDefinition< Item >(
128
+ field.type
129
+ );
36
130
  const getValue = field.getValue || getValueFromId( field.id );
37
131
 
38
132
  const sort =
@@ -56,16 +150,20 @@ export function normalizeFields< Item >(
56
150
 
57
151
  const Edit = getControl( field, fieldTypeDefinition );
58
152
 
59
- const renderFromElements = ( { item }: { item: Item } ) => {
60
- const value = getValue( { item } );
61
- return (
62
- field?.elements?.find( ( element ) => element.value === value )
63
- ?.label || getValue( { item } )
64
- );
65
- };
66
-
67
153
  const render =
68
- field.render || ( field.elements ? renderFromElements : getValue );
154
+ field.render ??
155
+ function render( {
156
+ item,
157
+ field: renderedField,
158
+ }: DataViewRenderFieldProps< Item > ) {
159
+ return (
160
+ fieldTypeDefinition.render as FunctionComponent<
161
+ DataViewRenderFieldProps< Item >
162
+ >
163
+ )( { item, field: renderedField } );
164
+ };
165
+
166
+ const filterBy = getFilterBy( field, fieldTypeDefinition );
69
167
 
70
168
  return {
71
169
  ...field,
@@ -77,7 +175,12 @@ export function normalizeFields< Item >(
77
175
  isValid,
78
176
  Edit,
79
177
  enableHiding: field.enableHiding ?? true,
80
- enableSorting: field.enableSorting ?? true,
178
+ enableSorting:
179
+ field.enableSorting ??
180
+ fieldTypeDefinition.enableSorting ??
181
+ true,
182
+ filterBy,
183
+ readOnly: field.readOnly ?? fieldTypeDefinition.readOnly ?? false,
81
184
  };
82
185
  } );
83
186
  }
@@ -268,7 +268,16 @@ describe( 'DataViews component', () => {
268
268
  } }
269
269
  actions={ actions }
270
270
  isItemClickable={ () => true }
271
- onClickItem={ onClickItemCallback }
271
+ renderItemLink={ ( { item, ...props } ) => (
272
+ <button
273
+ // @ts-expect-error
274
+ onClick={ ( event ) => {
275
+ event.preventDefault();
276
+ onClickItemCallback( item );
277
+ } }
278
+ { ...props }
279
+ />
280
+ ) }
272
281
  />
273
282
  );
274
283
  const titleField = screen.getByText( data[ 0 ].title );
@@ -335,7 +344,16 @@ describe( 'DataViews component', () => {
335
344
  } }
336
345
  actions={ actions }
337
346
  isItemClickable={ () => true }
338
- onClickItem={ mediaClickItemCallback }
347
+ renderItemLink={ ( { item, ...props } ) => (
348
+ <button
349
+ // @ts-expect-error
350
+ onClick={ ( event ) => {
351
+ event.preventDefault();
352
+ mediaClickItemCallback( item );
353
+ } }
354
+ { ...props }
355
+ />
356
+ ) }
339
357
  />
340
358
  );
341
359
  const imageField = screen.getByTestId(
@@ -1,3 +1,8 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import { subDays, subYears } from 'date-fns';
5
+
1
6
  /**
2
7
  * Internal dependencies
3
8
  */
@@ -230,6 +235,508 @@ describe( 'filters', () => {
230
235
  expect( result[ 1 ].title ).toBe( 'Space' );
231
236
  expect( result[ 2 ].title ).toBe( 'NASA' );
232
237
  } );
238
+
239
+ it( 'should search using IS filter and return all values if filter.value is undefined', () => {
240
+ const { data: result } = filterSortAndPaginate(
241
+ data,
242
+ {
243
+ filters: [
244
+ {
245
+ field: 'type',
246
+ operator: 'is',
247
+ value: undefined,
248
+ },
249
+ ],
250
+ },
251
+ fields
252
+ );
253
+ expect( result ).toHaveLength( 11 );
254
+ expect( result[ 0 ].title ).toBe( 'Apollo' );
255
+ expect( result[ 1 ].title ).toBe( 'Space' );
256
+ expect( result[ 2 ].title ).toBe( 'NASA' );
257
+ expect( result[ 3 ].title ).toBe( 'Neptune' );
258
+ expect( result[ 4 ].title ).toBe( 'Mercury' );
259
+ expect( result[ 5 ].title ).toBe( 'Venus' );
260
+ expect( result[ 6 ].title ).toBe( 'Earth' );
261
+ expect( result[ 7 ].title ).toBe( 'Mars' );
262
+ expect( result[ 8 ].title ).toBe( 'Jupiter' );
263
+ expect( result[ 9 ].title ).toBe( 'Saturn' );
264
+ expect( result[ 10 ].title ).toBe( 'Uranus' );
265
+ } );
266
+
267
+ it( 'should filter using LESS THAN operator for integer', () => {
268
+ const { data: result } = filterSortAndPaginate(
269
+ data,
270
+ {
271
+ filters: [
272
+ {
273
+ field: 'satellites',
274
+ operator: 'lessThan',
275
+ value: 2,
276
+ },
277
+ ],
278
+ },
279
+ fields
280
+ );
281
+ expect( result.every( ( item ) => item.satellites < 2 ) ).toBe( true );
282
+ } );
283
+
284
+ it( 'should filter using GREATER THAN operator for integer', () => {
285
+ const { data: result } = filterSortAndPaginate(
286
+ data,
287
+ {
288
+ filters: [
289
+ {
290
+ field: 'satellites',
291
+ operator: 'greaterThan',
292
+ value: 10,
293
+ },
294
+ ],
295
+ },
296
+ fields
297
+ );
298
+ expect( result.every( ( item ) => item.satellites > 10 ) ).toBe( true );
299
+ } );
300
+
301
+ it( 'should filter using LESS THAN OR EQUAL operator for integer', () => {
302
+ const { data: result } = filterSortAndPaginate(
303
+ data,
304
+ {
305
+ filters: [
306
+ {
307
+ field: 'satellites',
308
+ operator: 'lessThanOrEqual',
309
+ value: 1,
310
+ },
311
+ ],
312
+ },
313
+ fields
314
+ );
315
+ expect( result.every( ( item ) => item.satellites <= 1 ) ).toBe( true );
316
+ } );
317
+
318
+ it( 'should filter using GREATER THAN OR EQUAL operator for integer', () => {
319
+ const { data: result } = filterSortAndPaginate(
320
+ data,
321
+ {
322
+ filters: [
323
+ {
324
+ field: 'satellites',
325
+ operator: 'greaterThanOrEqual',
326
+ value: 27,
327
+ },
328
+ ],
329
+ },
330
+ fields
331
+ );
332
+ expect( result.every( ( item ) => item.satellites >= 27 ) ).toBe(
333
+ true
334
+ );
335
+ } );
336
+
337
+ it( 'should filter using CONTAINS operator for text fields', () => {
338
+ const { data: result } = filterSortAndPaginate(
339
+ data,
340
+ {
341
+ filters: [
342
+ {
343
+ field: 'title',
344
+ operator: 'contains',
345
+ value: 'nep',
346
+ },
347
+ ],
348
+ },
349
+ fields
350
+ );
351
+ expect( result ).toHaveLength( 1 );
352
+ expect( result[ 0 ].title ).toBe( 'Neptune' );
353
+ } );
354
+
355
+ it( 'should filter using NOT_CONTAINS operator for text fields', () => {
356
+ const { data: result } = filterSortAndPaginate(
357
+ data,
358
+ {
359
+ filters: [
360
+ {
361
+ field: 'description',
362
+ operator: 'notContains',
363
+ value: 'description',
364
+ },
365
+ ],
366
+ },
367
+ fields
368
+ );
369
+ // Only 'NASA photo' and 'La planète Vénus' do not contain 'description'
370
+ expect( result.map( ( r ) => r.description ) ).toEqual( [
371
+ 'NASA photo',
372
+ 'La planète Vénus',
373
+ ] );
374
+ } );
375
+
376
+ it( 'should filter using STARTS_WITH operator for text fields', () => {
377
+ const { data: result } = filterSortAndPaginate(
378
+ data,
379
+ {
380
+ filters: [
381
+ {
382
+ field: 'title',
383
+ operator: 'startsWith',
384
+ value: 'Mar',
385
+ },
386
+ ],
387
+ },
388
+ fields
389
+ );
390
+ expect( result.map( ( r ) => r.title ) ).toContain( 'Mars' );
391
+ } );
392
+
393
+ it( 'should filter using BEFORE operator for datetime', () => {
394
+ const { data: result } = filterSortAndPaginate(
395
+ data,
396
+ {
397
+ filters: [
398
+ {
399
+ field: 'date',
400
+ operator: 'before',
401
+ value: '2020-01-01',
402
+ },
403
+ ],
404
+ },
405
+ fields
406
+ );
407
+ expect(
408
+ result.every(
409
+ ( item ) => new Date( item.date ) < new Date( '2020-01-01' )
410
+ )
411
+ ).toBe( true );
412
+ } );
413
+
414
+ it( 'should filter using AFTER operator for datetime', () => {
415
+ const { data: result } = filterSortAndPaginate(
416
+ data,
417
+ {
418
+ filters: [
419
+ {
420
+ field: 'date',
421
+ operator: 'after',
422
+ value: '2020-01-01',
423
+ },
424
+ ],
425
+ },
426
+ fields
427
+ );
428
+ expect(
429
+ result.every(
430
+ ( item ) => new Date( item.date ) > new Date( '2020-01-01' )
431
+ )
432
+ ).toBe( true );
433
+ } );
434
+
435
+ it( 'should filter using BEFORE (inc) operator for datetime', () => {
436
+ const { data: result } = filterSortAndPaginate(
437
+ data,
438
+ {
439
+ filters: [
440
+ {
441
+ field: 'date',
442
+ operator: 'beforeInc',
443
+ value: '2020-01-01',
444
+ },
445
+ ],
446
+ },
447
+ fields
448
+ );
449
+ expect(
450
+ result.every(
451
+ ( item ) => new Date( item.date ) <= new Date( '2020-01-01' )
452
+ )
453
+ ).toBe( true );
454
+ } );
455
+
456
+ it( 'should filter using AFTER (inc) operator for datetime', () => {
457
+ const { data: result } = filterSortAndPaginate(
458
+ data,
459
+ {
460
+ filters: [
461
+ {
462
+ field: 'date',
463
+ operator: 'afterInc',
464
+ value: '2020-01-01',
465
+ },
466
+ ],
467
+ },
468
+ fields
469
+ );
470
+ expect(
471
+ result.every(
472
+ ( item ) => new Date( item.date ) >= new Date( '2020-01-01' )
473
+ )
474
+ ).toBe( true );
475
+ } );
476
+
477
+ it( 'should filter using ON operator for datetime with exact date match', () => {
478
+ const { data: result } = filterSortAndPaginate(
479
+ data,
480
+ {
481
+ filters: [
482
+ {
483
+ field: 'date',
484
+ operator: 'on',
485
+ value: '2020-01-01',
486
+ },
487
+ ],
488
+ },
489
+ fields
490
+ );
491
+ expect( result.length ).toBe( 2 );
492
+ expect( result[ 0 ].title ).toBe( 'Neptune' );
493
+ } );
494
+
495
+ it( 'should filter using ON operator for datetime with different date formats', () => {
496
+ // Test that '2019-03-01T00:00:00Z' matches '2019-03-01'
497
+ const testData = [
498
+ { title: 'Test Item 1', date: '2019-03-01T00:00:00Z' },
499
+ { title: 'Test Item 2', date: '2019-03-02' },
500
+ ];
501
+ const testFields = [
502
+ {
503
+ id: 'date',
504
+ type: 'datetime',
505
+ getValue: ( { item } ) => item.date,
506
+ },
507
+ ];
508
+
509
+ const { data: result } = filterSortAndPaginate(
510
+ testData,
511
+ {
512
+ filters: [
513
+ {
514
+ field: 'date',
515
+ operator: 'on',
516
+ value: '2019-03-01',
517
+ },
518
+ ],
519
+ },
520
+ testFields
521
+ );
522
+ expect( result.length ).toBe( 1 );
523
+ expect( result[ 0 ].title ).toBe( 'Test Item 1' );
524
+ } );
525
+
526
+ it( 'should filter using NOT_ON operator for datetime', () => {
527
+ const { data: result } = filterSortAndPaginate(
528
+ data,
529
+ {
530
+ filters: [
531
+ {
532
+ field: 'date',
533
+ operator: 'notOn',
534
+ value: '2020-01-01',
535
+ },
536
+ ],
537
+ },
538
+ fields
539
+ );
540
+ expect( result.length ).toBe( 9 );
541
+ expect( result.map( ( r ) => r.title ) ).not.toContain( 'Neptune' );
542
+ } );
543
+
544
+ it( 'should filter using NOT_ON operator for datetime with different date formats', () => {
545
+ // Test that '2019-03-01T00:00:00Z' does not match '2019-03-02'
546
+ const testData = [
547
+ { title: 'Test Item 1', date: '2019-03-01T00:00:00Z' },
548
+ { title: 'Test Item 2', date: '2019-03-02T00:00:00Z' },
549
+ ];
550
+ const testFields = [
551
+ {
552
+ id: 'date',
553
+ type: 'datetime',
554
+ getValue: ( { item } ) => item.date,
555
+ },
556
+ ];
557
+
558
+ const { data: result } = filterSortAndPaginate(
559
+ testData,
560
+ {
561
+ filters: [
562
+ {
563
+ field: 'date',
564
+ operator: 'notOn',
565
+ value: '2019-03-01',
566
+ },
567
+ ],
568
+ },
569
+ testFields
570
+ );
571
+ expect( result.length ).toBe( 1 );
572
+ expect( result[ 0 ].title ).toBe( 'Test Item 2' );
573
+ } );
574
+
575
+ it( 'should filter numbers inclusively between min and max using BETWEEN operator', () => {
576
+ const { data: result } = filterSortAndPaginate(
577
+ data,
578
+ {
579
+ filters: [
580
+ {
581
+ field: 'satellites',
582
+ operator: 'between',
583
+ value: [ 10, 30 ],
584
+ },
585
+ ],
586
+ },
587
+ fields
588
+ );
589
+ expect( result.map( ( r ) => r.title ).sort() ).toEqual( [
590
+ 'Neptune',
591
+ 'Uranus',
592
+ ] );
593
+ } );
594
+
595
+ it( 'should filter numbers inclusively at the edges using BETWEEN operator', () => {
596
+ const { data: result } = filterSortAndPaginate(
597
+ data,
598
+ {
599
+ filters: [
600
+ {
601
+ field: 'satellites',
602
+ operator: 'between',
603
+ value: [ 28, 28 ],
604
+ },
605
+ ],
606
+ },
607
+ fields
608
+ );
609
+ expect( result.map( ( r ) => r.title ) ).toEqual( [ 'Uranus' ] );
610
+ } );
611
+
612
+ it( 'should filter dates inclusively between min and max using BETWEEN operator', () => {
613
+ const { data: result } = filterSortAndPaginate(
614
+ data,
615
+ {
616
+ filters: [
617
+ {
618
+ field: 'date',
619
+ operator: 'between',
620
+ value: [ '1977-08-20', '1989-08-25' ],
621
+ },
622
+ ],
623
+ },
624
+ fields
625
+ );
626
+ const allInRange = result.every(
627
+ ( r ) => r.date >= '1977-08-20' && r.date <= '1989-08-25'
628
+ );
629
+ expect( allInRange ).toBe( true );
630
+ } );
631
+
632
+ it( 'should return no results if min > max using BETWEEN operator', () => {
633
+ const { data: result } = filterSortAndPaginate(
634
+ data,
635
+ {
636
+ filters: [
637
+ {
638
+ field: 'satellites',
639
+ operator: 'between',
640
+ value: [ 30, 10 ],
641
+ },
642
+ ],
643
+ },
644
+ fields
645
+ );
646
+ expect( result ).toHaveLength( 0 );
647
+ } );
648
+
649
+ it( 'should filter using IN_THE_PAST operator for datetime (days)', () => {
650
+ const testData = [
651
+ { title: 'Recent', date: subDays( new Date(), 5 ) },
652
+ { title: 'Old', date: subDays( new Date(), 14 ) },
653
+ ];
654
+ const testFields = [ { id: 'date', type: 'datetime', label: 'Date' } ];
655
+ const { data: result } = filterSortAndPaginate(
656
+ testData,
657
+ {
658
+ filters: [
659
+ {
660
+ field: 'date',
661
+ operator: 'inThePast',
662
+ value: { value: 7, unit: 'days' },
663
+ },
664
+ ],
665
+ },
666
+ testFields
667
+ );
668
+ expect( result ).toHaveLength( 1 );
669
+ expect( result ).toStrictEqual( [ testData[ 0 ] ] );
670
+ } );
671
+
672
+ it( 'should filter using OVER operator for datetime (days)', () => {
673
+ const testData = [
674
+ { title: 'Recent', date: subDays( new Date(), 5 ) },
675
+ { title: 'Old', date: subDays( new Date(), 14 ) },
676
+ ];
677
+ const testFields = [ { id: 'date', type: 'datetime', label: 'Date' } ];
678
+ const { data: result } = filterSortAndPaginate(
679
+ testData,
680
+ {
681
+ filters: [
682
+ {
683
+ field: 'date',
684
+ operator: 'over',
685
+ value: { value: 10, unit: 'days' },
686
+ },
687
+ ],
688
+ },
689
+ testFields
690
+ );
691
+ expect( result ).toHaveLength( 1 );
692
+ expect( result ).toStrictEqual( [ testData[ 1 ] ] );
693
+ } );
694
+
695
+ it( 'should filter using IN_THE_PAST operator for datetime (years)', () => {
696
+ const testData = [
697
+ { title: 'Recent', date: subYears( new Date(), 1 ) },
698
+ { title: 'Old', date: subYears( new Date(), 5 ) },
699
+ ];
700
+ const testFields = [ { id: 'date', type: 'datetime', label: 'Date' } ];
701
+ const { data: result } = filterSortAndPaginate(
702
+ testData,
703
+ {
704
+ filters: [
705
+ {
706
+ field: 'date',
707
+ operator: 'inThePast',
708
+ value: { value: 3, unit: 'years' },
709
+ },
710
+ ],
711
+ },
712
+ testFields
713
+ );
714
+ expect( result ).toHaveLength( 1 );
715
+ expect( result ).toStrictEqual( [ testData[ 0 ] ] );
716
+ } );
717
+
718
+ it( 'should filter using OVER operator for datetime (years)', () => {
719
+ const testData = [
720
+ { title: 'Recent', date: subYears( new Date(), 1 ) },
721
+ { title: 'Old', date: subYears( new Date(), 5 ) },
722
+ ];
723
+ const testFields = [ { id: 'date', type: 'datetime', label: 'Date' } ];
724
+ const { data: result } = filterSortAndPaginate(
725
+ testData,
726
+ {
727
+ filters: [
728
+ {
729
+ field: 'date',
730
+ operator: 'over',
731
+ value: { value: 3, unit: 'years' },
732
+ },
733
+ ],
734
+ },
735
+ testFields
736
+ );
737
+ expect( result ).toHaveLength( 1 );
738
+ expect( result ).toStrictEqual( [ testData[ 1 ] ] );
739
+ } );
233
740
  } );
234
741
 
235
742
  describe( 'sorting', () => {