@wordpress/dataviews 10.0.1-next.ff1cebbba.0 → 10.1.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 (399) hide show
  1. package/CHANGELOG.md +10 -1
  2. package/README.md +97 -8
  3. package/build/components/dataform/index.js +11 -2
  4. package/build/components/dataform/index.js.map +2 -2
  5. package/build/components/dataform-context/index.js.map +2 -2
  6. package/build/components/dataviews-bulk-actions/index.js +2 -4
  7. package/build/components/dataviews-bulk-actions/index.js.map +2 -2
  8. package/build/components/dataviews-filters/filter.js +9 -4
  9. package/build/components/dataviews-filters/filter.js.map +3 -3
  10. package/build/components/dataviews-filters/search-widget.js +13 -2
  11. package/build/components/dataviews-filters/search-widget.js.map +3 -3
  12. package/build/components/dataviews-filters/use-filters.js +4 -2
  13. package/build/components/dataviews-filters/use-filters.js.map +2 -2
  14. package/build/components/dataviews-item-actions/index.js +6 -6
  15. package/build/components/dataviews-item-actions/index.js.map +2 -2
  16. package/build/dataform-controls/array.js +14 -61
  17. package/build/dataform-controls/array.js.map +3 -3
  18. package/build/dataform-controls/checkbox.js +5 -29
  19. package/build/dataform-controls/checkbox.js.map +3 -3
  20. package/build/dataform-controls/color.js +5 -29
  21. package/build/dataform-controls/color.js.map +3 -3
  22. package/build/dataform-controls/date.js +40 -57
  23. package/build/dataform-controls/date.js.map +3 -3
  24. package/build/dataform-controls/datetime.js +12 -37
  25. package/build/dataform-controls/datetime.js.map +3 -3
  26. package/build/dataform-controls/email.js +3 -1
  27. package/build/dataform-controls/email.js.map +2 -2
  28. package/build/dataform-controls/index.js +2 -1
  29. package/build/dataform-controls/index.js.map +3 -3
  30. package/build/dataform-controls/password.js +3 -1
  31. package/build/dataform-controls/password.js.map +2 -2
  32. package/build/dataform-controls/radio.js +24 -43
  33. package/build/dataform-controls/radio.js.map +3 -3
  34. package/build/dataform-controls/select.js +13 -30
  35. package/build/dataform-controls/select.js.map +3 -3
  36. package/build/dataform-controls/telephone.js +3 -1
  37. package/build/dataform-controls/telephone.js.map +2 -2
  38. package/build/dataform-controls/text.js +3 -1
  39. package/build/dataform-controls/text.js.map +2 -2
  40. package/build/dataform-controls/textarea.js +6 -30
  41. package/build/dataform-controls/textarea.js.map +3 -3
  42. package/build/dataform-controls/toggle-group.js +38 -56
  43. package/build/dataform-controls/toggle-group.js.map +3 -3
  44. package/build/dataform-controls/toggle.js +6 -30
  45. package/build/dataform-controls/toggle.js.map +3 -3
  46. package/build/dataform-controls/url.js +3 -1
  47. package/build/dataform-controls/url.js.map +2 -2
  48. package/build/dataform-controls/utils/get-custom-validity.js +35 -0
  49. package/build/dataform-controls/utils/get-custom-validity.js.map +7 -0
  50. package/build/dataform-controls/utils/validated-input.js +4 -28
  51. package/build/dataform-controls/utils/validated-input.js.map +3 -3
  52. package/build/dataform-controls/utils/validated-number.js +6 -30
  53. package/build/dataform-controls/utils/validated-number.js.map +3 -3
  54. package/build/dataform-layouts/card/index.js +6 -3
  55. package/build/dataform-layouts/card/index.js.map +2 -2
  56. package/build/dataform-layouts/data-form-layout.js +8 -2
  57. package/build/dataform-layouts/data-form-layout.js.map +2 -2
  58. package/build/dataform-layouts/panel/dropdown.js +21 -9
  59. package/build/dataform-layouts/panel/dropdown.js.map +2 -2
  60. package/build/dataform-layouts/panel/index.js +12 -10
  61. package/build/dataform-layouts/panel/index.js.map +2 -2
  62. package/build/dataform-layouts/panel/modal.js +32 -22
  63. package/build/dataform-layouts/panel/modal.js.map +3 -3
  64. package/build/dataform-layouts/regular/index.js +8 -4
  65. package/build/dataform-layouts/regular/index.js.map +2 -2
  66. package/build/dataform-layouts/row/index.js +11 -7
  67. package/build/dataform-layouts/row/index.js.map +2 -2
  68. package/build/dataviews-layouts/list/index.js +7 -7
  69. package/build/dataviews-layouts/list/index.js.map +2 -2
  70. package/build/dataviews-layouts/table/column-header-menu.js +1 -1
  71. package/build/dataviews-layouts/table/column-header-menu.js.map +2 -2
  72. package/build/field-types/boolean.js +3 -2
  73. package/build/field-types/boolean.js.map +3 -3
  74. package/build/field-types/color.js +2 -2
  75. package/build/field-types/color.js.map +3 -3
  76. package/build/field-types/date.js +3 -2
  77. package/build/field-types/date.js.map +3 -3
  78. package/build/field-types/datetime.js +2 -1
  79. package/build/field-types/datetime.js.map +3 -3
  80. package/build/field-types/email.js +2 -1
  81. package/build/field-types/email.js.map +3 -3
  82. package/build/field-types/index.js +2 -1
  83. package/build/field-types/index.js.map +3 -3
  84. package/build/field-types/integer.js +2 -1
  85. package/build/field-types/integer.js.map +3 -3
  86. package/build/field-types/number.js +18 -9
  87. package/build/field-types/number.js.map +3 -3
  88. package/build/field-types/password.js +2 -1
  89. package/build/field-types/password.js.map +3 -3
  90. package/build/field-types/telephone.js +2 -1
  91. package/build/field-types/telephone.js.map +3 -3
  92. package/build/field-types/text.js +2 -1
  93. package/build/field-types/text.js.map +3 -3
  94. package/build/field-types/url.js +2 -1
  95. package/build/field-types/url.js.map +3 -3
  96. package/build/field-types/utils/render-from-elements.js +24 -3
  97. package/build/field-types/utils/render-from-elements.js.map +4 -4
  98. package/build/hooks/index.js +39 -0
  99. package/build/hooks/index.js.map +7 -0
  100. package/build/hooks/use-elements.js +63 -0
  101. package/build/hooks/use-elements.js.map +7 -0
  102. package/build/hooks/use-form-validity.js +426 -0
  103. package/build/hooks/use-form-validity.js.map +7 -0
  104. package/build/index.js +3 -3
  105. package/build/index.js.map +2 -2
  106. package/build/types/dataform.js.map +1 -1
  107. package/build/types/dataviews.js.map +1 -1
  108. package/build/types/field-api.js.map +1 -1
  109. package/build/utils/has-elements.js +27 -0
  110. package/build/utils/has-elements.js.map +7 -0
  111. package/build/utils/normalize-fields.js +4 -2
  112. package/build/utils/normalize-fields.js.map +3 -3
  113. package/build-module/components/dataform/index.js +11 -2
  114. package/build-module/components/dataform/index.js.map +2 -2
  115. package/build-module/components/dataform-context/index.js.map +2 -2
  116. package/build-module/components/dataviews-bulk-actions/index.js +2 -4
  117. package/build-module/components/dataviews-bulk-actions/index.js.map +2 -2
  118. package/build-module/components/dataviews-filters/filter.js +9 -4
  119. package/build-module/components/dataviews-filters/filter.js.map +2 -2
  120. package/build-module/components/dataviews-filters/search-widget.js +19 -3
  121. package/build-module/components/dataviews-filters/search-widget.js.map +2 -2
  122. package/build-module/components/dataviews-filters/use-filters.js +4 -2
  123. package/build-module/components/dataviews-filters/use-filters.js.map +2 -2
  124. package/build-module/components/dataviews-item-actions/index.js +6 -6
  125. package/build-module/components/dataviews-item-actions/index.js.map +2 -2
  126. package/build-module/dataform-controls/array.js +16 -63
  127. package/build-module/dataform-controls/array.js.map +2 -2
  128. package/build-module/dataform-controls/checkbox.js +6 -30
  129. package/build-module/dataform-controls/checkbox.js.map +2 -2
  130. package/build-module/dataform-controls/color.js +6 -30
  131. package/build-module/dataform-controls/color.js.map +2 -2
  132. package/build-module/dataform-controls/date.js +49 -66
  133. package/build-module/dataform-controls/date.js.map +2 -2
  134. package/build-module/dataform-controls/datetime.js +14 -39
  135. package/build-module/dataform-controls/datetime.js.map +2 -2
  136. package/build-module/dataform-controls/email.js +3 -1
  137. package/build-module/dataform-controls/email.js.map +2 -2
  138. package/build-module/dataform-controls/index.js +2 -1
  139. package/build-module/dataform-controls/index.js.map +2 -2
  140. package/build-module/dataform-controls/password.js +3 -1
  141. package/build-module/dataform-controls/password.js.map +2 -2
  142. package/build-module/dataform-controls/radio.js +26 -45
  143. package/build-module/dataform-controls/radio.js.map +2 -2
  144. package/build-module/dataform-controls/select.js +15 -32
  145. package/build-module/dataform-controls/select.js.map +2 -2
  146. package/build-module/dataform-controls/telephone.js +3 -1
  147. package/build-module/dataform-controls/telephone.js.map +2 -2
  148. package/build-module/dataform-controls/text.js +3 -1
  149. package/build-module/dataform-controls/text.js.map +2 -2
  150. package/build-module/dataform-controls/textarea.js +7 -31
  151. package/build-module/dataform-controls/textarea.js.map +2 -2
  152. package/build-module/dataform-controls/toggle-group.js +41 -58
  153. package/build-module/dataform-controls/toggle-group.js.map +2 -2
  154. package/build-module/dataform-controls/toggle.js +7 -31
  155. package/build-module/dataform-controls/toggle.js.map +2 -2
  156. package/build-module/dataform-controls/url.js +3 -1
  157. package/build-module/dataform-controls/url.js.map +2 -2
  158. package/build-module/dataform-controls/utils/get-custom-validity.js +15 -0
  159. package/build-module/dataform-controls/utils/get-custom-validity.js.map +7 -0
  160. package/build-module/dataform-controls/utils/validated-input.js +5 -29
  161. package/build-module/dataform-controls/utils/validated-input.js.map +2 -2
  162. package/build-module/dataform-controls/utils/validated-number.js +7 -31
  163. package/build-module/dataform-controls/utils/validated-number.js.map +2 -2
  164. package/build-module/dataform-layouts/card/index.js +6 -3
  165. package/build-module/dataform-layouts/card/index.js.map +2 -2
  166. package/build-module/dataform-layouts/data-form-layout.js +8 -2
  167. package/build-module/dataform-layouts/data-form-layout.js.map +2 -2
  168. package/build-module/dataform-layouts/panel/dropdown.js +21 -9
  169. package/build-module/dataform-layouts/panel/dropdown.js.map +2 -2
  170. package/build-module/dataform-layouts/panel/index.js +12 -10
  171. package/build-module/dataform-layouts/panel/index.js.map +2 -2
  172. package/build-module/dataform-layouts/panel/modal.js +33 -23
  173. package/build-module/dataform-layouts/panel/modal.js.map +2 -2
  174. package/build-module/dataform-layouts/regular/index.js +8 -4
  175. package/build-module/dataform-layouts/regular/index.js.map +2 -2
  176. package/build-module/dataform-layouts/row/index.js +11 -7
  177. package/build-module/dataform-layouts/row/index.js.map +2 -2
  178. package/build-module/dataviews-layouts/list/index.js +7 -7
  179. package/build-module/dataviews-layouts/list/index.js.map +2 -2
  180. package/build-module/dataviews-layouts/table/column-header-menu.js +1 -1
  181. package/build-module/dataviews-layouts/table/column-header-menu.js.map +2 -2
  182. package/build-module/field-types/boolean.js +4 -3
  183. package/build-module/field-types/boolean.js.map +2 -2
  184. package/build-module/field-types/color.js +3 -3
  185. package/build-module/field-types/color.js.map +2 -2
  186. package/build-module/field-types/date.js +4 -3
  187. package/build-module/field-types/date.js.map +2 -2
  188. package/build-module/field-types/datetime.js +3 -2
  189. package/build-module/field-types/datetime.js.map +2 -2
  190. package/build-module/field-types/email.js +3 -2
  191. package/build-module/field-types/email.js.map +2 -2
  192. package/build-module/field-types/index.js +3 -2
  193. package/build-module/field-types/index.js.map +2 -2
  194. package/build-module/field-types/integer.js +3 -2
  195. package/build-module/field-types/integer.js.map +2 -2
  196. package/build-module/field-types/number.js +8 -9
  197. package/build-module/field-types/number.js.map +2 -2
  198. package/build-module/field-types/password.js +3 -2
  199. package/build-module/field-types/password.js.map +2 -2
  200. package/build-module/field-types/telephone.js +3 -2
  201. package/build-module/field-types/telephone.js.map +2 -2
  202. package/build-module/field-types/text.js +3 -2
  203. package/build-module/field-types/text.js.map +2 -2
  204. package/build-module/field-types/url.js +3 -2
  205. package/build-module/field-types/url.js.map +2 -2
  206. package/build-module/field-types/utils/render-from-elements.js +14 -3
  207. package/build-module/field-types/utils/render-from-elements.js.map +3 -3
  208. package/build-module/hooks/index.js +5 -0
  209. package/build-module/hooks/index.js.map +7 -0
  210. package/build-module/hooks/use-elements.js +43 -0
  211. package/build-module/hooks/use-elements.js.map +7 -0
  212. package/build-module/hooks/use-form-validity.js +392 -0
  213. package/build-module/hooks/use-form-validity.js.map +7 -0
  214. package/build-module/index.js +2 -2
  215. package/build-module/index.js.map +2 -2
  216. package/build-module/utils/has-elements.js +7 -0
  217. package/build-module/utils/has-elements.js.map +7 -0
  218. package/build-module/utils/normalize-fields.js +4 -2
  219. package/build-module/utils/normalize-fields.js.map +2 -2
  220. package/build-style/style-rtl.css +10 -4
  221. package/build-style/style.css +10 -4
  222. package/build-types/components/dataform/index.d.ts +1 -1
  223. package/build-types/components/dataform/index.d.ts.map +1 -1
  224. package/build-types/components/dataform-context/index.d.ts.map +1 -1
  225. package/build-types/components/dataviews-bulk-actions/index.d.ts.map +1 -1
  226. package/build-types/components/dataviews-filters/filter.d.ts +1 -1
  227. package/build-types/components/dataviews-filters/filter.d.ts.map +1 -1
  228. package/build-types/components/dataviews-filters/search-widget.d.ts.map +1 -1
  229. package/build-types/components/dataviews-filters/use-filters.d.ts.map +1 -1
  230. package/build-types/components/dataviews-item-actions/index.d.ts.map +1 -1
  231. package/build-types/dataform-controls/array.d.ts +1 -1
  232. package/build-types/dataform-controls/array.d.ts.map +1 -1
  233. package/build-types/dataform-controls/checkbox.d.ts +1 -1
  234. package/build-types/dataform-controls/checkbox.d.ts.map +1 -1
  235. package/build-types/dataform-controls/color.d.ts +1 -1
  236. package/build-types/dataform-controls/color.d.ts.map +1 -1
  237. package/build-types/dataform-controls/date.d.ts +1 -1
  238. package/build-types/dataform-controls/date.d.ts.map +1 -1
  239. package/build-types/dataform-controls/datetime.d.ts +1 -1
  240. package/build-types/dataform-controls/datetime.d.ts.map +1 -1
  241. package/build-types/dataform-controls/email.d.ts +1 -1
  242. package/build-types/dataform-controls/email.d.ts.map +1 -1
  243. package/build-types/dataform-controls/index.d.ts.map +1 -1
  244. package/build-types/dataform-controls/password.d.ts +1 -1
  245. package/build-types/dataform-controls/password.d.ts.map +1 -1
  246. package/build-types/dataform-controls/radio.d.ts +1 -1
  247. package/build-types/dataform-controls/radio.d.ts.map +1 -1
  248. package/build-types/dataform-controls/select.d.ts +1 -1
  249. package/build-types/dataform-controls/select.d.ts.map +1 -1
  250. package/build-types/dataform-controls/telephone.d.ts +1 -1
  251. package/build-types/dataform-controls/telephone.d.ts.map +1 -1
  252. package/build-types/dataform-controls/text.d.ts +1 -1
  253. package/build-types/dataform-controls/text.d.ts.map +1 -1
  254. package/build-types/dataform-controls/textarea.d.ts +1 -1
  255. package/build-types/dataform-controls/textarea.d.ts.map +1 -1
  256. package/build-types/dataform-controls/toggle-group.d.ts +1 -1
  257. package/build-types/dataform-controls/toggle-group.d.ts.map +1 -1
  258. package/build-types/dataform-controls/toggle.d.ts +1 -1
  259. package/build-types/dataform-controls/toggle.d.ts.map +1 -1
  260. package/build-types/dataform-controls/url.d.ts +1 -1
  261. package/build-types/dataform-controls/url.d.ts.map +1 -1
  262. package/build-types/dataform-controls/utils/get-custom-validity.d.ts +9 -0
  263. package/build-types/dataform-controls/utils/get-custom-validity.d.ts.map +1 -0
  264. package/build-types/dataform-controls/utils/validated-input.d.ts +1 -1
  265. package/build-types/dataform-controls/utils/validated-input.d.ts.map +1 -1
  266. package/build-types/dataform-controls/utils/validated-number.d.ts +1 -1
  267. package/build-types/dataform-controls/utils/validated-number.d.ts.map +1 -1
  268. package/build-types/dataform-layouts/card/index.d.ts +1 -1
  269. package/build-types/dataform-layouts/card/index.d.ts.map +1 -1
  270. package/build-types/dataform-layouts/data-form-layout.d.ts +5 -3
  271. package/build-types/dataform-layouts/data-form-layout.d.ts.map +1 -1
  272. package/build-types/dataform-layouts/panel/dropdown.d.ts +8 -7
  273. package/build-types/dataform-layouts/panel/dropdown.d.ts.map +1 -1
  274. package/build-types/dataform-layouts/panel/index.d.ts +1 -1
  275. package/build-types/dataform-layouts/panel/index.d.ts.map +1 -1
  276. package/build-types/dataform-layouts/panel/modal.d.ts +5 -5
  277. package/build-types/dataform-layouts/panel/modal.d.ts.map +1 -1
  278. package/build-types/dataform-layouts/regular/index.d.ts +1 -1
  279. package/build-types/dataform-layouts/regular/index.d.ts.map +1 -1
  280. package/build-types/dataform-layouts/row/index.d.ts +1 -1
  281. package/build-types/dataform-layouts/row/index.d.ts.map +1 -1
  282. package/build-types/dataviews-layouts/list/index.d.ts.map +1 -1
  283. package/build-types/field-types/boolean.d.ts +1 -1
  284. package/build-types/field-types/date.d.ts +1 -1
  285. package/build-types/field-types/datetime.d.ts.map +1 -1
  286. package/build-types/field-types/email.d.ts.map +1 -1
  287. package/build-types/field-types/index.d.ts.map +1 -1
  288. package/build-types/field-types/integer.d.ts.map +1 -1
  289. package/build-types/field-types/number.d.ts +1 -1
  290. package/build-types/field-types/number.d.ts.map +1 -1
  291. package/build-types/field-types/password.d.ts +1 -1
  292. package/build-types/field-types/password.d.ts.map +1 -1
  293. package/build-types/field-types/telephone.d.ts.map +1 -1
  294. package/build-types/field-types/text.d.ts.map +1 -1
  295. package/build-types/field-types/url.d.ts.map +1 -1
  296. package/build-types/field-types/utils/render-from-elements.d.ts +1 -1
  297. package/build-types/field-types/utils/render-from-elements.d.ts.map +1 -1
  298. package/build-types/hooks/index.d.ts +5 -0
  299. package/build-types/hooks/index.d.ts.map +1 -0
  300. package/build-types/hooks/use-elements.d.ts +12 -0
  301. package/build-types/hooks/use-elements.d.ts.map +1 -0
  302. package/build-types/hooks/use-form-validity.d.ts +16 -0
  303. package/build-types/hooks/use-form-validity.d.ts.map +1 -0
  304. package/build-types/index.d.ts +1 -1
  305. package/build-types/index.d.ts.map +1 -1
  306. package/build-types/stories/dataform.story.d.ts +14 -4
  307. package/build-types/stories/dataform.story.d.ts.map +1 -1
  308. package/build-types/stories/dataviews.fixtures.d.ts.map +1 -1
  309. package/build-types/stories/field-types.story.d.ts +38 -15
  310. package/build-types/stories/field-types.story.d.ts.map +1 -1
  311. package/build-types/test/use-form-validity.d.ts +2 -0
  312. package/build-types/test/use-form-validity.d.ts.map +1 -0
  313. package/build-types/types/dataform.d.ts +4 -1
  314. package/build-types/types/dataform.d.ts.map +1 -1
  315. package/build-types/types/dataviews.d.ts +10 -2
  316. package/build-types/types/dataviews.d.ts.map +1 -1
  317. package/build-types/types/field-api.d.ts +25 -1
  318. package/build-types/types/field-api.d.ts.map +1 -1
  319. package/build-types/utils/has-elements.d.ts +6 -0
  320. package/build-types/utils/has-elements.d.ts.map +1 -0
  321. package/build-types/utils/normalize-fields.d.ts.map +1 -1
  322. package/build-wp/index.js +1011 -819
  323. package/package.json +15 -15
  324. package/src/components/dataform/index.tsx +7 -1
  325. package/src/components/dataform-context/index.tsx +3 -1
  326. package/src/components/dataviews-bulk-actions/index.tsx +3 -5
  327. package/src/components/dataviews-filters/filter.tsx +11 -5
  328. package/src/components/dataviews-filters/search-widget.tsx +30 -3
  329. package/src/components/dataviews-filters/style.scss +8 -0
  330. package/src/components/dataviews-filters/use-filters.ts +4 -2
  331. package/src/components/dataviews-item-actions/index.tsx +11 -6
  332. package/src/components/dataviews-item-actions/style.scss +1 -0
  333. package/src/dataform-controls/array.tsx +16 -82
  334. package/src/dataform-controls/checkbox.tsx +5 -41
  335. package/src/dataform-controls/color.tsx +5 -37
  336. package/src/dataform-controls/date.tsx +63 -76
  337. package/src/dataform-controls/datetime.tsx +11 -45
  338. package/src/dataform-controls/email.tsx +2 -0
  339. package/src/dataform-controls/index.tsx +2 -1
  340. package/src/dataform-controls/password.tsx +2 -0
  341. package/src/dataform-controls/radio.tsx +24 -55
  342. package/src/dataform-controls/select.tsx +14 -42
  343. package/src/dataform-controls/telephone.tsx +2 -0
  344. package/src/dataform-controls/text.tsx +2 -0
  345. package/src/dataform-controls/textarea.tsx +6 -42
  346. package/src/dataform-controls/toggle-group.tsx +38 -64
  347. package/src/dataform-controls/toggle.tsx +6 -42
  348. package/src/dataform-controls/url.tsx +2 -0
  349. package/src/dataform-controls/utils/get-custom-validity.ts +24 -0
  350. package/src/dataform-controls/utils/validated-input.tsx +4 -40
  351. package/src/dataform-controls/utils/validated-number.tsx +6 -44
  352. package/src/dataform-layouts/card/index.tsx +3 -0
  353. package/src/dataform-layouts/data-form-layout.tsx +18 -3
  354. package/src/dataform-layouts/panel/dropdown.tsx +35 -14
  355. package/src/dataform-layouts/panel/index.tsx +9 -7
  356. package/src/dataform-layouts/panel/modal.tsx +41 -30
  357. package/src/dataform-layouts/regular/index.tsx +4 -0
  358. package/src/dataform-layouts/row/index.tsx +8 -4
  359. package/src/dataviews-layouts/list/index.tsx +9 -7
  360. package/src/dataviews-layouts/table/column-header-menu.tsx +1 -1
  361. package/src/dataviews-layouts/table/style.scss +2 -3
  362. package/src/field-types/boolean.tsx +3 -3
  363. package/src/field-types/color.tsx +3 -3
  364. package/src/field-types/date.tsx +3 -3
  365. package/src/field-types/datetime.tsx +6 -4
  366. package/src/field-types/email.tsx +6 -4
  367. package/src/field-types/index.tsx +6 -4
  368. package/src/field-types/integer.tsx +6 -4
  369. package/src/field-types/number.tsx +8 -12
  370. package/src/field-types/password.tsx +6 -4
  371. package/src/field-types/telephone.tsx +6 -4
  372. package/src/field-types/text.tsx +6 -4
  373. package/src/field-types/url.tsx +6 -4
  374. package/src/field-types/utils/render-from-elements.tsx +29 -0
  375. package/src/hooks/index.ts +4 -0
  376. package/src/hooks/use-elements.ts +66 -0
  377. package/src/hooks/use-form-validity.ts +571 -0
  378. package/src/index.ts +1 -1
  379. package/src/stories/dataform.story.tsx +243 -59
  380. package/src/stories/dataviews.fixtures.tsx +9 -4
  381. package/src/stories/field-types.story.tsx +159 -29
  382. package/src/test/use-form-validity.ts +546 -0
  383. package/src/types/dataform.ts +5 -1
  384. package/src/types/dataviews.ts +12 -2
  385. package/src/types/field-api.ts +32 -1
  386. package/src/utils/has-elements.ts +11 -0
  387. package/src/utils/normalize-fields.ts +7 -2
  388. package/tsconfig.tsbuildinfo +1 -1
  389. package/build/utils/is-item-valid.js +0 -75
  390. package/build/utils/is-item-valid.js.map +0 -7
  391. package/build-module/utils/is-item-valid.js +0 -45
  392. package/build-module/utils/is-item-valid.js.map +0 -7
  393. package/build-types/test/validation.d.ts +0 -2
  394. package/build-types/test/validation.d.ts.map +0 -1
  395. package/build-types/utils/is-item-valid.d.ts +0 -12
  396. package/build-types/utils/is-item-valid.d.ts.map +0 -1
  397. package/src/field-types/utils/render-from-elements.ts +0 -15
  398. package/src/test/validation.ts +0 -322
  399. package/src/utils/is-item-valid.ts +0 -93
@@ -0,0 +1,546 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import { renderHook, waitFor } from '@testing-library/react';
5
+
6
+ /**
7
+ * Internal dependencies
8
+ */
9
+ import { useFormValidity } from '../hooks';
10
+ import type { Field } from '../types';
11
+
12
+ describe( 'useFormValidity', () => {
13
+ describe( 'fields', () => {
14
+ it( 'can override the defaults', () => {
15
+ const item = { id: 1, order: 'd' };
16
+ const fields: Field< {} >[] = [
17
+ {
18
+ id: 'order',
19
+ type: 'integer',
20
+ elements: [
21
+ { value: 'a', label: 'A' },
22
+ { value: 'b', label: 'B' },
23
+ ],
24
+ isValid: {
25
+ elements: false,
26
+ custom: () => null, // Overrides the validation provided for integer types.
27
+ },
28
+ },
29
+ ];
30
+ const form = { fields: [ 'order' ] };
31
+ const {
32
+ result: {
33
+ current: { validity, isValid },
34
+ },
35
+ } = renderHook( () => useFormValidity( item, fields, form ) );
36
+ expect( validity ).toEqual( undefined );
37
+ expect( isValid ).toBe( true );
38
+ } );
39
+
40
+ it( 'not in the form are ignored', () => {
41
+ const item = { id: 1, valid_order: 2, invalid_order: 'd' };
42
+ const fields: Field< {} >[] = [
43
+ {
44
+ id: 'valid_order',
45
+ type: 'integer',
46
+ },
47
+ {
48
+ id: 'invalid_order',
49
+ type: 'integer',
50
+ },
51
+ ];
52
+ const form = { fields: [ 'valid_order' ] };
53
+ const {
54
+ result: {
55
+ current: { validity, isValid },
56
+ },
57
+ } = renderHook( () => useFormValidity( item, fields, form ) );
58
+ expect( validity ).toEqual( undefined );
59
+ expect( isValid ).toBe( true );
60
+ } );
61
+
62
+ it( 'with children are checked for validity', () => {
63
+ const item = { id: 1, order: undefined };
64
+ const fields: Field< {} >[] = [
65
+ {
66
+ id: 'order',
67
+ type: 'integer',
68
+ isValid: {
69
+ required: true,
70
+ },
71
+ },
72
+ ];
73
+ const form = {
74
+ fields: [ { id: 'combinedField', children: [ 'order' ] } ],
75
+ };
76
+ const {
77
+ result: {
78
+ current: { validity, isValid },
79
+ },
80
+ } = renderHook( () => useFormValidity( item, fields, form ) );
81
+ expect( validity ).toEqual( {
82
+ combinedField: {
83
+ children: {
84
+ order: {
85
+ required: { type: 'invalid' },
86
+ },
87
+ },
88
+ },
89
+ } );
90
+ expect( isValid ).toBe( false );
91
+ } );
92
+
93
+ it( 'without children but defined as objects are checked for validity', () => {
94
+ const item = { id: 1, order: undefined };
95
+ const fields: Field< {} >[] = [
96
+ {
97
+ id: 'order',
98
+ type: 'integer',
99
+ isValid: {
100
+ required: true,
101
+ },
102
+ },
103
+ ];
104
+ const form = {
105
+ fields: [ { id: 'order' } ],
106
+ };
107
+ const {
108
+ result: {
109
+ current: { validity, isValid },
110
+ },
111
+ } = renderHook( () => useFormValidity( item, fields, form ) );
112
+ expect( validity ).toEqual( {
113
+ order: {
114
+ required: { type: 'invalid' },
115
+ },
116
+ } );
117
+ expect( isValid ).toBe( false );
118
+ } );
119
+ } );
120
+
121
+ describe( 'isValid.required', () => {
122
+ const REQUIRED_MESSAGE = {
123
+ required: { type: 'invalid' },
124
+ };
125
+
126
+ it( 'is valid when validity object only contains type:valid messages', async () => {
127
+ const item = { id: 1, title: 'Valid Title', status: 'published' };
128
+ const fields: Field< {} >[] = [
129
+ {
130
+ id: 'title',
131
+ type: 'text',
132
+ isValid: {
133
+ custom: async () =>
134
+ await new Promise( ( resolve ) =>
135
+ setTimeout( resolve, 5 )
136
+ ).then( () => null ),
137
+ },
138
+ },
139
+ {
140
+ id: 'status',
141
+ type: 'text',
142
+ isValid: {
143
+ custom: async () =>
144
+ await new Promise( ( resolve ) =>
145
+ setTimeout( resolve, 5 )
146
+ ).then( () => null ),
147
+ },
148
+ },
149
+ ];
150
+ const form = { fields: [ 'title', 'status' ] };
151
+ const { result } = renderHook( () =>
152
+ useFormValidity( item, fields, form )
153
+ );
154
+
155
+ await waitFor( () => {
156
+ expect( result.current ).toEqual( {
157
+ validity: {
158
+ title: {
159
+ custom: { type: 'valid', message: 'Valid' },
160
+ },
161
+ status: {
162
+ custom: { type: 'valid', message: 'Valid' },
163
+ },
164
+ },
165
+ isValid: true,
166
+ } );
167
+ } );
168
+ } );
169
+
170
+ it( 'array is invalid when required but empty', () => {
171
+ const item = { id: 1, tags: [] };
172
+ const fields: Field< {} >[] = [
173
+ {
174
+ id: 'tags',
175
+ type: 'array',
176
+ isValid: {
177
+ required: true,
178
+ },
179
+ },
180
+ ];
181
+ const form = { fields: [ 'tags' ] };
182
+ const {
183
+ result: {
184
+ current: { validity, isValid },
185
+ },
186
+ } = renderHook( () => useFormValidity( item, fields, form ) );
187
+ expect( validity?.tags ).toEqual( REQUIRED_MESSAGE );
188
+ expect( isValid ).toBe( false );
189
+ } );
190
+
191
+ it( 'array is invalid when required but not an array', () => {
192
+ const item = { id: 1, tags: null };
193
+ const fields: Field< {} >[] = [
194
+ {
195
+ id: 'tags',
196
+ type: 'array',
197
+ isValid: {
198
+ required: true,
199
+ },
200
+ },
201
+ ];
202
+ const form = { fields: [ 'tags' ] };
203
+ const {
204
+ result: {
205
+ current: { validity, isValid },
206
+ },
207
+ } = renderHook( () => useFormValidity( item, fields, form ) );
208
+ expect( validity?.tags ).toEqual( REQUIRED_MESSAGE );
209
+ expect( isValid ).toBe( false );
210
+ } );
211
+
212
+ it( 'array is valid when required and has values', () => {
213
+ const item = { id: 1, tags: [ 'tag1', 'tag2' ] };
214
+ const fields: Field< {} >[] = [
215
+ {
216
+ id: 'tags',
217
+ type: 'array',
218
+ isValid: {
219
+ required: true,
220
+ },
221
+ },
222
+ ];
223
+ const form = { fields: [ 'tags' ] };
224
+ const {
225
+ result: {
226
+ current: { validity, isValid },
227
+ },
228
+ } = renderHook( () => useFormValidity( item, fields, form ) );
229
+ expect( validity ).toEqual( undefined );
230
+ expect( isValid ).toBe( true );
231
+ } );
232
+ } );
233
+
234
+ describe( 'isValid.elements', () => {
235
+ const ELEMENTS_MESSAGE = {
236
+ elements: {
237
+ type: 'invalid',
238
+ message: 'Value must be one of the elements.',
239
+ },
240
+ };
241
+ it( 'untyped is invalid if value is not one of the elements', () => {
242
+ const item = { id: 1, author: 'not-in-elements' };
243
+ const fields: Field< {} >[] = [
244
+ {
245
+ id: 'author',
246
+ elements: [
247
+ { value: 'jane', label: 'Jane' },
248
+ { value: 'john', label: 'John' },
249
+ ],
250
+ },
251
+ ];
252
+ const form = { fields: [ 'author' ] };
253
+ const {
254
+ result: {
255
+ current: { validity, isValid },
256
+ },
257
+ } = renderHook( () => useFormValidity( item, fields, form ) );
258
+ expect( validity?.author ).toEqual( ELEMENTS_MESSAGE );
259
+ expect( isValid ).toBe( false );
260
+ } );
261
+
262
+ it( 'text is valid when value is one of the elements', () => {
263
+ const item = { id: 1, status: 'published' };
264
+ const fields: Field< {} >[] = [
265
+ {
266
+ id: 'status',
267
+ type: 'text',
268
+ elements: [
269
+ { value: 'draft', label: 'Draft' },
270
+ { value: 'published', label: 'Published' },
271
+ ],
272
+ isValid: {
273
+ elements: true,
274
+ },
275
+ },
276
+ ];
277
+ const form = { fields: [ 'status' ] };
278
+ const {
279
+ result: {
280
+ current: { validity, isValid },
281
+ },
282
+ } = renderHook( () => useFormValidity( item, fields, form ) );
283
+ expect( validity ).toEqual( undefined );
284
+ expect( isValid ).toBe( true );
285
+ } );
286
+
287
+ it( 'text is invalid when value is not one of the elements', () => {
288
+ const item = { id: 1, status: 'invalid-status' };
289
+ const fields: Field< {} >[] = [
290
+ {
291
+ id: 'status',
292
+ type: 'text',
293
+ elements: [
294
+ { value: 'draft', label: 'Draft' },
295
+ { value: 'published', label: 'Published' },
296
+ ],
297
+ isValid: {
298
+ elements: true,
299
+ },
300
+ },
301
+ ];
302
+ const form = { fields: [ 'status' ] };
303
+ const {
304
+ result: {
305
+ current: { validity, isValid },
306
+ },
307
+ } = renderHook( () => useFormValidity( item, fields, form ) );
308
+ expect( validity?.status ).toEqual( ELEMENTS_MESSAGE );
309
+ expect( isValid ).toBe( false );
310
+ } );
311
+
312
+ it( 'integer is valid when value is one of the elements', () => {
313
+ const item = { id: 1, priority: 2 };
314
+ const fields: Field< {} >[] = [
315
+ {
316
+ id: 'priority',
317
+ type: 'integer',
318
+ elements: [
319
+ { value: 1, label: 'Low' },
320
+ { value: 2, label: 'Medium' },
321
+ { value: 3, label: 'High' },
322
+ ],
323
+ isValid: {
324
+ elements: true,
325
+ },
326
+ },
327
+ ];
328
+ const form = { fields: [ 'priority' ] };
329
+ const {
330
+ result: {
331
+ current: { validity, isValid },
332
+ },
333
+ } = renderHook( () => useFormValidity( item, fields, form ) );
334
+ expect( validity ).toEqual( undefined );
335
+ expect( isValid ).toBe( true );
336
+ } );
337
+
338
+ it( 'integer is invalid when value is not one of the elements', () => {
339
+ const item = { id: 1, priority: 5 };
340
+ const fields: Field< {} >[] = [
341
+ {
342
+ id: 'priority',
343
+ type: 'integer',
344
+ elements: [
345
+ { value: 1, label: 'Low' },
346
+ { value: 2, label: 'Medium' },
347
+ { value: 3, label: 'High' },
348
+ ],
349
+ isValid: {
350
+ elements: true,
351
+ },
352
+ },
353
+ ];
354
+ const form = { fields: [ 'priority' ] };
355
+ const {
356
+ result: {
357
+ current: { validity, isValid },
358
+ },
359
+ } = renderHook( () => useFormValidity( item, fields, form ) );
360
+ expect( validity?.priority ).toEqual( ELEMENTS_MESSAGE );
361
+ expect( isValid ).toBe( false );
362
+ } );
363
+
364
+ it( 'number is invalid if value is not one of the elements', () => {
365
+ const item = { id: 1, price: 4.5 };
366
+ const fields: Field< {} >[] = [
367
+ {
368
+ id: 'price',
369
+ type: 'number',
370
+ elements: [
371
+ { value: 1.5, label: 'Bronze' },
372
+ { value: 2.5, label: 'Silver' },
373
+ ],
374
+ },
375
+ ];
376
+ const form = { fields: [ 'price' ] };
377
+ const {
378
+ result: {
379
+ current: { validity, isValid },
380
+ },
381
+ } = renderHook( () => useFormValidity( item, fields, form ) );
382
+ expect( validity?.price ).toEqual( ELEMENTS_MESSAGE );
383
+ expect( isValid ).toBe( false );
384
+ } );
385
+
386
+ it( 'array is valid if all items are part of the elements', () => {
387
+ const item = { id: 1, tags: [ 'red', 'blue' ] };
388
+ const fields: Field< {} >[] = [
389
+ {
390
+ id: 'tags',
391
+ type: 'array',
392
+ elements: [
393
+ { value: 'red', label: 'Red' },
394
+ { value: 'blue', label: 'Blue' },
395
+ { value: 'green', label: 'Green' },
396
+ ],
397
+ },
398
+ ];
399
+ const form = { fields: [ 'tags' ] };
400
+ const {
401
+ result: {
402
+ current: { validity, isValid },
403
+ },
404
+ } = renderHook( () => useFormValidity( item, fields, form ) );
405
+ expect( validity ).toEqual( undefined );
406
+ expect( isValid ).toBe( true );
407
+ } );
408
+
409
+ it( 'array is invalid when not all items are part of the elements', () => {
410
+ const item = { id: 1, tags: [ 'red', 'yellow' ] };
411
+ const fields: Field< {} >[] = [
412
+ {
413
+ id: 'tags',
414
+ type: 'array',
415
+ elements: [
416
+ { value: 'red', label: 'Red' },
417
+ { value: 'blue', label: 'Blue' },
418
+ { value: 'green', label: 'Green' },
419
+ ],
420
+ },
421
+ ];
422
+ const form = { fields: [ 'tags' ] };
423
+ const {
424
+ result: {
425
+ current: { validity, isValid },
426
+ },
427
+ } = renderHook( () => useFormValidity( item, fields, form ) );
428
+ expect( validity?.tags ).toEqual( ELEMENTS_MESSAGE );
429
+ expect( isValid ).toBe( false );
430
+ } );
431
+
432
+ it( 'array is invalid when value is not an array', () => {
433
+ const item = { id: 1, tags: 'not-an-array' };
434
+ const fields: Field< {} >[] = [
435
+ {
436
+ id: 'tags',
437
+ type: 'array',
438
+ elements: [
439
+ { value: 'red', label: 'Red' },
440
+ { value: 'blue', label: 'Blue' },
441
+ ],
442
+ isValid: {
443
+ custom: () => null, // Disable to make sure the only validation triggered is elements
444
+ },
445
+ },
446
+ ];
447
+ const form = { fields: [ 'tags' ] };
448
+ const {
449
+ result: {
450
+ current: { validity, isValid },
451
+ },
452
+ } = renderHook( () => useFormValidity( item, fields, form ) );
453
+ expect( validity?.tags ).toEqual( {
454
+ elements: {
455
+ type: 'invalid',
456
+ message: 'Value must be an array.',
457
+ },
458
+ } );
459
+ expect( isValid ).toBe( false );
460
+ } );
461
+ } );
462
+
463
+ describe( 'isValid.custom', () => {
464
+ it( 'integer is valid if value is integer', () => {
465
+ const item = { id: 1, order: 2, title: 'hi' };
466
+ const fields: Field< {} >[] = [
467
+ {
468
+ type: 'integer',
469
+ id: 'order',
470
+ },
471
+ ];
472
+ const form = { fields: [ 'order' ] };
473
+ const {
474
+ result: {
475
+ current: { validity, isValid },
476
+ },
477
+ } = renderHook( () => useFormValidity( item, fields, form ) );
478
+ expect( validity ).toEqual( undefined );
479
+ expect( isValid ).toBe( true );
480
+ } );
481
+
482
+ it( 'integer is invalid if value is not integer when not empty', () => {
483
+ const item = { id: 1, order: 'd' };
484
+ const fields: Field< {} >[] = [
485
+ {
486
+ id: 'order',
487
+ type: 'integer',
488
+ },
489
+ ];
490
+ const form = { fields: [ 'order' ] };
491
+ const {
492
+ result: {
493
+ current: { validity, isValid },
494
+ },
495
+ } = renderHook( () => useFormValidity( item, fields, form ) );
496
+ expect( validity?.order ).toEqual( {
497
+ custom: {
498
+ type: 'invalid',
499
+ message: 'Value must be an integer.',
500
+ },
501
+ } );
502
+ expect( isValid ).toBe( false );
503
+ } );
504
+
505
+ it( 'number is valid if value is finite', () => {
506
+ const item = { id: 1, price: 2.5 };
507
+ const fields: Field< {} >[] = [
508
+ {
509
+ id: 'price',
510
+ type: 'number',
511
+ },
512
+ ];
513
+ const form = { fields: [ 'price' ] };
514
+ const {
515
+ result: {
516
+ current: { validity, isValid },
517
+ },
518
+ } = renderHook( () => useFormValidity( item, fields, form ) );
519
+ expect( validity ).toEqual( undefined );
520
+ expect( isValid ).toBe( true );
521
+ } );
522
+
523
+ it( 'number is invalid if value is not finite when not empty', () => {
524
+ const item = { id: 1, price: Number.NaN };
525
+ const fields: Field< {} >[] = [
526
+ {
527
+ id: 'price',
528
+ type: 'number',
529
+ },
530
+ ];
531
+ const form = { fields: [ 'price' ] };
532
+ const {
533
+ result: {
534
+ current: { validity, isValid },
535
+ },
536
+ } = renderHook( () => useFormValidity( item, fields, form ) );
537
+ expect( validity?.price ).toEqual( {
538
+ custom: {
539
+ type: 'invalid',
540
+ message: 'Value must be a number.',
541
+ },
542
+ } );
543
+ expect( isValid ).toBe( false );
544
+ } );
545
+ } );
546
+ } );
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Internal dependencies
3
3
  */
4
- import type { Field } from './field-api';
4
+ import type { Field, FieldValidity } from './field-api';
5
5
 
6
6
  /**
7
7
  * DataForm layouts.
@@ -130,11 +130,15 @@ export interface DataFormProps< Item > {
130
130
  fields: Field< Item >[];
131
131
  form: Form;
132
132
  onChange: ( value: Record< string, any > ) => void;
133
+ validity?: FormValidity;
133
134
  }
134
135
 
136
+ export type FormValidity = Record< string, FieldValidity > | undefined;
137
+
135
138
  export interface FieldLayoutProps< Item > {
136
139
  data: Item;
137
140
  field: FormField;
138
141
  onChange: ( value: any ) => void;
139
142
  hideLabelFromVision?: boolean;
143
+ validity?: FieldValidity;
140
144
  }
@@ -58,7 +58,17 @@ export interface NormalizedFilter {
58
58
  /**
59
59
  * The list of options to pick from when using the field as a filter.
60
60
  */
61
- elements: Option[];
61
+ elements?: Option[];
62
+
63
+ /**
64
+ * Retrieval function to get the elements.
65
+ */
66
+ getElements?: () => Promise< Option[] >;
67
+
68
+ /**
69
+ * Whether the filter has elements.
70
+ */
71
+ hasElements: boolean;
62
72
 
63
73
  /**
64
74
  * Is a single selection filter.
@@ -332,7 +342,7 @@ export interface ActionModal< Item > extends ActionBase< Item > {
332
342
  /**
333
343
  * The header of the modal.
334
344
  */
335
- modalHeader?: string;
345
+ modalHeader?: string | ( ( items: Item[] ) => string );
336
346
 
337
347
  /**
338
348
  * The size of the modal.
@@ -151,7 +151,12 @@ export type FieldTypeDefinition< Item > = {
151
151
  export type Rules< Item > = {
152
152
  required?: boolean;
153
153
  elements?: boolean;
154
- custom?: ( item: Item, field: NormalizedField< Item > ) => null | string;
154
+ custom?:
155
+ | ( ( item: Item, field: NormalizedField< Item > ) => null | string )
156
+ | ( (
157
+ item: Item,
158
+ field: NormalizedField< Item >
159
+ ) => Promise< null | string > );
155
160
  };
156
161
 
157
162
  /**
@@ -276,6 +281,11 @@ export type Field< Item > = {
276
281
  */
277
282
  elements?: Option[];
278
283
 
284
+ /**
285
+ * Retrieval function for elements.
286
+ */
287
+ getElements?: () => Promise< Option[] >;
288
+
279
289
  /**
280
290
  * Filter config for the field.
281
291
  */
@@ -307,6 +317,7 @@ export type NormalizedField< Item > = Omit< Field< Item >, 'Edit' > & {
307
317
  setValue: ( args: { item: Item; value: any } ) => DeepPartial< Item >;
308
318
  render: ComponentType< DataViewRenderFieldProps< Item > >;
309
319
  Edit: ComponentType< DataFormControlProps< Item > > | null;
320
+ hasElements: boolean;
310
321
  sort: ( a: Item, b: Item, direction: SortDirection ) => number;
311
322
  isValid: Rules< Item >;
312
323
  enableHiding: boolean;
@@ -320,6 +331,22 @@ export type NormalizedField< Item > = Omit< Field< Item >, 'Edit' > & {
320
331
  */
321
332
  export type Fields< Item > = Field< Item >[];
322
333
 
334
+ export type FieldValidity = {
335
+ required?: {
336
+ type: 'valid' | 'invalid' | 'validating';
337
+ message?: string;
338
+ };
339
+ elements?: {
340
+ type: 'valid' | 'invalid' | 'validating';
341
+ message: string;
342
+ };
343
+ custom?: {
344
+ type: 'valid' | 'invalid' | 'validating';
345
+ message: string;
346
+ };
347
+ children?: Record< string, FieldValidity >;
348
+ };
349
+
323
350
  export type DataFormControlProps< Item > = {
324
351
  data: Item;
325
352
  field: NormalizedField< Item >;
@@ -331,6 +358,10 @@ export type DataFormControlProps< Item > = {
331
358
  * Used by DataViews filters to determine which control to render based on the operator type.
332
359
  */
333
360
  operator?: Operator;
361
+ /**
362
+ * Validity information for the field, if any.
363
+ */
364
+ validity?: FieldValidity;
334
365
  /**
335
366
  * Configuration object for the control.
336
367
  */
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Internal dependencies
3
+ */
4
+ import type { Field } from '../types/field-api';
5
+
6
+ export default function hasElements< Item >( field: Field< Item > ): boolean {
7
+ return (
8
+ ( Array.isArray( field.elements ) && field.elements.length > 0 ) ||
9
+ typeof field.getElements === 'function'
10
+ );
11
+ }
@@ -20,6 +20,7 @@ import {
20
20
  OPERATOR_BETWEEN,
21
21
  SINGLE_SELECTION_OPERATORS,
22
22
  } from '../constants';
23
+ import hasElements from './has-elements';
23
24
 
24
25
  const getValueFromId =
25
26
  ( id: string ) =>
@@ -81,7 +82,7 @@ function getFilterBy< Item >(
81
82
  );
82
83
 
83
84
  // The `between` operator is not supported when elements are provided.
84
- if ( field.elements && operators.includes( OPERATOR_BETWEEN ) ) {
85
+ if ( hasElements( field ) && operators.includes( OPERATOR_BETWEEN ) ) {
85
86
  operators = operators.filter(
86
87
  ( operator ) => operator !== OPERATOR_BETWEEN
87
88
  );
@@ -119,7 +120,10 @@ function getFilterBy< Item >(
119
120
 
120
121
  let defaultOperators = fieldTypeDefinition.filterBy.defaultOperators;
121
122
  // The `between` operator is not supported when elements are provided.
122
- if ( field.elements && defaultOperators.includes( OPERATOR_BETWEEN ) ) {
123
+ if (
124
+ hasElements( field ) &&
125
+ defaultOperators.includes( OPERATOR_BETWEEN )
126
+ ) {
123
127
  defaultOperators = defaultOperators.filter(
124
128
  ( operator ) => operator !== OPERATOR_BETWEEN
125
129
  );
@@ -188,6 +192,7 @@ export default function normalizeFields< Item >(
188
192
  sort,
189
193
  isValid,
190
194
  Edit,
195
+ hasElements: hasElements( field ),
191
196
  enableHiding: field.enableHiding ?? true,
192
197
  enableSorting:
193
198
  field.enableSorting ??