@wordpress/dataviews 11.0.0 → 11.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 (303) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +140 -93
  3. package/build/components/dataviews-filters/filter.js +25 -267
  4. package/build/components/dataviews-filters/filter.js.map +2 -2
  5. package/build/components/dataviews-filters/input-widget.js +1 -4
  6. package/build/components/dataviews-filters/input-widget.js.map +2 -2
  7. package/build/components/dataviews-filters/use-filters.js +3 -3
  8. package/build/components/dataviews-filters/use-filters.js.map +2 -2
  9. package/build/constants.js +5 -142
  10. package/build/constants.js.map +2 -2
  11. package/build/dataform-controls/number.js +2 -1
  12. package/build/dataform-controls/number.js.map +2 -2
  13. package/build/dataform-controls/textarea.js +3 -1
  14. package/build/dataform-controls/textarea.js.map +2 -2
  15. package/build/dataform-controls/utils/get-custom-validity.js +8 -0
  16. package/build/dataform-controls/utils/get-custom-validity.js.map +2 -2
  17. package/build/dataform-controls/utils/validated-input.js +4 -2
  18. package/build/dataform-controls/utils/validated-input.js.map +2 -2
  19. package/build/dataform-controls/utils/validated-number.js +4 -2
  20. package/build/dataform-controls/utils/validated-number.js.map +2 -2
  21. package/build/dataform-layouts/panel/modal.js +14 -5
  22. package/build/dataform-layouts/panel/modal.js.map +2 -2
  23. package/build/dataviews-layouts/grid/composite-grid.js +39 -37
  24. package/build/dataviews-layouts/grid/composite-grid.js.map +3 -3
  25. package/build/dataviews-layouts/table/index.js +8 -3
  26. package/build/dataviews-layouts/table/index.js.map +2 -2
  27. package/build/field-types/array.js +27 -14
  28. package/build/field-types/array.js.map +3 -3
  29. package/build/field-types/boolean.js +13 -10
  30. package/build/field-types/boolean.js.map +3 -3
  31. package/build/field-types/color.js +14 -11
  32. package/build/field-types/color.js.map +3 -3
  33. package/build/field-types/date.js +11 -8
  34. package/build/field-types/date.js.map +3 -3
  35. package/build/field-types/datetime.js +7 -5
  36. package/build/field-types/datetime.js.map +3 -3
  37. package/build/field-types/email.js +20 -11
  38. package/build/field-types/email.js.map +3 -3
  39. package/build/field-types/index.js +12 -14
  40. package/build/field-types/index.js.map +3 -3
  41. package/build/field-types/integer.js +63 -14
  42. package/build/field-types/integer.js.map +3 -3
  43. package/build/field-types/media.js +5 -5
  44. package/build/field-types/media.js.map +2 -2
  45. package/build/field-types/no-type.js +9 -6
  46. package/build/field-types/no-type.js.map +3 -3
  47. package/build/field-types/number.js +51 -15
  48. package/build/field-types/number.js.map +3 -3
  49. package/build/field-types/password.js +13 -5
  50. package/build/field-types/password.js.map +3 -3
  51. package/build/field-types/telephone.js +13 -5
  52. package/build/field-types/telephone.js.map +3 -3
  53. package/build/field-types/text.js +13 -5
  54. package/build/field-types/text.js.map +3 -3
  55. package/build/field-types/url.js +13 -5
  56. package/build/field-types/url.js.map +3 -3
  57. package/build/field-types/utils/get-is-valid.js +89 -0
  58. package/build/field-types/utils/get-is-valid.js.map +7 -0
  59. package/build/field-types/utils/is-valid-elements.js +35 -0
  60. package/build/field-types/utils/is-valid-elements.js.map +7 -0
  61. package/build/field-types/utils/is-valid-max-length.js +36 -0
  62. package/build/field-types/utils/is-valid-max-length.js.map +7 -0
  63. package/build/field-types/utils/is-valid-max.js +36 -0
  64. package/build/field-types/utils/is-valid-max.js.map +7 -0
  65. package/build/field-types/utils/is-valid-min-length.js +36 -0
  66. package/build/field-types/utils/is-valid-min-length.js.map +7 -0
  67. package/build/field-types/utils/is-valid-min.js +36 -0
  68. package/build/field-types/utils/is-valid-min.js.map +7 -0
  69. package/build/field-types/utils/is-valid-pattern.js +41 -0
  70. package/build/field-types/utils/is-valid-pattern.js.map +7 -0
  71. package/build/field-types/utils/is-valid-required-for-array.js +32 -0
  72. package/build/field-types/utils/is-valid-required-for-array.js.map +7 -0
  73. package/build/field-types/utils/is-valid-required-for-bool.js +30 -0
  74. package/build/field-types/utils/is-valid-required-for-bool.js.map +7 -0
  75. package/build/field-types/utils/is-valid-required.js +30 -0
  76. package/build/field-types/utils/is-valid-required.js.map +7 -0
  77. package/build/hooks/use-form-validity.js +52 -102
  78. package/build/hooks/use-form-validity.js.map +2 -2
  79. package/build/types/field-api.js.map +1 -1
  80. package/build/types/private.js.map +1 -1
  81. package/build/utils/filter-sort-and-paginate.js +5 -0
  82. package/build/utils/filter-sort-and-paginate.js.map +3 -3
  83. package/build/utils/operators.js +399 -0
  84. package/build/utils/operators.js.map +7 -0
  85. package/build-module/components/dataviews-filters/filter.js +26 -292
  86. package/build-module/components/dataviews-filters/filter.js.map +2 -2
  87. package/build-module/components/dataviews-filters/input-widget.js +1 -4
  88. package/build-module/components/dataviews-filters/input-widget.js.map +2 -2
  89. package/build-module/components/dataviews-filters/use-filters.js +6 -3
  90. package/build-module/components/dataviews-filters/use-filters.js.map +2 -2
  91. package/build-module/constants.js +5 -139
  92. package/build-module/constants.js.map +2 -2
  93. package/build-module/dataform-controls/number.js +2 -1
  94. package/build-module/dataform-controls/number.js.map +2 -2
  95. package/build-module/dataform-controls/textarea.js +3 -1
  96. package/build-module/dataform-controls/textarea.js.map +2 -2
  97. package/build-module/dataform-controls/utils/get-custom-validity.js +8 -0
  98. package/build-module/dataform-controls/utils/get-custom-validity.js.map +2 -2
  99. package/build-module/dataform-controls/utils/validated-input.js +4 -2
  100. package/build-module/dataform-controls/utils/validated-input.js.map +2 -2
  101. package/build-module/dataform-controls/utils/validated-number.js +4 -2
  102. package/build-module/dataform-controls/utils/validated-number.js.map +2 -2
  103. package/build-module/dataform-layouts/panel/modal.js +14 -5
  104. package/build-module/dataform-layouts/panel/modal.js.map +2 -2
  105. package/build-module/dataviews-layouts/grid/composite-grid.js +40 -38
  106. package/build-module/dataviews-layouts/grid/composite-grid.js.map +3 -3
  107. package/build-module/dataviews-layouts/table/index.js +8 -3
  108. package/build-module/dataviews-layouts/table/index.js.map +2 -2
  109. package/build-module/field-types/array.js +17 -14
  110. package/build-module/field-types/array.js.map +2 -2
  111. package/build-module/field-types/boolean.js +13 -10
  112. package/build-module/field-types/boolean.js.map +2 -2
  113. package/build-module/field-types/color.js +14 -11
  114. package/build-module/field-types/color.js.map +2 -2
  115. package/build-module/field-types/date.js +11 -8
  116. package/build-module/field-types/date.js.map +2 -2
  117. package/build-module/field-types/datetime.js +7 -5
  118. package/build-module/field-types/datetime.js.map +2 -2
  119. package/build-module/field-types/email.js +20 -11
  120. package/build-module/field-types/email.js.map +2 -2
  121. package/build-module/field-types/index.js +12 -14
  122. package/build-module/field-types/index.js.map +2 -2
  123. package/build-module/field-types/integer.js +58 -13
  124. package/build-module/field-types/integer.js.map +2 -2
  125. package/build-module/field-types/media.js +5 -5
  126. package/build-module/field-types/media.js.map +2 -2
  127. package/build-module/field-types/no-type.js +10 -7
  128. package/build-module/field-types/no-type.js.map +2 -2
  129. package/build-module/field-types/number.js +47 -15
  130. package/build-module/field-types/number.js.map +2 -2
  131. package/build-module/field-types/password.js +13 -5
  132. package/build-module/field-types/password.js.map +2 -2
  133. package/build-module/field-types/telephone.js +13 -5
  134. package/build-module/field-types/telephone.js.map +2 -2
  135. package/build-module/field-types/text.js +13 -5
  136. package/build-module/field-types/text.js.map +2 -2
  137. package/build-module/field-types/url.js +13 -5
  138. package/build-module/field-types/url.js.map +2 -2
  139. package/build-module/field-types/utils/get-is-valid.js +68 -0
  140. package/build-module/field-types/utils/get-is-valid.js.map +7 -0
  141. package/build-module/field-types/utils/is-valid-elements.js +14 -0
  142. package/build-module/field-types/utils/is-valid-elements.js.map +7 -0
  143. package/build-module/field-types/utils/is-valid-max-length.js +15 -0
  144. package/build-module/field-types/utils/is-valid-max-length.js.map +7 -0
  145. package/build-module/field-types/utils/is-valid-max.js +15 -0
  146. package/build-module/field-types/utils/is-valid-max.js.map +7 -0
  147. package/build-module/field-types/utils/is-valid-min-length.js +15 -0
  148. package/build-module/field-types/utils/is-valid-min-length.js.map +7 -0
  149. package/build-module/field-types/utils/is-valid-min.js +15 -0
  150. package/build-module/field-types/utils/is-valid-min.js.map +7 -0
  151. package/build-module/field-types/utils/is-valid-pattern.js +20 -0
  152. package/build-module/field-types/utils/is-valid-pattern.js.map +7 -0
  153. package/build-module/field-types/utils/is-valid-required-for-array.js +11 -0
  154. package/build-module/field-types/utils/is-valid-required-for-array.js.map +7 -0
  155. package/build-module/field-types/utils/is-valid-required-for-bool.js +9 -0
  156. package/build-module/field-types/utils/is-valid-required-for-bool.js.map +7 -0
  157. package/build-module/field-types/utils/is-valid-required.js +9 -0
  158. package/build-module/field-types/utils/is-valid-required.js.map +7 -0
  159. package/build-module/hooks/use-form-validity.js +52 -102
  160. package/build-module/hooks/use-form-validity.js.map +2 -2
  161. package/build-module/utils/filter-sort-and-paginate.js +5 -0
  162. package/build-module/utils/filter-sort-and-paginate.js.map +2 -2
  163. package/build-module/utils/operators.js +394 -0
  164. package/build-module/utils/operators.js.map +7 -0
  165. package/build-style/style-rtl.css +13 -80
  166. package/build-style/style.css +13 -80
  167. package/build-types/components/dataviews-filters/filter.d.ts.map +1 -1
  168. package/build-types/components/dataviews-filters/input-widget.d.ts.map +1 -1
  169. package/build-types/components/dataviews-filters/use-filters.d.ts.map +1 -1
  170. package/build-types/constants.d.ts +6 -12
  171. package/build-types/constants.d.ts.map +1 -1
  172. package/build-types/dataform-controls/number.d.ts.map +1 -1
  173. package/build-types/dataform-controls/textarea.d.ts.map +1 -1
  174. package/build-types/dataform-controls/utils/get-custom-validity.d.ts +2 -2
  175. package/build-types/dataform-controls/utils/get-custom-validity.d.ts.map +1 -1
  176. package/build-types/dataform-controls/utils/validated-input.d.ts.map +1 -1
  177. package/build-types/dataform-controls/utils/validated-number.d.ts.map +1 -1
  178. package/build-types/dataform-layouts/panel/modal.d.ts.map +1 -1
  179. package/build-types/dataviews-layouts/grid/composite-grid.d.ts.map +1 -1
  180. package/build-types/dataviews-layouts/table/index.d.ts.map +1 -1
  181. package/build-types/field-types/array.d.ts +9 -2
  182. package/build-types/field-types/array.d.ts.map +1 -1
  183. package/build-types/field-types/boolean.d.ts +9 -2
  184. package/build-types/field-types/boolean.d.ts.map +1 -1
  185. package/build-types/field-types/color.d.ts +9 -2
  186. package/build-types/field-types/color.d.ts.map +1 -1
  187. package/build-types/field-types/date.d.ts +6 -4
  188. package/build-types/field-types/date.d.ts.map +1 -1
  189. package/build-types/field-types/datetime.d.ts +6 -4
  190. package/build-types/field-types/datetime.d.ts.map +1 -1
  191. package/build-types/field-types/email.d.ts +15 -2
  192. package/build-types/field-types/email.d.ts.map +1 -1
  193. package/build-types/field-types/index.d.ts.map +1 -1
  194. package/build-types/field-types/integer.d.ts +17 -4
  195. package/build-types/field-types/integer.d.ts.map +1 -1
  196. package/build-types/field-types/media.d.ts +1 -4
  197. package/build-types/field-types/media.d.ts.map +1 -1
  198. package/build-types/field-types/no-type.d.ts +6 -4
  199. package/build-types/field-types/no-type.d.ts.map +1 -1
  200. package/build-types/field-types/number.d.ts +17 -4
  201. package/build-types/field-types/number.d.ts.map +1 -1
  202. package/build-types/field-types/password.d.ts +12 -4
  203. package/build-types/field-types/password.d.ts.map +1 -1
  204. package/build-types/field-types/telephone.d.ts +12 -4
  205. package/build-types/field-types/telephone.d.ts.map +1 -1
  206. package/build-types/field-types/text.d.ts +12 -4
  207. package/build-types/field-types/text.d.ts.map +1 -1
  208. package/build-types/field-types/url.d.ts +12 -4
  209. package/build-types/field-types/url.d.ts.map +1 -1
  210. package/build-types/field-types/utils/get-is-valid.d.ts +7 -0
  211. package/build-types/field-types/utils/get-is-valid.d.ts.map +1 -0
  212. package/build-types/field-types/utils/is-valid-elements.d.ts +6 -0
  213. package/build-types/field-types/utils/is-valid-elements.d.ts.map +1 -0
  214. package/build-types/field-types/utils/is-valid-max-length.d.ts +6 -0
  215. package/build-types/field-types/utils/is-valid-max-length.d.ts.map +1 -0
  216. package/build-types/field-types/utils/is-valid-max.d.ts +6 -0
  217. package/build-types/field-types/utils/is-valid-max.d.ts.map +1 -0
  218. package/build-types/field-types/utils/is-valid-min-length.d.ts +6 -0
  219. package/build-types/field-types/utils/is-valid-min-length.d.ts.map +1 -0
  220. package/build-types/field-types/utils/is-valid-min.d.ts +6 -0
  221. package/build-types/field-types/utils/is-valid-min.d.ts.map +1 -0
  222. package/build-types/field-types/utils/is-valid-pattern.d.ts +6 -0
  223. package/build-types/field-types/utils/is-valid-pattern.d.ts.map +1 -0
  224. package/build-types/field-types/utils/is-valid-required-for-array.d.ts +6 -0
  225. package/build-types/field-types/utils/is-valid-required-for-array.d.ts.map +1 -0
  226. package/build-types/field-types/utils/is-valid-required-for-bool.d.ts +6 -0
  227. package/build-types/field-types/utils/is-valid-required-for-bool.d.ts.map +1 -0
  228. package/build-types/field-types/utils/is-valid-required.d.ts +6 -0
  229. package/build-types/field-types/utils/is-valid-required.d.ts.map +1 -0
  230. package/build-types/hooks/use-form-validity.d.ts.map +1 -1
  231. package/build-types/stories/dataform.story.d.ts +9 -1
  232. package/build-types/stories/dataform.story.d.ts.map +1 -1
  233. package/build-types/stories/dataviews-picker.story.d.ts.map +1 -1
  234. package/build-types/stories/dataviews.story.d.ts +27 -2
  235. package/build-types/stories/dataviews.story.d.ts.map +1 -1
  236. package/build-types/stories/field-types.story.d.ts +39 -2
  237. package/build-types/stories/field-types.story.d.ts.map +1 -1
  238. package/build-types/types/field-api.d.ts +72 -4
  239. package/build-types/types/field-api.d.ts.map +1 -1
  240. package/build-types/types/private.d.ts +13 -3
  241. package/build-types/types/private.d.ts.map +1 -1
  242. package/build-types/utils/filter-sort-and-paginate.d.ts.map +1 -1
  243. package/build-types/utils/operators.d.ts +16 -0
  244. package/build-types/utils/operators.d.ts.map +1 -0
  245. package/build-wp/index.js +1548 -1452
  246. package/package.json +17 -16
  247. package/src/components/dataviews/style.scss +3 -28
  248. package/src/components/dataviews-filters/filter.tsx +34 -321
  249. package/src/components/dataviews-filters/input-widget.tsx +7 -5
  250. package/src/components/dataviews-filters/use-filters.ts +6 -3
  251. package/src/components/dataviews-footer/style.scss +1 -7
  252. package/src/constants.ts +6 -140
  253. package/src/dataform-controls/number.tsx +3 -3
  254. package/src/dataform-controls/textarea.tsx +7 -1
  255. package/src/dataform-controls/utils/get-custom-validity.ts +10 -2
  256. package/src/dataform-controls/utils/validated-input.tsx +8 -2
  257. package/src/dataform-controls/utils/validated-number.tsx +3 -1
  258. package/src/dataform-layouts/panel/modal.tsx +14 -5
  259. package/src/dataviews-layouts/activity/style.scss +1 -1
  260. package/src/dataviews-layouts/grid/composite-grid.tsx +64 -57
  261. package/src/dataviews-layouts/grid/style.scss +3 -12
  262. package/src/dataviews-layouts/table/index.tsx +9 -3
  263. package/src/dataviews-layouts/table/style.scss +4 -15
  264. package/src/dataviews-layouts/utils/grid-items.scss +1 -9
  265. package/src/field-types/array.tsx +26 -19
  266. package/src/field-types/boolean.tsx +22 -15
  267. package/src/field-types/color.tsx +22 -15
  268. package/src/field-types/date.tsx +14 -11
  269. package/src/field-types/datetime.tsx +6 -4
  270. package/src/field-types/email.tsx +24 -15
  271. package/src/field-types/index.tsx +12 -14
  272. package/src/field-types/integer.tsx +83 -17
  273. package/src/field-types/media.tsx +4 -4
  274. package/src/field-types/no-type.tsx +9 -6
  275. package/src/field-types/number.tsx +82 -16
  276. package/src/field-types/password.tsx +12 -4
  277. package/src/field-types/telephone.tsx +12 -4
  278. package/src/field-types/text.tsx +12 -4
  279. package/src/field-types/url.tsx +12 -4
  280. package/src/field-types/utils/get-is-valid.ts +103 -0
  281. package/src/field-types/utils/is-valid-elements.ts +20 -0
  282. package/src/field-types/utils/is-valid-max-length.ts +23 -0
  283. package/src/field-types/utils/is-valid-max.ts +23 -0
  284. package/src/field-types/utils/is-valid-min-length.ts +23 -0
  285. package/src/field-types/utils/is-valid-min.ts +23 -0
  286. package/src/field-types/utils/is-valid-pattern.ts +29 -0
  287. package/src/field-types/utils/is-valid-required-for-array.ts +18 -0
  288. package/src/field-types/utils/is-valid-required-for-bool.ts +13 -0
  289. package/src/field-types/utils/is-valid-required.ts +13 -0
  290. package/src/hooks/use-form-validity.ts +78 -156
  291. package/src/stories/dataform.story.tsx +126 -30
  292. package/src/stories/dataviews-picker.story.tsx +27 -17
  293. package/src/stories/dataviews.story.tsx +79 -30
  294. package/src/stories/field-types.story.tsx +86 -4
  295. package/src/test/filter-sort-and-paginate.js +2 -1
  296. package/src/test/normalize-fields.ts +87 -11
  297. package/src/test/use-form-validity.ts +796 -31
  298. package/src/types/field-api.ts +90 -4
  299. package/src/types/private.ts +26 -8
  300. package/src/utils/filter-sort-and-paginate.ts +5 -0
  301. package/src/utils/operators.tsx +448 -0
  302. package/tsconfig.json +1 -0
  303. package/tsconfig.tsbuildinfo +1 -1
@@ -501,36 +501,6 @@ describe( 'useFormValidity', () => {
501
501
  expect( validity?.tags ).toEqual( ELEMENTS_MESSAGE );
502
502
  expect( isValid ).toBe( false );
503
503
  } );
504
-
505
- it( 'array is invalid when value is not an array', () => {
506
- const item = { id: 1, tags: 'not-an-array' };
507
- const fields: Field< {} >[] = [
508
- {
509
- id: 'tags',
510
- type: 'array',
511
- elements: [
512
- { value: 'red', label: 'Red' },
513
- { value: 'blue', label: 'Blue' },
514
- ],
515
- isValid: {
516
- custom: () => null, // Disable to make sure the only validation triggered is elements
517
- },
518
- },
519
- ];
520
- const form = { fields: [ 'tags' ] };
521
- const {
522
- result: {
523
- current: { validity, isValid },
524
- },
525
- } = renderHook( () => useFormValidity( item, fields, form ) );
526
- expect( validity?.tags ).toEqual( {
527
- elements: {
528
- type: 'invalid',
529
- message: 'Value must be an array.',
530
- },
531
- } );
532
- expect( isValid ).toBe( false );
533
- } );
534
504
  } );
535
505
 
536
506
  describe( 'isValid.pattern', () => {
@@ -792,13 +762,808 @@ describe( 'useFormValidity', () => {
792
762
  expect( validity?.username ).toEqual( {
793
763
  pattern: {
794
764
  type: 'invalid',
795
- message: 'Invalid pattern configuration.',
765
+ message: 'Value does not match the required pattern.',
796
766
  },
797
767
  } );
798
768
  expect( isValid ).toBe( false );
799
769
  } );
800
770
  } );
801
771
 
772
+ describe( 'isValid.min', () => {
773
+ const MIN_MESSAGE = {
774
+ min: {
775
+ type: 'invalid',
776
+ message: 'Value is below the minimum.',
777
+ },
778
+ };
779
+
780
+ it( 'integer is valid when value is at min', () => {
781
+ const item = { id: 1, quantity: 5 };
782
+ const fields: Field< {} >[] = [
783
+ {
784
+ id: 'quantity',
785
+ type: 'integer',
786
+ isValid: {
787
+ min: 5,
788
+ },
789
+ },
790
+ ];
791
+ const form = { fields: [ 'quantity' ] };
792
+ const {
793
+ result: {
794
+ current: { validity, isValid },
795
+ },
796
+ } = renderHook( () => useFormValidity( item, fields, form ) );
797
+ expect( validity ).toEqual( undefined );
798
+ expect( isValid ).toBe( true );
799
+ } );
800
+
801
+ it( 'integer is valid when value is above min', () => {
802
+ const item = { id: 1, quantity: 10 };
803
+ const fields: Field< {} >[] = [
804
+ {
805
+ id: 'quantity',
806
+ type: 'integer',
807
+ isValid: {
808
+ min: 5,
809
+ },
810
+ },
811
+ ];
812
+ const form = { fields: [ 'quantity' ] };
813
+ const {
814
+ result: {
815
+ current: { validity, isValid },
816
+ },
817
+ } = renderHook( () => useFormValidity( item, fields, form ) );
818
+ expect( validity ).toEqual( undefined );
819
+ expect( isValid ).toBe( true );
820
+ } );
821
+
822
+ it( 'integer is invalid when value is below min', () => {
823
+ const item = { id: 1, quantity: 3 };
824
+ const fields: Field< {} >[] = [
825
+ {
826
+ id: 'quantity',
827
+ type: 'integer',
828
+ isValid: {
829
+ min: 5,
830
+ },
831
+ },
832
+ ];
833
+ const form = { fields: [ 'quantity' ] };
834
+ const {
835
+ result: {
836
+ current: { validity, isValid },
837
+ },
838
+ } = renderHook( () => useFormValidity( item, fields, form ) );
839
+ expect( validity?.quantity ).toEqual( MIN_MESSAGE );
840
+ expect( isValid ).toBe( false );
841
+ } );
842
+
843
+ it( 'integer is valid when value is empty and min is defined', () => {
844
+ const item = { id: 1, quantity: undefined };
845
+ const fields: Field< {} >[] = [
846
+ {
847
+ id: 'quantity',
848
+ type: 'integer',
849
+ isValid: {
850
+ min: 5,
851
+ },
852
+ },
853
+ ];
854
+ const form = { fields: [ 'quantity' ] };
855
+ const {
856
+ result: {
857
+ current: { validity, isValid },
858
+ },
859
+ } = renderHook( () => useFormValidity( item, fields, form ) );
860
+ expect( validity ).toEqual( undefined );
861
+ expect( isValid ).toBe( true );
862
+ } );
863
+
864
+ it( 'number is valid when value is at or above min', () => {
865
+ const item = { id: 1, price: 9.99 };
866
+ const fields: Field< {} >[] = [
867
+ {
868
+ id: 'price',
869
+ type: 'number',
870
+ isValid: {
871
+ min: 5.5,
872
+ },
873
+ },
874
+ ];
875
+ const form = { fields: [ 'price' ] };
876
+ const {
877
+ result: {
878
+ current: { validity, isValid },
879
+ },
880
+ } = renderHook( () => useFormValidity( item, fields, form ) );
881
+ expect( validity ).toEqual( undefined );
882
+ expect( isValid ).toBe( true );
883
+ } );
884
+
885
+ it( 'number is invalid when value is below min', () => {
886
+ const item = { id: 1, price: 2.5 };
887
+ const fields: Field< {} >[] = [
888
+ {
889
+ id: 'price',
890
+ type: 'number',
891
+ isValid: {
892
+ min: 5.5,
893
+ },
894
+ },
895
+ ];
896
+ const form = { fields: [ 'price' ] };
897
+ const {
898
+ result: {
899
+ current: { validity, isValid },
900
+ },
901
+ } = renderHook( () => useFormValidity( item, fields, form ) );
902
+ expect( validity?.price ).toEqual( MIN_MESSAGE );
903
+ expect( isValid ).toBe( false );
904
+ } );
905
+ } );
906
+
907
+ describe( 'isValid.max', () => {
908
+ const MAX_MESSAGE = {
909
+ max: {
910
+ type: 'invalid',
911
+ message: 'Value is above the maximum.',
912
+ },
913
+ };
914
+
915
+ it( 'integer is valid when value is at max', () => {
916
+ const item = { id: 1, quantity: 100 };
917
+ const fields: Field< {} >[] = [
918
+ {
919
+ id: 'quantity',
920
+ type: 'integer',
921
+ isValid: {
922
+ max: 100,
923
+ },
924
+ },
925
+ ];
926
+ const form = { fields: [ 'quantity' ] };
927
+ const {
928
+ result: {
929
+ current: { validity, isValid },
930
+ },
931
+ } = renderHook( () => useFormValidity( item, fields, form ) );
932
+ expect( validity ).toEqual( undefined );
933
+ expect( isValid ).toBe( true );
934
+ } );
935
+
936
+ it( 'integer is valid when value is below max', () => {
937
+ const item = { id: 1, quantity: 50 };
938
+ const fields: Field< {} >[] = [
939
+ {
940
+ id: 'quantity',
941
+ type: 'integer',
942
+ isValid: {
943
+ max: 100,
944
+ },
945
+ },
946
+ ];
947
+ const form = { fields: [ 'quantity' ] };
948
+ const {
949
+ result: {
950
+ current: { validity, isValid },
951
+ },
952
+ } = renderHook( () => useFormValidity( item, fields, form ) );
953
+ expect( validity ).toEqual( undefined );
954
+ expect( isValid ).toBe( true );
955
+ } );
956
+
957
+ it( 'integer is invalid when value is above max', () => {
958
+ const item = { id: 1, quantity: 150 };
959
+ const fields: Field< {} >[] = [
960
+ {
961
+ id: 'quantity',
962
+ type: 'integer',
963
+ isValid: {
964
+ max: 100,
965
+ },
966
+ },
967
+ ];
968
+ const form = { fields: [ 'quantity' ] };
969
+ const {
970
+ result: {
971
+ current: { validity, isValid },
972
+ },
973
+ } = renderHook( () => useFormValidity( item, fields, form ) );
974
+ expect( validity?.quantity ).toEqual( MAX_MESSAGE );
975
+ expect( isValid ).toBe( false );
976
+ } );
977
+
978
+ it( 'integer is valid when value is empty and max is defined', () => {
979
+ const item = { id: 1, quantity: undefined };
980
+ const fields: Field< {} >[] = [
981
+ {
982
+ id: 'quantity',
983
+ type: 'integer',
984
+ isValid: {
985
+ max: 100,
986
+ },
987
+ },
988
+ ];
989
+ const form = { fields: [ 'quantity' ] };
990
+ const {
991
+ result: {
992
+ current: { validity, isValid },
993
+ },
994
+ } = renderHook( () => useFormValidity( item, fields, form ) );
995
+ expect( validity ).toEqual( undefined );
996
+ expect( isValid ).toBe( true );
997
+ } );
998
+
999
+ it( 'number is valid when value is at or below max', () => {
1000
+ const item = { id: 1, price: 99.99 };
1001
+ const fields: Field< {} >[] = [
1002
+ {
1003
+ id: 'price',
1004
+ type: 'number',
1005
+ isValid: {
1006
+ max: 100.0,
1007
+ },
1008
+ },
1009
+ ];
1010
+ const form = { fields: [ 'price' ] };
1011
+ const {
1012
+ result: {
1013
+ current: { validity, isValid },
1014
+ },
1015
+ } = renderHook( () => useFormValidity( item, fields, form ) );
1016
+ expect( validity ).toEqual( undefined );
1017
+ expect( isValid ).toBe( true );
1018
+ } );
1019
+
1020
+ it( 'number is invalid when value is above max', () => {
1021
+ const item = { id: 1, price: 150.5 };
1022
+ const fields: Field< {} >[] = [
1023
+ {
1024
+ id: 'price',
1025
+ type: 'number',
1026
+ isValid: {
1027
+ max: 100.0,
1028
+ },
1029
+ },
1030
+ ];
1031
+ const form = { fields: [ 'price' ] };
1032
+ const {
1033
+ result: {
1034
+ current: { validity, isValid },
1035
+ },
1036
+ } = renderHook( () => useFormValidity( item, fields, form ) );
1037
+ expect( validity?.price ).toEqual( MAX_MESSAGE );
1038
+ expect( isValid ).toBe( false );
1039
+ } );
1040
+ } );
1041
+
1042
+ describe( 'isValid.minLength', () => {
1043
+ const MIN_LENGTH_MESSAGE = {
1044
+ minLength: {
1045
+ type: 'invalid',
1046
+ message: 'Value is too short.',
1047
+ },
1048
+ };
1049
+
1050
+ it( 'text is valid when value length is at minLength', () => {
1051
+ const item = { id: 1, username: 'abcde' };
1052
+ const fields: Field< {} >[] = [
1053
+ {
1054
+ id: 'username',
1055
+ type: 'text',
1056
+ isValid: {
1057
+ minLength: 5,
1058
+ },
1059
+ },
1060
+ ];
1061
+ const form = { fields: [ 'username' ] };
1062
+ const {
1063
+ result: {
1064
+ current: { validity, isValid },
1065
+ },
1066
+ } = renderHook( () => useFormValidity( item, fields, form ) );
1067
+ expect( validity ).toEqual( undefined );
1068
+ expect( isValid ).toBe( true );
1069
+ } );
1070
+
1071
+ it( 'text is valid when value length is above minLength', () => {
1072
+ const item = { id: 1, username: 'abcdefghij' };
1073
+ const fields: Field< {} >[] = [
1074
+ {
1075
+ id: 'username',
1076
+ type: 'text',
1077
+ isValid: {
1078
+ minLength: 5,
1079
+ },
1080
+ },
1081
+ ];
1082
+ const form = { fields: [ 'username' ] };
1083
+ const {
1084
+ result: {
1085
+ current: { validity, isValid },
1086
+ },
1087
+ } = renderHook( () => useFormValidity( item, fields, form ) );
1088
+ expect( validity ).toEqual( undefined );
1089
+ expect( isValid ).toBe( true );
1090
+ } );
1091
+
1092
+ it( 'text is invalid when value length is below minLength', () => {
1093
+ const item = { id: 1, username: 'abc' };
1094
+ const fields: Field< {} >[] = [
1095
+ {
1096
+ id: 'username',
1097
+ type: 'text',
1098
+ isValid: {
1099
+ minLength: 5,
1100
+ },
1101
+ },
1102
+ ];
1103
+ const form = { fields: [ 'username' ] };
1104
+ const {
1105
+ result: {
1106
+ current: { validity, isValid },
1107
+ },
1108
+ } = renderHook( () => useFormValidity( item, fields, form ) );
1109
+ expect( validity?.username ).toEqual( MIN_LENGTH_MESSAGE );
1110
+ expect( isValid ).toBe( false );
1111
+ } );
1112
+
1113
+ it( 'text is valid when value is empty and minLength is defined', () => {
1114
+ const item = { id: 1, username: '' };
1115
+ const fields: Field< {} >[] = [
1116
+ {
1117
+ id: 'username',
1118
+ type: 'text',
1119
+ isValid: {
1120
+ minLength: 5,
1121
+ },
1122
+ },
1123
+ ];
1124
+ const form = { fields: [ 'username' ] };
1125
+ const {
1126
+ result: {
1127
+ current: { validity, isValid },
1128
+ },
1129
+ } = renderHook( () => useFormValidity( item, fields, form ) );
1130
+ expect( validity ).toEqual( undefined );
1131
+ expect( isValid ).toBe( true );
1132
+ } );
1133
+
1134
+ it( 'email is valid when value length meets minLength', () => {
1135
+ const item = { id: 1, email: 'user@example.com' };
1136
+ const fields: Field< {} >[] = [
1137
+ {
1138
+ id: 'email',
1139
+ type: 'email',
1140
+ isValid: {
1141
+ minLength: 10,
1142
+ },
1143
+ },
1144
+ ];
1145
+ const form = { fields: [ 'email' ] };
1146
+ const {
1147
+ result: {
1148
+ current: { validity, isValid },
1149
+ },
1150
+ } = renderHook( () => useFormValidity( item, fields, form ) );
1151
+ expect( validity ).toEqual( undefined );
1152
+ expect( isValid ).toBe( true );
1153
+ } );
1154
+
1155
+ it( 'email is invalid when value length is below minLength', () => {
1156
+ const item = { id: 1, email: 'a@b.co' };
1157
+ const fields: Field< {} >[] = [
1158
+ {
1159
+ id: 'email',
1160
+ type: 'email',
1161
+ isValid: {
1162
+ minLength: 10,
1163
+ },
1164
+ },
1165
+ ];
1166
+ const form = { fields: [ 'email' ] };
1167
+ const {
1168
+ result: {
1169
+ current: { validity, isValid },
1170
+ },
1171
+ } = renderHook( () => useFormValidity( item, fields, form ) );
1172
+ expect( validity?.email ).toEqual( MIN_LENGTH_MESSAGE );
1173
+ expect( isValid ).toBe( false );
1174
+ } );
1175
+
1176
+ it( 'url is valid when value length meets minLength', () => {
1177
+ const item = { id: 1, website: 'https://example.com' };
1178
+ const fields: Field< {} >[] = [
1179
+ {
1180
+ id: 'website',
1181
+ type: 'url',
1182
+ isValid: {
1183
+ minLength: 10,
1184
+ },
1185
+ },
1186
+ ];
1187
+ const form = { fields: [ 'website' ] };
1188
+ const {
1189
+ result: {
1190
+ current: { validity, isValid },
1191
+ },
1192
+ } = renderHook( () => useFormValidity( item, fields, form ) );
1193
+ expect( validity ).toEqual( undefined );
1194
+ expect( isValid ).toBe( true );
1195
+ } );
1196
+
1197
+ it( 'url is invalid when value length is below minLength', () => {
1198
+ const item = { id: 1, website: 'http://a' };
1199
+ const fields: Field< {} >[] = [
1200
+ {
1201
+ id: 'website',
1202
+ type: 'url',
1203
+ isValid: {
1204
+ minLength: 15,
1205
+ },
1206
+ },
1207
+ ];
1208
+ const form = { fields: [ 'website' ] };
1209
+ const {
1210
+ result: {
1211
+ current: { validity, isValid },
1212
+ },
1213
+ } = renderHook( () => useFormValidity( item, fields, form ) );
1214
+ expect( validity?.website ).toEqual( MIN_LENGTH_MESSAGE );
1215
+ expect( isValid ).toBe( false );
1216
+ } );
1217
+
1218
+ it( 'telephone is valid when value length meets minLength', () => {
1219
+ const item = { id: 1, phone: '+1-555-123-4567' };
1220
+ const fields: Field< {} >[] = [
1221
+ {
1222
+ id: 'phone',
1223
+ type: 'telephone',
1224
+ isValid: {
1225
+ minLength: 10,
1226
+ },
1227
+ },
1228
+ ];
1229
+ const form = { fields: [ 'phone' ] };
1230
+ const {
1231
+ result: {
1232
+ current: { validity, isValid },
1233
+ },
1234
+ } = renderHook( () => useFormValidity( item, fields, form ) );
1235
+ expect( validity ).toEqual( undefined );
1236
+ expect( isValid ).toBe( true );
1237
+ } );
1238
+
1239
+ it( 'telephone is invalid when value length is below minLength', () => {
1240
+ const item = { id: 1, phone: '555' };
1241
+ const fields: Field< {} >[] = [
1242
+ {
1243
+ id: 'phone',
1244
+ type: 'telephone',
1245
+ isValid: {
1246
+ minLength: 10,
1247
+ },
1248
+ },
1249
+ ];
1250
+ const form = { fields: [ 'phone' ] };
1251
+ const {
1252
+ result: {
1253
+ current: { validity, isValid },
1254
+ },
1255
+ } = renderHook( () => useFormValidity( item, fields, form ) );
1256
+ expect( validity?.phone ).toEqual( MIN_LENGTH_MESSAGE );
1257
+ expect( isValid ).toBe( false );
1258
+ } );
1259
+
1260
+ it( 'password is valid when value length meets minLength', () => {
1261
+ const item = { id: 1, password: 'securepassword123' };
1262
+ const fields: Field< {} >[] = [
1263
+ {
1264
+ id: 'password',
1265
+ type: 'password',
1266
+ isValid: {
1267
+ minLength: 8,
1268
+ },
1269
+ },
1270
+ ];
1271
+ const form = { fields: [ 'password' ] };
1272
+ const {
1273
+ result: {
1274
+ current: { validity, isValid },
1275
+ },
1276
+ } = renderHook( () => useFormValidity( item, fields, form ) );
1277
+ expect( validity ).toEqual( undefined );
1278
+ expect( isValid ).toBe( true );
1279
+ } );
1280
+
1281
+ it( 'password is invalid when value length is below minLength', () => {
1282
+ const item = { id: 1, password: 'short' };
1283
+ const fields: Field< {} >[] = [
1284
+ {
1285
+ id: 'password',
1286
+ type: 'password',
1287
+ isValid: {
1288
+ minLength: 8,
1289
+ },
1290
+ },
1291
+ ];
1292
+ const form = { fields: [ 'password' ] };
1293
+ const {
1294
+ result: {
1295
+ current: { validity, isValid },
1296
+ },
1297
+ } = renderHook( () => useFormValidity( item, fields, form ) );
1298
+ expect( validity?.password ).toEqual( MIN_LENGTH_MESSAGE );
1299
+ expect( isValid ).toBe( false );
1300
+ } );
1301
+ } );
1302
+
1303
+ describe( 'isValid.maxLength', () => {
1304
+ const MAX_LENGTH_MESSAGE = {
1305
+ maxLength: {
1306
+ type: 'invalid',
1307
+ message: 'Value is too long.',
1308
+ },
1309
+ };
1310
+
1311
+ it( 'text is valid when value length is at maxLength', () => {
1312
+ const item = { id: 1, username: 'abcdefghij' };
1313
+ const fields: Field< {} >[] = [
1314
+ {
1315
+ id: 'username',
1316
+ type: 'text',
1317
+ isValid: {
1318
+ maxLength: 10,
1319
+ },
1320
+ },
1321
+ ];
1322
+ const form = { fields: [ 'username' ] };
1323
+ const {
1324
+ result: {
1325
+ current: { validity, isValid },
1326
+ },
1327
+ } = renderHook( () => useFormValidity( item, fields, form ) );
1328
+ expect( validity ).toEqual( undefined );
1329
+ expect( isValid ).toBe( true );
1330
+ } );
1331
+
1332
+ it( 'text is valid when value length is below maxLength', () => {
1333
+ const item = { id: 1, username: 'abc' };
1334
+ const fields: Field< {} >[] = [
1335
+ {
1336
+ id: 'username',
1337
+ type: 'text',
1338
+ isValid: {
1339
+ maxLength: 10,
1340
+ },
1341
+ },
1342
+ ];
1343
+ const form = { fields: [ 'username' ] };
1344
+ const {
1345
+ result: {
1346
+ current: { validity, isValid },
1347
+ },
1348
+ } = renderHook( () => useFormValidity( item, fields, form ) );
1349
+ expect( validity ).toEqual( undefined );
1350
+ expect( isValid ).toBe( true );
1351
+ } );
1352
+
1353
+ it( 'text is invalid when value length is above maxLength', () => {
1354
+ const item = { id: 1, username: 'abcdefghijklmnop' };
1355
+ const fields: Field< {} >[] = [
1356
+ {
1357
+ id: 'username',
1358
+ type: 'text',
1359
+ isValid: {
1360
+ maxLength: 10,
1361
+ },
1362
+ },
1363
+ ];
1364
+ const form = { fields: [ 'username' ] };
1365
+ const {
1366
+ result: {
1367
+ current: { validity, isValid },
1368
+ },
1369
+ } = renderHook( () => useFormValidity( item, fields, form ) );
1370
+ expect( validity?.username ).toEqual( MAX_LENGTH_MESSAGE );
1371
+ expect( isValid ).toBe( false );
1372
+ } );
1373
+
1374
+ it( 'text is valid when value is empty and maxLength is defined', () => {
1375
+ const item = { id: 1, username: '' };
1376
+ const fields: Field< {} >[] = [
1377
+ {
1378
+ id: 'username',
1379
+ type: 'text',
1380
+ isValid: {
1381
+ maxLength: 10,
1382
+ },
1383
+ },
1384
+ ];
1385
+ const form = { fields: [ 'username' ] };
1386
+ const {
1387
+ result: {
1388
+ current: { validity, isValid },
1389
+ },
1390
+ } = renderHook( () => useFormValidity( item, fields, form ) );
1391
+ expect( validity ).toEqual( undefined );
1392
+ expect( isValid ).toBe( true );
1393
+ } );
1394
+
1395
+ it( 'email is valid when value length meets maxLength', () => {
1396
+ const item = { id: 1, email: 'user@example.com' };
1397
+ const fields: Field< {} >[] = [
1398
+ {
1399
+ id: 'email',
1400
+ type: 'email',
1401
+ isValid: {
1402
+ maxLength: 50,
1403
+ },
1404
+ },
1405
+ ];
1406
+ const form = { fields: [ 'email' ] };
1407
+ const {
1408
+ result: {
1409
+ current: { validity, isValid },
1410
+ },
1411
+ } = renderHook( () => useFormValidity( item, fields, form ) );
1412
+ expect( validity ).toEqual( undefined );
1413
+ expect( isValid ).toBe( true );
1414
+ } );
1415
+
1416
+ it( 'email is invalid when value length is above maxLength', () => {
1417
+ const item = { id: 1, email: 'verylongemailaddress@example.com' };
1418
+ const fields: Field< {} >[] = [
1419
+ {
1420
+ id: 'email',
1421
+ type: 'email',
1422
+ isValid: {
1423
+ maxLength: 20,
1424
+ },
1425
+ },
1426
+ ];
1427
+ const form = { fields: [ 'email' ] };
1428
+ const {
1429
+ result: {
1430
+ current: { validity, isValid },
1431
+ },
1432
+ } = renderHook( () => useFormValidity( item, fields, form ) );
1433
+ expect( validity?.email ).toEqual( MAX_LENGTH_MESSAGE );
1434
+ expect( isValid ).toBe( false );
1435
+ } );
1436
+
1437
+ it( 'url is valid when value length meets maxLength', () => {
1438
+ const item = { id: 1, website: 'https://example.com' };
1439
+ const fields: Field< {} >[] = [
1440
+ {
1441
+ id: 'website',
1442
+ type: 'url',
1443
+ isValid: {
1444
+ maxLength: 50,
1445
+ },
1446
+ },
1447
+ ];
1448
+ const form = { fields: [ 'website' ] };
1449
+ const {
1450
+ result: {
1451
+ current: { validity, isValid },
1452
+ },
1453
+ } = renderHook( () => useFormValidity( item, fields, form ) );
1454
+ expect( validity ).toEqual( undefined );
1455
+ expect( isValid ).toBe( true );
1456
+ } );
1457
+
1458
+ it( 'url is invalid when value length is above maxLength', () => {
1459
+ const item = {
1460
+ id: 1,
1461
+ website: 'https://verylongdomainname.example.com/path',
1462
+ };
1463
+ const fields: Field< {} >[] = [
1464
+ {
1465
+ id: 'website',
1466
+ type: 'url',
1467
+ isValid: {
1468
+ maxLength: 30,
1469
+ },
1470
+ },
1471
+ ];
1472
+ const form = { fields: [ 'website' ] };
1473
+ const {
1474
+ result: {
1475
+ current: { validity, isValid },
1476
+ },
1477
+ } = renderHook( () => useFormValidity( item, fields, form ) );
1478
+ expect( validity?.website ).toEqual( MAX_LENGTH_MESSAGE );
1479
+ expect( isValid ).toBe( false );
1480
+ } );
1481
+
1482
+ it( 'telephone is valid when value length meets maxLength', () => {
1483
+ const item = { id: 1, phone: '+1-555-123-4567' };
1484
+ const fields: Field< {} >[] = [
1485
+ {
1486
+ id: 'phone',
1487
+ type: 'telephone',
1488
+ isValid: {
1489
+ maxLength: 20,
1490
+ },
1491
+ },
1492
+ ];
1493
+ const form = { fields: [ 'phone' ] };
1494
+ const {
1495
+ result: {
1496
+ current: { validity, isValid },
1497
+ },
1498
+ } = renderHook( () => useFormValidity( item, fields, form ) );
1499
+ expect( validity ).toEqual( undefined );
1500
+ expect( isValid ).toBe( true );
1501
+ } );
1502
+
1503
+ it( 'telephone is invalid when value length is above maxLength', () => {
1504
+ const item = { id: 1, phone: '+1-555-123-4567-extension-12345' };
1505
+ const fields: Field< {} >[] = [
1506
+ {
1507
+ id: 'phone',
1508
+ type: 'telephone',
1509
+ isValid: {
1510
+ maxLength: 15,
1511
+ },
1512
+ },
1513
+ ];
1514
+ const form = { fields: [ 'phone' ] };
1515
+ const {
1516
+ result: {
1517
+ current: { validity, isValid },
1518
+ },
1519
+ } = renderHook( () => useFormValidity( item, fields, form ) );
1520
+ expect( validity?.phone ).toEqual( MAX_LENGTH_MESSAGE );
1521
+ expect( isValid ).toBe( false );
1522
+ } );
1523
+
1524
+ it( 'password is valid when value length meets maxLength', () => {
1525
+ const item = { id: 1, password: 'secure123' };
1526
+ const fields: Field< {} >[] = [
1527
+ {
1528
+ id: 'password',
1529
+ type: 'password',
1530
+ isValid: {
1531
+ maxLength: 20,
1532
+ },
1533
+ },
1534
+ ];
1535
+ const form = { fields: [ 'password' ] };
1536
+ const {
1537
+ result: {
1538
+ current: { validity, isValid },
1539
+ },
1540
+ } = renderHook( () => useFormValidity( item, fields, form ) );
1541
+ expect( validity ).toEqual( undefined );
1542
+ expect( isValid ).toBe( true );
1543
+ } );
1544
+
1545
+ it( 'password is invalid when value length is above maxLength', () => {
1546
+ const item = { id: 1, password: 'verylongsecurepassword123456' };
1547
+ const fields: Field< {} >[] = [
1548
+ {
1549
+ id: 'password',
1550
+ type: 'password',
1551
+ isValid: {
1552
+ maxLength: 20,
1553
+ },
1554
+ },
1555
+ ];
1556
+ const form = { fields: [ 'password' ] };
1557
+ const {
1558
+ result: {
1559
+ current: { validity, isValid },
1560
+ },
1561
+ } = renderHook( () => useFormValidity( item, fields, form ) );
1562
+ expect( validity?.password ).toEqual( MAX_LENGTH_MESSAGE );
1563
+ expect( isValid ).toBe( false );
1564
+ } );
1565
+ } );
1566
+
802
1567
  describe( 'isValid.custom', () => {
803
1568
  it( 'integer is valid if value is integer', () => {
804
1569
  const item = { id: 1, order: 2, title: 'hi' };