@wordpress/dataviews 9.0.1-next.6f42e1382.0 → 9.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 (286) hide show
  1. package/CHANGELOG.md +25 -2
  2. package/README.md +112 -15
  3. package/build/components/dataviews/index.js +4 -6
  4. package/build/components/dataviews/index.js.map +1 -1
  5. package/build/components/dataviews-filters/filters-toggled.js +32 -0
  6. package/build/components/dataviews-filters/filters-toggled.js.map +1 -0
  7. package/build/components/dataviews-filters/filters.js +73 -0
  8. package/build/components/dataviews-filters/filters.js.map +1 -0
  9. package/build/components/dataviews-filters/index.js +26 -190
  10. package/build/components/dataviews-filters/index.js.map +1 -1
  11. package/build/components/dataviews-filters/input-widget.js +48 -4
  12. package/build/components/dataviews-filters/input-widget.js.map +1 -1
  13. package/build/components/dataviews-filters/toggle.js +99 -0
  14. package/build/components/dataviews-filters/toggle.js.map +1 -0
  15. package/build/components/dataviews-filters/use-filters.js +63 -0
  16. package/build/components/dataviews-filters/use-filters.js.map +1 -0
  17. package/build/components/dataviews-picker/index.js +4 -6
  18. package/build/components/dataviews-picker/index.js.map +1 -1
  19. package/build/components/dataviews-view-config/index.js +22 -3
  20. package/build/components/dataviews-view-config/index.js.map +1 -1
  21. package/build/dataform-controls/array.js +117 -29
  22. package/build/dataform-controls/array.js.map +1 -1
  23. package/build/dataform-controls/checkbox.js +31 -20
  24. package/build/dataform-controls/checkbox.js.map +1 -1
  25. package/build/dataform-controls/color.js +29 -24
  26. package/build/dataform-controls/color.js.map +1 -1
  27. package/build/dataform-controls/date.js +32 -24
  28. package/build/dataform-controls/date.js.map +1 -1
  29. package/build/dataform-controls/datetime.js +133 -19
  30. package/build/dataform-controls/datetime.js.map +1 -1
  31. package/build/dataform-controls/email.js +7 -1
  32. package/build/dataform-controls/email.js.map +1 -1
  33. package/build/dataform-controls/index.js +25 -0
  34. package/build/dataform-controls/index.js.map +1 -1
  35. package/build/dataform-controls/integer.js +7 -106
  36. package/build/dataform-controls/integer.js.map +1 -1
  37. package/build/dataform-controls/number.js +21 -0
  38. package/build/dataform-controls/number.js.map +1 -0
  39. package/build/dataform-controls/radio.js +42 -9
  40. package/build/dataform-controls/radio.js.map +1 -1
  41. package/build/dataform-controls/relative-date-control.js +6 -10
  42. package/build/dataform-controls/relative-date-control.js.map +1 -1
  43. package/build/dataform-controls/select.js +41 -10
  44. package/build/dataform-controls/select.js.map +1 -1
  45. package/build/dataform-controls/telephone.js +7 -1
  46. package/build/dataform-controls/telephone.js.map +1 -1
  47. package/build/dataform-controls/text.js +14 -2
  48. package/build/dataform-controls/text.js.map +1 -1
  49. package/build/dataform-controls/textarea.js +33 -20
  50. package/build/dataform-controls/textarea.js.map +1 -1
  51. package/build/dataform-controls/toggle-group.js +36 -6
  52. package/build/dataform-controls/toggle-group.js.map +1 -1
  53. package/build/dataform-controls/toggle.js +33 -22
  54. package/build/dataform-controls/toggle.js.map +1 -1
  55. package/build/dataform-controls/url.js +7 -1
  56. package/build/dataform-controls/url.js.map +1 -1
  57. package/build/dataform-controls/utils/validated-input.js +34 -32
  58. package/build/dataform-controls/utils/validated-input.js.map +1 -1
  59. package/build/dataform-controls/utils/validated-number.js +146 -0
  60. package/build/dataform-controls/utils/validated-number.js.map +1 -0
  61. package/build/dataforms-layouts/panel/dropdown.js +10 -14
  62. package/build/dataforms-layouts/panel/dropdown.js.map +1 -1
  63. package/build/dataforms-layouts/panel/index.js +24 -11
  64. package/build/dataforms-layouts/panel/index.js.map +1 -1
  65. package/build/dataforms-layouts/panel/modal.js +22 -27
  66. package/build/dataforms-layouts/panel/modal.js.map +1 -1
  67. package/build/dataforms-layouts/panel/summary-button.js +67 -0
  68. package/build/dataforms-layouts/panel/summary-button.js.map +1 -0
  69. package/build/dataviews-layouts/picker-grid/index.js +4 -1
  70. package/build/dataviews-layouts/picker-grid/index.js.map +1 -1
  71. package/build/field-types/array.js +0 -6
  72. package/build/field-types/array.js.map +1 -1
  73. package/build/field-types/index.js +4 -0
  74. package/build/field-types/index.js.map +1 -1
  75. package/build/field-types/number.js +71 -0
  76. package/build/field-types/number.js.map +1 -0
  77. package/build/index.js +7 -0
  78. package/build/index.js.map +1 -1
  79. package/build/normalize-fields.js +17 -0
  80. package/build/normalize-fields.js.map +1 -1
  81. package/build/types.js.map +1 -1
  82. package/build/validation.js +18 -1
  83. package/build/validation.js.map +1 -1
  84. package/build-module/components/dataviews/index.js +5 -7
  85. package/build-module/components/dataviews/index.js.map +1 -1
  86. package/build-module/components/dataviews-filters/filters-toggled.js +24 -0
  87. package/build-module/components/dataviews-filters/filters-toggled.js.map +1 -0
  88. package/build-module/components/dataviews-filters/filters.js +65 -0
  89. package/build-module/components/dataviews-filters/filters.js.map +1 -0
  90. package/build-module/components/dataviews-filters/index.js +4 -186
  91. package/build-module/components/dataviews-filters/index.js.map +1 -1
  92. package/build-module/components/dataviews-filters/input-widget.js +48 -4
  93. package/build-module/components/dataviews-filters/input-widget.js.map +1 -1
  94. package/build-module/components/dataviews-filters/toggle.js +91 -0
  95. package/build-module/components/dataviews-filters/toggle.js.map +1 -0
  96. package/build-module/components/dataviews-filters/use-filters.js +56 -0
  97. package/build-module/components/dataviews-filters/use-filters.js.map +1 -0
  98. package/build-module/components/dataviews-picker/index.js +5 -7
  99. package/build-module/components/dataviews-picker/index.js.map +1 -1
  100. package/build-module/components/dataviews-view-config/index.js +22 -3
  101. package/build-module/components/dataviews-view-config/index.js.map +1 -1
  102. package/build-module/dataform-controls/array.js +120 -32
  103. package/build-module/dataform-controls/array.js.map +1 -1
  104. package/build-module/dataform-controls/checkbox.js +31 -21
  105. package/build-module/dataform-controls/checkbox.js.map +1 -1
  106. package/build-module/dataform-controls/color.js +28 -24
  107. package/build-module/dataform-controls/color.js.map +1 -1
  108. package/build-module/dataform-controls/date.js +32 -24
  109. package/build-module/dataform-controls/date.js.map +1 -1
  110. package/build-module/dataform-controls/datetime.js +135 -21
  111. package/build-module/dataform-controls/datetime.js.map +1 -1
  112. package/build-module/dataform-controls/email.js +7 -1
  113. package/build-module/dataform-controls/email.js.map +1 -1
  114. package/build-module/dataform-controls/index.js +25 -0
  115. package/build-module/dataform-controls/index.js.map +1 -1
  116. package/build-module/dataform-controls/integer.js +7 -106
  117. package/build-module/dataform-controls/integer.js.map +1 -1
  118. package/build-module/dataform-controls/number.js +14 -0
  119. package/build-module/dataform-controls/number.js.map +1 -0
  120. package/build-module/dataform-controls/radio.js +44 -11
  121. package/build-module/dataform-controls/radio.js.map +1 -1
  122. package/build-module/dataform-controls/relative-date-control.js +6 -10
  123. package/build-module/dataform-controls/relative-date-control.js.map +1 -1
  124. package/build-module/dataform-controls/select.js +43 -12
  125. package/build-module/dataform-controls/select.js.map +1 -1
  126. package/build-module/dataform-controls/telephone.js +7 -1
  127. package/build-module/dataform-controls/telephone.js.map +1 -1
  128. package/build-module/dataform-controls/text.js +14 -2
  129. package/build-module/dataform-controls/text.js.map +1 -1
  130. package/build-module/dataform-controls/textarea.js +32 -20
  131. package/build-module/dataform-controls/textarea.js.map +1 -1
  132. package/build-module/dataform-controls/toggle-group.js +38 -8
  133. package/build-module/dataform-controls/toggle-group.js.map +1 -1
  134. package/build-module/dataform-controls/toggle.js +33 -23
  135. package/build-module/dataform-controls/toggle.js.map +1 -1
  136. package/build-module/dataform-controls/url.js +7 -1
  137. package/build-module/dataform-controls/url.js.map +1 -1
  138. package/build-module/dataform-controls/utils/validated-input.js +34 -33
  139. package/build-module/dataform-controls/utils/validated-input.js.map +1 -1
  140. package/build-module/dataform-controls/utils/validated-number.js +138 -0
  141. package/build-module/dataform-controls/utils/validated-number.js.map +1 -0
  142. package/build-module/dataforms-layouts/panel/dropdown.js +10 -15
  143. package/build-module/dataforms-layouts/panel/dropdown.js.map +1 -1
  144. package/build-module/dataforms-layouts/panel/index.js +24 -11
  145. package/build-module/dataforms-layouts/panel/index.js.map +1 -1
  146. package/build-module/dataforms-layouts/panel/modal.js +22 -28
  147. package/build-module/dataforms-layouts/panel/modal.js.map +1 -1
  148. package/build-module/dataforms-layouts/panel/summary-button.js +60 -0
  149. package/build-module/dataforms-layouts/panel/summary-button.js.map +1 -0
  150. package/build-module/dataviews-layouts/picker-grid/index.js +4 -1
  151. package/build-module/dataviews-layouts/picker-grid/index.js.map +1 -1
  152. package/build-module/field-types/array.js +0 -6
  153. package/build-module/field-types/array.js.map +1 -1
  154. package/build-module/field-types/index.js +4 -0
  155. package/build-module/field-types/index.js.map +1 -1
  156. package/build-module/field-types/number.js +65 -0
  157. package/build-module/field-types/number.js.map +1 -0
  158. package/build-module/index.js +1 -0
  159. package/build-module/index.js.map +1 -1
  160. package/build-module/normalize-fields.js +15 -0
  161. package/build-module/normalize-fields.js.map +1 -1
  162. package/build-module/types.js.map +1 -1
  163. package/build-module/validation.js +18 -1
  164. package/build-module/validation.js.map +1 -1
  165. package/build-types/components/dataform/stories/index.story.d.ts +3 -0
  166. package/build-types/components/dataform/stories/index.story.d.ts.map +1 -1
  167. package/build-types/components/dataviews/index.d.ts +3 -2
  168. package/build-types/components/dataviews/index.d.ts.map +1 -1
  169. package/build-types/components/dataviews/stories/fixtures.d.ts +4 -2
  170. package/build-types/components/dataviews/stories/fixtures.d.ts.map +1 -1
  171. package/build-types/components/dataviews-filters/filters-toggled.d.ts +5 -0
  172. package/build-types/components/dataviews-filters/filters-toggled.d.ts.map +1 -0
  173. package/build-types/components/dataviews-filters/filters.d.ts +6 -0
  174. package/build-types/components/dataviews-filters/filters.d.ts.map +1 -0
  175. package/build-types/components/dataviews-filters/index.d.ts +4 -8
  176. package/build-types/components/dataviews-filters/index.d.ts.map +1 -1
  177. package/build-types/components/dataviews-filters/input-widget.d.ts.map +1 -1
  178. package/build-types/components/dataviews-filters/toggle.d.ts +3 -0
  179. package/build-types/components/dataviews-filters/toggle.d.ts.map +1 -0
  180. package/build-types/components/dataviews-filters/use-filters.d.ts +4 -0
  181. package/build-types/components/dataviews-filters/use-filters.d.ts.map +1 -0
  182. package/build-types/components/dataviews-picker/index.d.ts +3 -2
  183. package/build-types/components/dataviews-picker/index.d.ts.map +1 -1
  184. package/build-types/components/dataviews-view-config/index.d.ts.map +1 -1
  185. package/build-types/dataform-controls/array.d.ts.map +1 -1
  186. package/build-types/dataform-controls/checkbox.d.ts.map +1 -1
  187. package/build-types/dataform-controls/color.d.ts.map +1 -1
  188. package/build-types/dataform-controls/date.d.ts.map +1 -1
  189. package/build-types/dataform-controls/datetime.d.ts.map +1 -1
  190. package/build-types/dataform-controls/email.d.ts.map +1 -1
  191. package/build-types/dataform-controls/index.d.ts +1 -1
  192. package/build-types/dataform-controls/index.d.ts.map +1 -1
  193. package/build-types/dataform-controls/integer.d.ts +4 -1
  194. package/build-types/dataform-controls/integer.d.ts.map +1 -1
  195. package/build-types/dataform-controls/number.d.ts +6 -0
  196. package/build-types/dataform-controls/number.d.ts.map +1 -0
  197. package/build-types/dataform-controls/radio.d.ts.map +1 -1
  198. package/build-types/dataform-controls/relative-date-control.d.ts +6 -5
  199. package/build-types/dataform-controls/relative-date-control.d.ts.map +1 -1
  200. package/build-types/dataform-controls/select.d.ts.map +1 -1
  201. package/build-types/dataform-controls/telephone.d.ts.map +1 -1
  202. package/build-types/dataform-controls/text.d.ts +1 -1
  203. package/build-types/dataform-controls/text.d.ts.map +1 -1
  204. package/build-types/dataform-controls/textarea.d.ts +1 -1
  205. package/build-types/dataform-controls/textarea.d.ts.map +1 -1
  206. package/build-types/dataform-controls/toggle-group.d.ts.map +1 -1
  207. package/build-types/dataform-controls/toggle.d.ts.map +1 -1
  208. package/build-types/dataform-controls/url.d.ts.map +1 -1
  209. package/build-types/dataform-controls/utils/validated-input.d.ts +4 -4
  210. package/build-types/dataform-controls/utils/validated-input.d.ts.map +1 -1
  211. package/build-types/dataform-controls/utils/validated-number.d.ts +9 -0
  212. package/build-types/dataform-controls/utils/validated-number.d.ts.map +1 -0
  213. package/build-types/dataforms-layouts/panel/dropdown.d.ts +2 -1
  214. package/build-types/dataforms-layouts/panel/dropdown.d.ts.map +1 -1
  215. package/build-types/dataforms-layouts/panel/index.d.ts.map +1 -1
  216. package/build-types/dataforms-layouts/panel/modal.d.ts +2 -1
  217. package/build-types/dataforms-layouts/panel/modal.d.ts.map +1 -1
  218. package/build-types/dataforms-layouts/panel/summary-button.d.ts +15 -0
  219. package/build-types/dataforms-layouts/panel/summary-button.d.ts.map +1 -0
  220. package/build-types/dataviews-layouts/picker-grid/index.d.ts.map +1 -1
  221. package/build-types/field-types/array.d.ts.map +1 -1
  222. package/build-types/field-types/index.d.ts.map +1 -1
  223. package/build-types/field-types/number.d.ts +20 -0
  224. package/build-types/field-types/number.d.ts.map +1 -0
  225. package/build-types/field-types/stories/index.story.d.ts +106 -57
  226. package/build-types/field-types/stories/index.story.d.ts.map +1 -1
  227. package/build-types/index.d.ts +1 -0
  228. package/build-types/index.d.ts.map +1 -1
  229. package/build-types/normalize-fields.d.ts +3 -0
  230. package/build-types/normalize-fields.d.ts.map +1 -1
  231. package/build-types/types.d.ts +69 -5
  232. package/build-types/types.d.ts.map +1 -1
  233. package/build-types/validation.d.ts.map +1 -1
  234. package/build-wp/index.js +2354 -1717
  235. package/package.json +16 -15
  236. package/src/components/dataform/stories/index.story.tsx +528 -8
  237. package/src/components/dataviews/index.tsx +8 -14
  238. package/src/components/dataviews/stories/fixtures.tsx +99 -41
  239. package/src/components/dataviews/stories/index.story.tsx +2 -2
  240. package/src/components/dataviews-filters/filters-toggled.tsx +20 -0
  241. package/src/components/dataviews-filters/filters.tsx +73 -0
  242. package/src/components/dataviews-filters/index.tsx +4 -246
  243. package/src/components/dataviews-filters/input-widget.tsx +44 -5
  244. package/src/components/dataviews-filters/toggle.tsx +118 -0
  245. package/src/components/dataviews-filters/use-filters.ts +73 -0
  246. package/src/components/dataviews-picker/index.tsx +8 -14
  247. package/src/components/dataviews-picker/stories/index.story.tsx +1 -1
  248. package/src/components/dataviews-view-config/index.tsx +18 -3
  249. package/src/dataform-controls/array.tsx +139 -44
  250. package/src/dataform-controls/checkbox.tsx +41 -24
  251. package/src/dataform-controls/color.tsx +33 -24
  252. package/src/dataform-controls/date.tsx +47 -21
  253. package/src/dataform-controls/datetime.tsx +171 -23
  254. package/src/dataform-controls/email.tsx +9 -1
  255. package/src/dataform-controls/index.tsx +28 -0
  256. package/src/dataform-controls/integer.tsx +3 -146
  257. package/src/dataform-controls/number.tsx +10 -0
  258. package/src/dataform-controls/radio.tsx +53 -11
  259. package/src/dataform-controls/relative-date-control.tsx +11 -10
  260. package/src/dataform-controls/select.tsx +53 -10
  261. package/src/dataform-controls/telephone.tsx +9 -1
  262. package/src/dataform-controls/text.tsx +18 -1
  263. package/src/dataform-controls/textarea.tsx +38 -24
  264. package/src/dataform-controls/toggle-group.tsx +50 -10
  265. package/src/dataform-controls/toggle.tsx +41 -24
  266. package/src/dataform-controls/url.tsx +9 -1
  267. package/src/dataform-controls/utils/validated-input.tsx +50 -50
  268. package/src/dataform-controls/utils/validated-number.tsx +209 -0
  269. package/src/dataforms-layouts/panel/dropdown.tsx +12 -23
  270. package/src/dataforms-layouts/panel/index.tsx +39 -16
  271. package/src/dataforms-layouts/panel/modal.tsx +24 -30
  272. package/src/dataforms-layouts/panel/summary-button.tsx +92 -0
  273. package/src/dataviews-layouts/picker-grid/index.tsx +15 -8
  274. package/src/field-types/array.tsx +0 -8
  275. package/src/field-types/index.tsx +5 -0
  276. package/src/field-types/number.tsx +104 -0
  277. package/src/field-types/stories/index.story.tsx +170 -16
  278. package/src/index.ts +1 -0
  279. package/src/normalize-fields.ts +18 -0
  280. package/src/test/dataform.tsx +36 -0
  281. package/src/test/filter-and-sort-data-view.js +182 -138
  282. package/src/test/normalize-fields.ts +136 -0
  283. package/src/test/validation.ts +235 -0
  284. package/src/types.ts +76 -4
  285. package/src/validation.ts +32 -0
  286. package/tsconfig.tsbuildinfo +1 -1
@@ -0,0 +1,104 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { __ } from '@wordpress/i18n';
5
+
6
+ /**
7
+ * Internal dependencies
8
+ */
9
+ import type {
10
+ DataViewRenderFieldProps,
11
+ SortDirection,
12
+ NormalizedField,
13
+ FieldTypeDefinition,
14
+ } from '../types';
15
+ import {
16
+ OPERATOR_IS,
17
+ OPERATOR_IS_NOT,
18
+ OPERATOR_LESS_THAN,
19
+ OPERATOR_GREATER_THAN,
20
+ OPERATOR_LESS_THAN_OR_EQUAL,
21
+ OPERATOR_GREATER_THAN_OR_EQUAL,
22
+ OPERATOR_IS_ANY,
23
+ OPERATOR_IS_NONE,
24
+ OPERATOR_IS_ALL,
25
+ OPERATOR_IS_NOT_ALL,
26
+ OPERATOR_BETWEEN,
27
+ } from '../constants';
28
+
29
+ function sort( a: any, b: any, direction: SortDirection ) {
30
+ return direction === 'asc' ? a - b : b - a;
31
+ }
32
+
33
+ function isEmpty( value: unknown ): value is '' | undefined | null {
34
+ return value === '' || value === undefined || value === null;
35
+ }
36
+
37
+ export default {
38
+ sort,
39
+ isValid: {
40
+ custom: ( item: any, field: NormalizedField< any > ) => {
41
+ const value = field.getValue( { item } );
42
+
43
+ if ( ! isEmpty( value ) && ! Number.isFinite( value ) ) {
44
+ return __( 'Value must be a number.' );
45
+ }
46
+
47
+ if ( field?.elements ) {
48
+ const isMember = field.elements.some(
49
+ ( element ) => element.value === Number( value )
50
+ );
51
+ if ( ! isMember ) {
52
+ return __( 'Value must be one of the elements.' );
53
+ }
54
+ }
55
+
56
+ return null;
57
+ },
58
+ },
59
+ Edit: 'number',
60
+ render: ( { item, field }: DataViewRenderFieldProps< any > ) => {
61
+ const value = field.getValue( { item } );
62
+ if ( ! isEmpty( value ) && field.elements ) {
63
+ const numericValue = Number( value );
64
+ const match = field.elements.find(
65
+ ( element ) =>
66
+ Number.isFinite( Number( element.value ) ) &&
67
+ Number( element.value ) === numericValue
68
+ );
69
+ if ( match ) {
70
+ return match.label;
71
+ }
72
+ }
73
+
74
+ // TODO: remove this hardcoded value when the decimal number is configurable
75
+ return Number( value ).toFixed( 2 );
76
+ },
77
+ enableSorting: true,
78
+ filterBy: {
79
+ defaultOperators: [
80
+ OPERATOR_IS,
81
+ OPERATOR_IS_NOT,
82
+ OPERATOR_LESS_THAN,
83
+ OPERATOR_GREATER_THAN,
84
+ OPERATOR_LESS_THAN_OR_EQUAL,
85
+ OPERATOR_GREATER_THAN_OR_EQUAL,
86
+ OPERATOR_BETWEEN,
87
+ ],
88
+ validOperators: [
89
+ // Single-selection
90
+ OPERATOR_IS,
91
+ OPERATOR_IS_NOT,
92
+ OPERATOR_LESS_THAN,
93
+ OPERATOR_GREATER_THAN,
94
+ OPERATOR_LESS_THAN_OR_EQUAL,
95
+ OPERATOR_GREATER_THAN_OR_EQUAL,
96
+ OPERATOR_BETWEEN,
97
+ // Multiple-selection
98
+ OPERATOR_IS_ANY,
99
+ OPERATOR_IS_NONE,
100
+ OPERATOR_IS_ALL,
101
+ OPERATOR_IS_NOT_ALL,
102
+ ],
103
+ },
104
+ } satisfies FieldTypeDefinition< any >;
@@ -5,7 +5,11 @@ import { useState, useMemo } from '@wordpress/element';
5
5
  import {
6
6
  __experimentalHStack as HStack,
7
7
  __experimentalVStack as VStack,
8
+ Icon,
9
+ __experimentalInputControlPrefixWrapper as InputControlPrefixWrapper,
10
+ __experimentalInputControlSuffixWrapper as InputControlSuffixWrapper,
8
11
  } from '@wordpress/components';
12
+ import { starFilled } from '@wordpress/icons';
9
13
 
10
14
  /**
11
15
  * Internal dependencies
@@ -38,6 +42,7 @@ const meta = {
38
42
  'datetime',
39
43
  'email',
40
44
  'integer',
45
+ 'number',
41
46
  'password',
42
47
  'radio',
43
48
  'select',
@@ -56,13 +61,36 @@ const meta = {
56
61
  };
57
62
  export default meta;
58
63
 
64
+ const DollarPrefix = () => (
65
+ <InputControlPrefixWrapper>
66
+ <span>$</span>
67
+ </InputControlPrefixWrapper>
68
+ );
69
+ const StarIconPrefix = () => (
70
+ <InputControlPrefixWrapper variant="icon">
71
+ <Icon icon={ starFilled } />
72
+ </InputControlPrefixWrapper>
73
+ );
74
+ const PercentSuffix = () => (
75
+ <InputControlSuffixWrapper>
76
+ <span>%</span>
77
+ </InputControlSuffixWrapper>
78
+ );
79
+ const USDSuffix = () => (
80
+ <InputControlSuffixWrapper>
81
+ <span>USD</span>
82
+ </InputControlSuffixWrapper>
83
+ );
59
84
  type DataType = {
60
85
  id: number;
61
86
  text: string;
62
87
  textWithElements: string;
88
+ textWithRadio: string;
63
89
  textWithTextarea: string;
64
90
  integer: number;
65
91
  integerWithElements: number;
92
+ number?: number;
93
+ numberWithElements?: number;
66
94
  boolean: boolean;
67
95
  booleanWithToggle: boolean;
68
96
  booleanWithElements: boolean;
@@ -86,16 +114,23 @@ type DataType = {
86
114
  arrayWithElements: string[];
87
115
  notype: string;
88
116
  notypeWithElements: string;
117
+ priceWithPrefix?: string;
118
+ ratingWithIcon?: string;
119
+ percentageWithSuffix?: string;
120
+ priceWithBoth?: string;
89
121
  };
90
122
 
91
123
  const data: DataType[] = [
92
124
  {
93
125
  id: 1,
94
126
  text: 'Text',
95
- textWithElements: 'Item 1',
127
+ textWithElements: 'item1',
128
+ textWithRadio: 'item2',
96
129
  textWithTextarea: 'Textarea',
97
130
  integer: 1,
98
131
  integerWithElements: 1,
132
+ number: 10.25,
133
+ numberWithElements: 2,
99
134
  boolean: true,
100
135
  booleanWithToggle: true,
101
136
  booleanWithElements: true,
@@ -104,7 +139,7 @@ const data: DataType[] = [
104
139
  date: '2021-01-01',
105
140
  dateWithElements: '2021-01-01',
106
141
  email: 'hi@example.com',
107
- emailWithElements: 'hi@example.com',
142
+ emailWithElements: 'bob@example.com',
108
143
  telephone: '+1-555-123-4567',
109
144
  telephoneWithElements: '+1-555-123-4567',
110
145
  color: '#ff6600',
@@ -120,6 +155,10 @@ const data: DataType[] = [
120
155
  arrayWithElements: [ 'item1', 'item2', 'item3' ],
121
156
  notype: 'No type',
122
157
  notypeWithElements: 'No type',
158
+ priceWithPrefix: '25.99',
159
+ ratingWithIcon: '4.5',
160
+ percentageWithSuffix: '85',
161
+ priceWithBoth: '199.99',
123
162
  },
124
163
  ];
125
164
 
@@ -141,6 +180,18 @@ const fields: Field< DataType >[] = [
141
180
  { value: 'item3', label: 'Item 3' },
142
181
  ],
143
182
  },
183
+ {
184
+ id: 'textWithRadio',
185
+ type: 'text',
186
+ label: 'Text (with radio)',
187
+ description: 'Help for text with radio.',
188
+ Edit: 'radio',
189
+ elements: [
190
+ { value: 'item1', label: 'Item 1' },
191
+ { value: 'item2', label: 'Item 2' },
192
+ { value: 'item3', label: 'Item 3' },
193
+ ],
194
+ },
144
195
  {
145
196
  id: 'textWithTextarea',
146
197
  type: 'text',
@@ -164,6 +215,29 @@ const fields: Field< DataType >[] = [
164
215
  { value: 2, label: 'Two' },
165
216
  { value: 3, label: 'Three' },
166
217
  ],
218
+ setValue: ( { value } ) => ( {
219
+ integerWithElements: parseInt( value, 10 ),
220
+ } ),
221
+ },
222
+ {
223
+ id: 'number',
224
+ type: 'number',
225
+ label: 'Number',
226
+ description: 'Number field increments by 0.01.',
227
+ },
228
+ {
229
+ id: 'numberWithElements',
230
+ type: 'number',
231
+ label: 'Number (with elements)',
232
+ description: 'Number field with elements.',
233
+ elements: [
234
+ { value: 1, label: 'One' },
235
+ { value: 2, label: 'Two' },
236
+ { value: 3, label: 'Three' },
237
+ ],
238
+ setValue: ( { value } ) => ( {
239
+ numberWithElements: Number( value ),
240
+ } ),
167
241
  },
168
242
  {
169
243
  id: 'boolean',
@@ -187,6 +261,9 @@ const fields: Field< DataType >[] = [
187
261
  { value: true, label: 'It is true' },
188
262
  { value: false, label: 'It is false' },
189
263
  ],
264
+ setValue: ( { value } ) => ( {
265
+ booleanWithElements: value === 'true' ? true : false,
266
+ } ),
190
267
  },
191
268
  {
192
269
  id: 'datetime',
@@ -247,6 +324,9 @@ const fields: Field< DataType >[] = [
247
324
  { value: 'jane@example.com', label: 'Jane Doe' },
248
325
  { value: 'bob@example.com', label: 'Bob Smith' },
249
326
  ],
327
+ setValue: ( { value } ) => ( {
328
+ emailWithElements: value,
329
+ } ),
250
330
  },
251
331
  {
252
332
  id: 'telephone',
@@ -395,6 +475,47 @@ const fields: Field< DataType >[] = [
395
475
  { value: 'item3', label: 'Item 3' },
396
476
  ],
397
477
  },
478
+ {
479
+ id: 'priceWithPrefix',
480
+ label: 'Text with Prefix',
481
+ type: 'text',
482
+ description: 'Text field with dollar sign prefix.',
483
+ Edit: {
484
+ control: 'text',
485
+ prefix: DollarPrefix,
486
+ },
487
+ },
488
+ {
489
+ id: 'ratingWithIcon',
490
+ label: 'Text with Icon Prefix',
491
+ type: 'text',
492
+ description: 'Text field with star icon prefix.',
493
+ Edit: {
494
+ control: 'text',
495
+ prefix: StarIconPrefix,
496
+ },
497
+ },
498
+ {
499
+ id: 'percentageWithSuffix',
500
+ label: 'Text with Suffix',
501
+ type: 'text',
502
+ description: 'Text field with percent sign suffix.',
503
+ Edit: {
504
+ control: 'text',
505
+ suffix: PercentSuffix,
506
+ },
507
+ },
508
+ {
509
+ id: 'priceWithBoth',
510
+ label: 'Text with Prefix and Suffix',
511
+ type: 'text',
512
+ description: 'Text field with both dollar prefix and USD suffix.',
513
+ Edit: {
514
+ control: 'text',
515
+ prefix: DollarPrefix,
516
+ suffix: USDSuffix,
517
+ },
518
+ },
398
519
  ];
399
520
 
400
521
  type PanelTypes = 'regular' | 'panel';
@@ -407,6 +528,7 @@ type ControlTypes =
407
528
  | 'datetime'
408
529
  | 'email'
409
530
  | 'integer'
531
+ | 'number'
410
532
  | 'password'
411
533
  | 'radio'
412
534
  | 'select'
@@ -534,7 +656,7 @@ const FieldTypeStory = ( {
534
656
  );
535
657
  };
536
658
 
537
- export const All = ( {
659
+ export const AllComponent = ( {
538
660
  type,
539
661
  Edit,
540
662
  }: {
@@ -543,8 +665,9 @@ export const All = ( {
543
665
  } ) => {
544
666
  return <FieldTypeStory fields={ fields } type={ type } Edit={ Edit } />;
545
667
  };
668
+ AllComponent.storyName = 'All types';
546
669
 
547
- export const Text = ( {
670
+ export const TextComponent = ( {
548
671
  type,
549
672
  Edit,
550
673
  }: {
@@ -558,8 +681,9 @@ export const Text = ( {
558
681
 
559
682
  return <FieldTypeStory fields={ textFields } type={ type } Edit={ Edit } />;
560
683
  };
684
+ TextComponent.storyName = 'text';
561
685
 
562
- export const Integer = ( {
686
+ export const IntegerComponent = ( {
563
687
  type,
564
688
  Edit,
565
689
  }: {
@@ -575,8 +699,27 @@ export const Integer = ( {
575
699
  <FieldTypeStory fields={ integerFields } type={ type } Edit={ Edit } />
576
700
  );
577
701
  };
702
+ IntegerComponent.storyName = 'integer';
703
+
704
+ export const NumberComponent = ( {
705
+ type,
706
+ Edit,
707
+ }: {
708
+ type: PanelTypes;
709
+ Edit: ControlTypes;
710
+ } ) => {
711
+ const numberFields = useMemo(
712
+ () => fields.filter( ( field ) => field.type === 'number' ),
713
+ []
714
+ );
715
+
716
+ return (
717
+ <FieldTypeStory fields={ numberFields } type={ type } Edit={ Edit } />
718
+ );
719
+ };
720
+ NumberComponent.storyName = 'number';
578
721
 
579
- export const Boolean = ( {
722
+ export const BooleanComponent = ( {
580
723
  type,
581
724
  Edit,
582
725
  }: {
@@ -592,8 +735,9 @@ export const Boolean = ( {
592
735
  <FieldTypeStory fields={ booleanFields } type={ type } Edit={ Edit } />
593
736
  );
594
737
  };
738
+ BooleanComponent.storyName = 'boolean';
595
739
 
596
- export const DateTime = ( {
740
+ export const DateTimeComponent = ( {
597
741
  type,
598
742
  Edit,
599
743
  }: {
@@ -609,8 +753,9 @@ export const DateTime = ( {
609
753
  <FieldTypeStory fields={ dateTimeFields } type={ type } Edit={ Edit } />
610
754
  );
611
755
  };
756
+ DateTimeComponent.storyName = 'datetime';
612
757
 
613
- export const Date = ( {
758
+ export const DateComponent = ( {
614
759
  type,
615
760
  Edit,
616
761
  }: {
@@ -624,8 +769,9 @@ export const Date = ( {
624
769
 
625
770
  return <FieldTypeStory fields={ dateFields } type={ type } Edit={ Edit } />;
626
771
  };
772
+ DateComponent.storyName = 'date';
627
773
 
628
- export const Email = ( {
774
+ export const EmailComponent = ( {
629
775
  type,
630
776
  Edit,
631
777
  }: {
@@ -641,8 +787,9 @@ export const Email = ( {
641
787
  <FieldTypeStory fields={ emailFields } type={ type } Edit={ Edit } />
642
788
  );
643
789
  };
790
+ EmailComponent.storyName = 'email';
644
791
 
645
- export const Telephone = ( {
792
+ export const TelephoneComponent = ( {
646
793
  type,
647
794
  Edit,
648
795
  }: {
@@ -662,8 +809,9 @@ export const Telephone = ( {
662
809
  />
663
810
  );
664
811
  };
812
+ TelephoneComponent.storyName = 'telephone';
665
813
 
666
- export const Url = ( {
814
+ export const UrlComponent = ( {
667
815
  type,
668
816
  Edit,
669
817
  }: {
@@ -677,8 +825,9 @@ export const Url = ( {
677
825
 
678
826
  return <FieldTypeStory fields={ urlFields } type={ type } Edit={ Edit } />;
679
827
  };
828
+ UrlComponent.storyName = 'url';
680
829
 
681
- export const Color = ( {
830
+ export const ColorComponent = ( {
682
831
  type,
683
832
  Edit,
684
833
  }: {
@@ -694,8 +843,9 @@ export const Color = ( {
694
843
  <FieldTypeStory fields={ colorFields } type={ type } Edit={ Edit } />
695
844
  );
696
845
  };
846
+ ColorComponent.storyName = 'color';
697
847
 
698
- export const Media = ( {
848
+ export const MediaComponent = ( {
699
849
  type,
700
850
  Edit,
701
851
  }: {
@@ -711,8 +861,9 @@ export const Media = ( {
711
861
  <FieldTypeStory fields={ mediaFields } type={ type } Edit={ Edit } />
712
862
  );
713
863
  };
864
+ MediaComponent.storyName = 'media';
714
865
 
715
- export const Array = ( {
866
+ export const ArrayComponent = ( {
716
867
  type,
717
868
  Edit,
718
869
  }: {
@@ -732,8 +883,9 @@ export const Array = ( {
732
883
  />
733
884
  );
734
885
  };
886
+ ArrayComponent.storyName = 'array';
735
887
 
736
- export const Password = ( {
888
+ export const PasswordComponent = ( {
737
889
  type,
738
890
  Edit,
739
891
  }: {
@@ -749,8 +901,9 @@ export const Password = ( {
749
901
  <FieldTypeStory fields={ passwordFields } type={ type } Edit={ Edit } />
750
902
  );
751
903
  };
904
+ PasswordComponent.storyName = 'password';
752
905
 
753
- export const NoType = ( {
906
+ export const NoTypeComponent = ( {
754
907
  type,
755
908
  Edit,
756
909
  }: {
@@ -766,3 +919,4 @@ export const NoType = ( {
766
919
  <FieldTypeStory fields={ noTypeFields } type={ type } Edit={ Edit } />
767
920
  );
768
921
  };
922
+ NoTypeComponent.storyName = 'No type';
package/src/index.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export { default as DataViews } from './components/dataviews';
2
+ export { default as DataViewsPicker } from './components/dataviews-picker';
2
3
  export { default as DataForm } from './components/dataform';
3
4
  export { VIEW_LAYOUTS } from './dataviews-layouts';
4
5
  export { filterSortAndPaginate } from './filter-and-sort-data-view';
@@ -37,6 +37,22 @@ const getValueFromId =
37
37
  return value;
38
38
  };
39
39
 
40
+ export const setValueFromId =
41
+ ( id: string ) =>
42
+ ( { value }: { value: any } ) => {
43
+ const path = id.split( '.' );
44
+ const result: any = {};
45
+ let current = result;
46
+
47
+ for ( const segment of path.slice( 0, -1 ) ) {
48
+ current[ segment ] = {};
49
+ current = current[ segment ];
50
+ }
51
+
52
+ current[ path.at( -1 )! ] = value;
53
+ return result;
54
+ };
55
+
40
56
  function getFilterBy< Item >(
41
57
  field: Field< Item >,
42
58
  fieldTypeDefinition: FieldTypeDefinition< Item >
@@ -128,6 +144,7 @@ export function normalizeFields< Item >(
128
144
  field.type
129
145
  );
130
146
  const getValue = field.getValue || getValueFromId( field.id );
147
+ const setValue = field.setValue || setValueFromId( field.id );
131
148
 
132
149
  const sort =
133
150
  field.sort ??
@@ -166,6 +183,7 @@ export function normalizeFields< Item >(
166
183
  label: field.label || field.id,
167
184
  header: field.header || field.label || field.id,
168
185
  getValue,
186
+ setValue,
169
187
  render,
170
188
  sort,
171
189
  isValid,
@@ -144,6 +144,42 @@ describe( 'DataForm component', () => {
144
144
  }
145
145
  } );
146
146
 
147
+ it( 'should allow decimal input for number fields', async () => {
148
+ const onChange = jest.fn();
149
+ const fieldsWithNumber = [
150
+ ...fields,
151
+ {
152
+ id: 'price',
153
+ label: 'Price',
154
+ type: 'number' as const,
155
+ },
156
+ ];
157
+ const formWithNumber = {
158
+ ...form,
159
+ fields: [ ...form.fields, 'price' ],
160
+ };
161
+ render(
162
+ <Dataform
163
+ onChange={ onChange }
164
+ fields={ fieldsWithNumber }
165
+ form={ formWithNumber }
166
+ data={ { ...data, price: 2.5 } }
167
+ />
168
+ );
169
+
170
+ const priceInput = screen.getByRole( 'spinbutton', {
171
+ name: /price/i,
172
+ } );
173
+ expect( priceInput ).toHaveValue( 2.5 );
174
+
175
+ const user = userEvent.setup();
176
+ await user.clear( priceInput );
177
+ await user.type( priceInput, '3.75' );
178
+
179
+ expect( onChange ).toHaveBeenLastCalledWith( { price: 3.75 } );
180
+ expect( priceInput ).toHaveValue( 3.75 );
181
+ } );
182
+
147
183
  it( 'should wrap fields in HStack when labelPosition is set to side', async () => {
148
184
  const { container } = render(
149
185
  <Dataform