@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
@@ -80,6 +80,10 @@ export type Rules< Item > = {
80
80
  required?: boolean;
81
81
  elements?: boolean;
82
82
  pattern?: string;
83
+ minLength?: number;
84
+ maxLength?: number;
85
+ min?: number;
86
+ max?: number;
83
87
  custom?:
84
88
  | ( ( item: Item, field: NormalizedField< Item > ) => null | string )
85
89
  | ( (
@@ -88,6 +92,34 @@ export type Rules< Item > = {
88
92
  ) => Promise< null | string > );
89
93
  };
90
94
 
95
+ export type Validator< Item > = (
96
+ item: Item,
97
+ field: NormalizedField< Item >
98
+ ) => boolean;
99
+
100
+ export type CustomValidator< Item > =
101
+ | ( ( item: Item, field: NormalizedField< Item > ) => null | string )
102
+ | ( (
103
+ item: Item,
104
+ field: NormalizedField< Item >
105
+ ) => Promise< null | string > );
106
+
107
+ type NormalizedRule< Item, ConstraintType > = {
108
+ constraint: ConstraintType;
109
+ validate: Validator< Item >;
110
+ };
111
+
112
+ export type NormalizedRules< Item > = {
113
+ required?: NormalizedRule< Item, boolean >;
114
+ elements?: NormalizedRule< Item, boolean >;
115
+ pattern?: NormalizedRule< Item, string >;
116
+ minLength?: NormalizedRule< Item, number >;
117
+ maxLength?: NormalizedRule< Item, number >;
118
+ min?: NormalizedRule< Item, number >;
119
+ max?: NormalizedRule< Item, number >;
120
+ custom?: CustomValidator< Item >;
121
+ };
122
+
91
123
  /**
92
124
  * Edit configuration for textarea controls.
93
125
  */
@@ -241,7 +273,7 @@ export type Field< Item > = {
241
273
  /**
242
274
  * Display format configuration for fields.
243
275
  */
244
- format?: FormatDate;
276
+ format?: FormatDate | FormatNumber | FormatInteger;
245
277
  };
246
278
 
247
279
  /**
@@ -258,7 +290,33 @@ export type FormatDate = {
258
290
  };
259
291
  export type DayNumber = 0 | 1 | 2 | 3 | 4 | 5 | 6;
260
292
 
261
- type NormalizedFieldBase< Item > = Omit< Field< Item >, 'Edit' > & {
293
+ /**
294
+ * Format for number fields:
295
+ *
296
+ * - separatorThousand: character to use for thousand separators (e.g., ',')
297
+ * - separatorDecimal: character to use for decimal point (e.g., '.')
298
+ * - decimals: number of decimal places to display (e.g., 2)
299
+ *
300
+ * If not provided, defaults to ',' for thousands, '.' for decimal, 2 decimals.
301
+ */
302
+ export type FormatNumber = {
303
+ separatorThousand?: string;
304
+ separatorDecimal?: string;
305
+ decimals?: number;
306
+ };
307
+
308
+ /**
309
+ * Format for integer fields:
310
+ *
311
+ * - separatorThousand: character to use for thousand separators (e.g., ',')
312
+ *
313
+ * If not provided, defaults to ',' for thousands.
314
+ */
315
+ export type FormatInteger = {
316
+ separatorThousand?: string;
317
+ };
318
+
319
+ type NormalizedFieldBase< Item > = Omit< Field< Item >, 'Edit' | 'isValid' > & {
262
320
  label: string;
263
321
  header: string | ReactElement;
264
322
  getValue: ( args: { item: Item } ) => any;
@@ -267,7 +325,7 @@ type NormalizedFieldBase< Item > = Omit< Field< Item >, 'Edit' > & {
267
325
  Edit: ComponentType< DataFormControlProps< Item > > | null;
268
326
  hasElements: boolean;
269
327
  sort: ( a: Item, b: Item, direction: SortDirection ) => number;
270
- isValid: Rules< Item >;
328
+ isValid: NormalizedRules< Item >;
271
329
  enableHiding: boolean;
272
330
  enableSorting: boolean;
273
331
  filterBy: Required< FilterByConfig > | false;
@@ -280,9 +338,21 @@ export type NormalizedFieldDate< Item > = NormalizedFieldBase< Item > & {
280
338
  format: Required< FormatDate >;
281
339
  };
282
340
 
341
+ export type NormalizedFieldNumber< Item > = NormalizedFieldBase< Item > & {
342
+ type: 'number';
343
+ format: Required< FormatNumber >;
344
+ };
345
+
346
+ export type NormalizedFieldInteger< Item > = NormalizedFieldBase< Item > & {
347
+ type: 'integer';
348
+ format: Required< FormatInteger >;
349
+ };
350
+
283
351
  export type NormalizedField< Item > =
284
352
  | NormalizedFieldBase< Item >
285
- | NormalizedFieldDate< Item >;
353
+ | NormalizedFieldDate< Item >
354
+ | NormalizedFieldNumber< Item >
355
+ | NormalizedFieldInteger< Item >;
286
356
 
287
357
  /**
288
358
  * A collection of dataview fields for a data type.
@@ -298,6 +368,22 @@ export type FieldValidity = {
298
368
  type: 'valid' | 'invalid' | 'validating';
299
369
  message: string;
300
370
  };
371
+ min?: {
372
+ type: 'valid' | 'invalid' | 'validating';
373
+ message: string;
374
+ };
375
+ max?: {
376
+ type: 'valid' | 'invalid' | 'validating';
377
+ message: string;
378
+ };
379
+ minLength?: {
380
+ type: 'valid' | 'invalid' | 'validating';
381
+ message: string;
382
+ };
383
+ maxLength?: {
384
+ type: 'valid' | 'invalid' | 'validating';
385
+ message: string;
386
+ };
301
387
  elements?: {
302
388
  type: 'valid' | 'invalid' | 'validating';
303
389
  message: string;
@@ -1,23 +1,41 @@
1
1
  /**
2
2
  * Internal dependencies
3
3
  */
4
- import type { Field, FormatDate, NormalizedField, Operator } from './field-api';
4
+ import type {
5
+ CustomValidator,
6
+ Field,
7
+ FormatDate,
8
+ FormatInteger,
9
+ FormatNumber,
10
+ NormalizedField,
11
+ Operator,
12
+ Validator,
13
+ } from './field-api';
5
14
 
6
15
  export type SelectionOrUpdater = string[] | ( ( prev: string[] ) => string[] );
7
16
  export type SetSelection = ( selection: SelectionOrUpdater ) => void;
8
17
  export type FieldType< Item > = Pick<
9
18
  NormalizedField< Item >,
10
- | 'type'
11
- | 'render'
12
- | 'sort'
13
- | 'isValid'
14
- | 'enableSorting'
15
- | 'enableGlobalSearch'
19
+ 'type' | 'render' | 'sort' | 'enableSorting' | 'enableGlobalSearch'
16
20
  > & {
17
21
  Edit: string | null;
18
22
  validOperators: Operator[];
19
23
  defaultOperators: Operator[];
20
24
  getFormat: (
21
25
  field: Field< Item >
22
- ) => Record< string, any > | Required< FormatDate >;
26
+ ) =>
27
+ | Record< string, any >
28
+ | Required< FormatDate >
29
+ | Required< FormatNumber >
30
+ | Required< FormatInteger >;
31
+ validate: {
32
+ required?: Validator< Item >;
33
+ elements?: Validator< Item >;
34
+ pattern?: Validator< Item >;
35
+ minLength?: Validator< Item >;
36
+ maxLength?: Validator< Item >;
37
+ min?: Validator< Item >;
38
+ max?: Validator< Item >;
39
+ custom?: CustomValidator< Item >;
40
+ };
23
41
  };
@@ -7,6 +7,7 @@ import { subDays, subWeeks, subMonths, subYears } from 'date-fns';
7
7
  /**
8
8
  * WordPress dependencies
9
9
  */
10
+ import deprecated from '@wordpress/deprecated';
10
11
  import { getDate } from '@wordpress/date';
11
12
 
12
13
  /**
@@ -163,6 +164,10 @@ export default function filterSortAndPaginate< Item >(
163
164
  filter.operator === OPERATOR_IS_NOT_ALL &&
164
165
  filter?.value?.length > 0
165
166
  ) {
167
+ deprecated( "The 'isNotAll' filter operator", {
168
+ since: '7.0',
169
+ alternative: "'isNone'",
170
+ } );
166
171
  filteredData = filteredData.filter( ( item ) => {
167
172
  return filter.value.every( ( value: any ) => {
168
173
  return ! field
@@ -0,0 +1,448 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { __, sprintf } from '@wordpress/i18n';
5
+ import { createInterpolateElement } from '@wordpress/element';
6
+ import type { ReactElement } from 'react';
7
+
8
+ /**
9
+ * Internal dependencies
10
+ */
11
+ import type { NormalizedFilter, Operator, Option } from '../types';
12
+ import {
13
+ OPERATOR_AFTER,
14
+ OPERATOR_AFTER_INC,
15
+ OPERATOR_BEFORE,
16
+ OPERATOR_BEFORE_INC,
17
+ OPERATOR_BETWEEN,
18
+ OPERATOR_CONTAINS,
19
+ OPERATOR_GREATER_THAN,
20
+ OPERATOR_GREATER_THAN_OR_EQUAL,
21
+ OPERATOR_IN_THE_PAST,
22
+ OPERATOR_IS,
23
+ OPERATOR_IS_ALL,
24
+ OPERATOR_IS_ANY,
25
+ OPERATOR_IS_NONE,
26
+ OPERATOR_IS_NOT,
27
+ OPERATOR_IS_NOT_ALL,
28
+ OPERATOR_LESS_THAN,
29
+ OPERATOR_LESS_THAN_OR_EQUAL,
30
+ OPERATOR_NOT_CONTAINS,
31
+ OPERATOR_NOT_ON,
32
+ OPERATOR_ON,
33
+ OPERATOR_OVER,
34
+ OPERATOR_STARTS_WITH,
35
+ } from '../constants';
36
+
37
+ const filterTextWrappers = {
38
+ Name: <span className="dataviews-filters__summary-filter-text-name" />,
39
+ Value: <span className="dataviews-filters__summary-filter-text-value" />,
40
+ };
41
+
42
+ const OPERATORS: {
43
+ name: Operator;
44
+ label: string;
45
+ filterText: (
46
+ filter: NormalizedFilter,
47
+ activeElements: Option[]
48
+ ) => ReactElement;
49
+ selection: 'single' | 'multi' | 'custom';
50
+ }[] = [
51
+ {
52
+ name: OPERATOR_IS_ANY,
53
+ /* translators: DataViews operator name */
54
+ label: __( 'Includes' ),
55
+ filterText: ( filter: NormalizedFilter, activeElements: Option[] ) =>
56
+ createInterpolateElement(
57
+ sprintf(
58
+ /* translators: 1: Filter name (e.g. "Author"). 2: Filter value (e.g. "Admin"): "Author is any: Admin, Editor". */
59
+ __( '<Name>%1$s includes: </Name><Value>%2$s</Value>' ),
60
+ filter.name,
61
+ activeElements
62
+ .map( ( element ) => element.label )
63
+ .join( ', ' )
64
+ ),
65
+ filterTextWrappers
66
+ ),
67
+ selection: 'multi',
68
+ },
69
+ {
70
+ name: OPERATOR_IS_NONE,
71
+ /* translators: DataViews operator name */
72
+ label: __( 'Is none of' ),
73
+ filterText: ( filter: NormalizedFilter, activeElements: Option[] ) =>
74
+ createInterpolateElement(
75
+ sprintf(
76
+ /* translators: 1: Filter name (e.g. "Author"). 2: Filter value (e.g. "Admin"): "Author is none of: Admin, Editor". */
77
+ __( '<Name>%1$s is none of: </Name><Value>%2$s</Value>' ),
78
+ filter.name,
79
+ activeElements
80
+ .map( ( element ) => element.label )
81
+ .join( ', ' )
82
+ ),
83
+ filterTextWrappers
84
+ ),
85
+ selection: 'multi',
86
+ },
87
+ {
88
+ name: OPERATOR_IS_ALL,
89
+ /* translators: DataViews operator name */
90
+ label: __( 'Includes all' ),
91
+ filterText: ( filter: NormalizedFilter, activeElements: Option[] ) =>
92
+ createInterpolateElement(
93
+ sprintf(
94
+ /* translators: 1: Filter name (e.g. "Author"). 2: Filter value (e.g. "Admin"): "Author includes all: Admin, Editor". */
95
+ __( '<Name>%1$s includes all: </Name><Value>%2$s</Value>' ),
96
+ filter.name,
97
+ activeElements
98
+ .map( ( element ) => element.label )
99
+ .join( ', ' )
100
+ ),
101
+ filterTextWrappers
102
+ ),
103
+ selection: 'multi',
104
+ },
105
+ {
106
+ name: OPERATOR_IS_NOT_ALL,
107
+ /* translators: DataViews operator name */
108
+ label: __( 'Is none of' ),
109
+ filterText: ( filter: NormalizedFilter, activeElements: Option[] ) =>
110
+ createInterpolateElement(
111
+ sprintf(
112
+ /* translators: 1: Filter name (e.g. "Author"). 2: Filter value (e.g. "Admin"): "Author is none of: Admin, Editor". */
113
+ __( '<Name>%1$s is none of: </Name><Value>%2$s</Value>' ),
114
+ filter.name,
115
+ activeElements
116
+ .map( ( element ) => element.label )
117
+ .join( ', ' )
118
+ ),
119
+ filterTextWrappers
120
+ ),
121
+ selection: 'multi',
122
+ },
123
+ {
124
+ name: OPERATOR_BETWEEN,
125
+ /* translators: DataViews operator name */
126
+ label: __( 'Between (inc)' ),
127
+ filterText: ( filter: NormalizedFilter, activeElements: Option[] ) =>
128
+ createInterpolateElement(
129
+ sprintf(
130
+ /* translators: 1: Filter name (e.g. "Item count"). 2: Filter value min. 3: Filter value max. e.g.: "Item count between (inc): 10 and 180". */
131
+ __(
132
+ '<Name>%1$s between (inc): </Name><Value>%2$s and %3$s</Value>'
133
+ ),
134
+ filter.name,
135
+ activeElements[ 0 ].label[ 0 ],
136
+ activeElements[ 0 ].label[ 1 ]
137
+ ),
138
+ filterTextWrappers
139
+ ),
140
+ selection: 'custom',
141
+ },
142
+ {
143
+ name: OPERATOR_IN_THE_PAST,
144
+ /* translators: DataViews operator name */
145
+ label: __( 'In the past' ),
146
+ filterText: ( filter: NormalizedFilter, activeElements: Option[] ) =>
147
+ createInterpolateElement(
148
+ sprintf(
149
+ /* translators: 1: Filter name (e.g. "Date"). 2: Filter value (e.g. "7 days"): "Date is in the past: 7 days". */
150
+ __(
151
+ '<Name>%1$s is in the past: </Name><Value>%2$s</Value>'
152
+ ),
153
+ filter.name,
154
+ `${ activeElements[ 0 ].value.value } ${ activeElements[ 0 ].value.unit }`
155
+ ),
156
+ filterTextWrappers
157
+ ),
158
+ selection: 'custom',
159
+ },
160
+ {
161
+ name: OPERATOR_OVER,
162
+ /* translators: DataViews operator name */
163
+ label: __( 'Over' ),
164
+ filterText: ( filter: NormalizedFilter, activeElements: Option[] ) =>
165
+ createInterpolateElement(
166
+ sprintf(
167
+ /* translators: 1: Filter name (e.g. "Date"). 2: Filter value (e.g. "7 days"): "Date is over: 7 days". */
168
+ __( '<Name>%1$s is over: </Name><Value>%2$s</Value>' ),
169
+ filter.name,
170
+ `${ activeElements[ 0 ].value.value } ${ activeElements[ 0 ].value.unit }`
171
+ ),
172
+ filterTextWrappers
173
+ ),
174
+ selection: 'custom',
175
+ },
176
+ {
177
+ name: OPERATOR_IS,
178
+ /* translators: DataViews operator name */
179
+ label: __( 'Is' ),
180
+ filterText: ( filter: NormalizedFilter, activeElements: Option[] ) =>
181
+ createInterpolateElement(
182
+ sprintf(
183
+ /* translators: 1: Filter name (e.g. "Author"). 2: Filter value (e.g. "Admin"): "Author is: Admin". */
184
+ __( '<Name>%1$s is: </Name><Value>%2$s</Value>' ),
185
+ filter.name,
186
+ activeElements[ 0 ].label
187
+ ),
188
+ filterTextWrappers
189
+ ),
190
+ selection: 'single',
191
+ },
192
+ {
193
+ name: OPERATOR_IS_NOT,
194
+ /* translators: DataViews operator name */
195
+ label: __( 'Is not' ),
196
+ filterText: ( filter: NormalizedFilter, activeElements: Option[] ) =>
197
+ createInterpolateElement(
198
+ sprintf(
199
+ /* translators: 1: Filter name (e.g. "Author"). 2: Filter value (e.g. "Admin"): "Author is not: Admin". */
200
+ __( '<Name>%1$s is not: </Name><Value>%2$s</Value>' ),
201
+ filter.name,
202
+ activeElements[ 0 ].label
203
+ ),
204
+ filterTextWrappers
205
+ ),
206
+ selection: 'single',
207
+ },
208
+ {
209
+ name: OPERATOR_LESS_THAN,
210
+ /* translators: DataViews operator name */
211
+ label: __( 'Less than' ),
212
+ filterText: ( filter: NormalizedFilter, activeElements: Option[] ) =>
213
+ createInterpolateElement(
214
+ sprintf(
215
+ /* translators: 1: Filter name (e.g. "Count"). 2: Filter value (e.g. "10"): "Count is less than: 10". */
216
+ __( '<Name>%1$s is less than: </Name><Value>%2$s</Value>' ),
217
+ filter.name,
218
+ activeElements[ 0 ].label
219
+ ),
220
+ filterTextWrappers
221
+ ),
222
+ selection: 'single',
223
+ },
224
+ {
225
+ name: OPERATOR_GREATER_THAN,
226
+ /* translators: DataViews operator name */
227
+ label: __( 'Greater than' ),
228
+ filterText: ( filter: NormalizedFilter, activeElements: Option[] ) =>
229
+ createInterpolateElement(
230
+ sprintf(
231
+ /* translators: 1: Filter name (e.g. "Count"). 2: Filter value (e.g. "10"): "Count is greater than: 10". */
232
+ __(
233
+ '<Name>%1$s is greater than: </Name><Value>%2$s</Value>'
234
+ ),
235
+ filter.name,
236
+ activeElements[ 0 ].label
237
+ ),
238
+ filterTextWrappers
239
+ ),
240
+ selection: 'single',
241
+ },
242
+ {
243
+ name: OPERATOR_LESS_THAN_OR_EQUAL,
244
+ /* translators: DataViews operator name */
245
+ label: __( 'Less than or equal' ),
246
+ filterText: ( filter: NormalizedFilter, activeElements: Option[] ) =>
247
+ createInterpolateElement(
248
+ sprintf(
249
+ /* translators: 1: Filter name (e.g. "Count"). 2: Filter value (e.g. "10"): "Count is less than or equal to: 10". */
250
+ __(
251
+ '<Name>%1$s is less than or equal to: </Name><Value>%2$s</Value>'
252
+ ),
253
+ filter.name,
254
+ activeElements[ 0 ].label
255
+ ),
256
+ filterTextWrappers
257
+ ),
258
+ selection: 'single',
259
+ },
260
+ {
261
+ name: OPERATOR_GREATER_THAN_OR_EQUAL,
262
+ /* translators: DataViews operator name */
263
+ label: __( 'Greater than or equal' ),
264
+ filterText: ( filter: NormalizedFilter, activeElements: Option[] ) =>
265
+ createInterpolateElement(
266
+ sprintf(
267
+ /* translators: 1: Filter name (e.g. "Count"). 2: Filter value (e.g. "10"): "Count is greater than or equal to: 10". */
268
+ __(
269
+ '<Name>%1$s is greater than or equal to: </Name><Value>%2$s</Value>'
270
+ ),
271
+ filter.name,
272
+ activeElements[ 0 ].label
273
+ ),
274
+ filterTextWrappers
275
+ ),
276
+ selection: 'single',
277
+ },
278
+ {
279
+ name: OPERATOR_BEFORE,
280
+ /* translators: DataViews operator name */
281
+ label: __( 'Before' ),
282
+ filterText: ( filter: NormalizedFilter, activeElements: Option[] ) =>
283
+ createInterpolateElement(
284
+ sprintf(
285
+ /* translators: 1: Filter name (e.g. "Date"). 2: Filter value (e.g. "2024-01-01"): "Date is before: 2024-01-01". */
286
+ __( '<Name>%1$s is before: </Name><Value>%2$s</Value>' ),
287
+ filter.name,
288
+ activeElements[ 0 ].label
289
+ ),
290
+ filterTextWrappers
291
+ ),
292
+ selection: 'single',
293
+ },
294
+ {
295
+ name: OPERATOR_AFTER,
296
+ /* translators: DataViews operator name */
297
+ label: __( 'After' ),
298
+ filterText: ( filter: NormalizedFilter, activeElements: Option[] ) =>
299
+ createInterpolateElement(
300
+ sprintf(
301
+ /* translators: 1: Filter name (e.g. "Date"). 2: Filter value (e.g. "2024-01-01"): "Date is after: 2024-01-01". */
302
+ __( '<Name>%1$s is after: </Name><Value>%2$s</Value>' ),
303
+ filter.name,
304
+ activeElements[ 0 ].label
305
+ ),
306
+ filterTextWrappers
307
+ ),
308
+ selection: 'single',
309
+ },
310
+ {
311
+ name: OPERATOR_BEFORE_INC,
312
+ /* translators: DataViews operator name */
313
+ label: __( 'Before (inc)' ),
314
+ filterText: ( filter: NormalizedFilter, activeElements: Option[] ) =>
315
+ createInterpolateElement(
316
+ sprintf(
317
+ /* translators: 1: Filter name (e.g. "Date"). 2: Filter value (e.g. "2024-01-01"): "Date is on or before: 2024-01-01". */
318
+ __(
319
+ '<Name>%1$s is on or before: </Name><Value>%2$s</Value>'
320
+ ),
321
+ filter.name,
322
+ activeElements[ 0 ].label
323
+ ),
324
+ filterTextWrappers
325
+ ),
326
+ selection: 'single',
327
+ },
328
+ {
329
+ name: OPERATOR_AFTER_INC,
330
+ /* translators: DataViews operator name */
331
+ label: __( 'After (inc)' ),
332
+ filterText: ( filter: NormalizedFilter, activeElements: Option[] ) =>
333
+ createInterpolateElement(
334
+ sprintf(
335
+ /* translators: 1: Filter name (e.g. "Date"). 2: Filter value (e.g. "2024-01-01"): "Date is on or after: 2024-01-01". */
336
+ __(
337
+ '<Name>%1$s is on or after: </Name><Value>%2$s</Value>'
338
+ ),
339
+ filter.name,
340
+ activeElements[ 0 ].label
341
+ ),
342
+ filterTextWrappers
343
+ ),
344
+ selection: 'single',
345
+ },
346
+ {
347
+ name: OPERATOR_CONTAINS,
348
+ /* translators: DataViews operator name */
349
+ label: __( 'Contains' ),
350
+ filterText: ( filter: NormalizedFilter, activeElements: Option[] ) =>
351
+ createInterpolateElement(
352
+ sprintf(
353
+ /* translators: 1: Filter name (e.g. "Title"). 2: Filter value (e.g. "Hello"): "Title contains: Hello". */
354
+ __( '<Name>%1$s contains: </Name><Value>%2$s</Value>' ),
355
+ filter.name,
356
+ activeElements[ 0 ].label
357
+ ),
358
+ filterTextWrappers
359
+ ),
360
+ selection: 'single',
361
+ },
362
+ {
363
+ name: OPERATOR_NOT_CONTAINS,
364
+ /* translators: DataViews operator name */
365
+ label: __( "Doesn't contain" ),
366
+ filterText: ( filter: NormalizedFilter, activeElements: Option[] ) =>
367
+ createInterpolateElement(
368
+ sprintf(
369
+ /* translators: 1: Filter name (e.g. "Title"). 2: Filter value (e.g. "Hello"): "Title doesn't contain: Hello". */
370
+ __(
371
+ "<Name>%1$s doesn't contain: </Name><Value>%2$s</Value>"
372
+ ),
373
+ filter.name,
374
+ activeElements[ 0 ].label
375
+ ),
376
+ filterTextWrappers
377
+ ),
378
+ selection: 'single',
379
+ },
380
+ {
381
+ name: OPERATOR_STARTS_WITH,
382
+ /* translators: DataViews operator name */
383
+ label: __( 'Starts with' ),
384
+ filterText: ( filter: NormalizedFilter, activeElements: Option[] ) =>
385
+ createInterpolateElement(
386
+ sprintf(
387
+ /* translators: 1: Filter name (e.g. "Title"). 2: Filter value (e.g. "Hello"): "Title starts with: Hello". */
388
+ __( '<Name>%1$s starts with: </Name><Value>%2$s</Value>' ),
389
+ filter.name,
390
+ activeElements[ 0 ].label
391
+ ),
392
+ filterTextWrappers
393
+ ),
394
+ selection: 'single',
395
+ },
396
+ {
397
+ name: OPERATOR_ON,
398
+ /* translators: DataViews operator name */
399
+ label: __( 'On' ),
400
+ filterText: ( filter: NormalizedFilter, activeElements: Option[] ) =>
401
+ createInterpolateElement(
402
+ sprintf(
403
+ /* translators: 1: Filter name (e.g. "Date"). 2: Filter value (e.g. "2024-01-01"): "Date is: 2024-01-01". */
404
+ __( '<Name>%1$s is: </Name><Value>%2$s</Value>' ),
405
+ filter.name,
406
+ activeElements[ 0 ].label
407
+ ),
408
+ filterTextWrappers
409
+ ),
410
+ selection: 'single',
411
+ },
412
+ {
413
+ name: OPERATOR_NOT_ON,
414
+ /* translators: DataViews operator name */
415
+ label: __( 'Not on' ),
416
+ filterText: ( filter: NormalizedFilter, activeElements: Option[] ) =>
417
+ createInterpolateElement(
418
+ sprintf(
419
+ /* translators: 1: Filter name (e.g. "Date"). 2: Filter value (e.g. "2024-01-01"): "Date is not: 2024-01-01". */
420
+ __( '<Name>%1$s is not: </Name><Value>%2$s</Value>' ),
421
+ filter.name,
422
+ activeElements[ 0 ].label
423
+ ),
424
+ filterTextWrappers
425
+ ),
426
+ selection: 'single',
427
+ },
428
+ ];
429
+
430
+ const getOperatorByName = ( name: string | undefined ) =>
431
+ OPERATORS.find( ( op ) => op.name === name );
432
+
433
+ const getAllOperatorNames = () => OPERATORS.map( ( op ) => op.name );
434
+
435
+ const isSingleSelectionOperator = ( name: string ) =>
436
+ OPERATORS.filter( ( op ) => op.selection === 'single' ).some(
437
+ ( op ) => op.name === name
438
+ );
439
+
440
+ const isRegisteredOperator = ( name: string ) =>
441
+ OPERATORS.some( ( op ) => op.name === name );
442
+
443
+ export {
444
+ getOperatorByName,
445
+ getAllOperatorNames,
446
+ isSingleSelectionOperator,
447
+ isRegisteredOperator,
448
+ };
package/tsconfig.json CHANGED
@@ -14,6 +14,7 @@
14
14
  { "path": "../compose" },
15
15
  { "path": "../data" },
16
16
  { "path": "../date" },
17
+ { "path": "../deprecated" },
17
18
  { "path": "../dom" },
18
19
  { "path": "../element" },
19
20
  { "path": "../i18n" },