@wordpress/dataviews 4.0.0 → 4.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 (214) hide show
  1. package/CHANGELOG.md +16 -5
  2. package/build/components/dataform/index.js +10 -61
  3. package/build/components/dataform/index.js.map +1 -1
  4. package/build/components/dataviews/index.js +16 -5
  5. package/build/components/dataviews/index.js.map +1 -1
  6. package/build/components/dataviews-bulk-actions/index.js +3 -0
  7. package/build/components/dataviews-bulk-actions/index.js.map +1 -1
  8. package/build/components/dataviews-filters/add-filter.js +34 -17
  9. package/build/components/dataviews-filters/add-filter.js.map +1 -1
  10. package/build/components/dataviews-filters/index.js +106 -43
  11. package/build/components/dataviews-filters/index.js.map +1 -1
  12. package/build/components/dataviews-layout/index.js +2 -2
  13. package/build/components/dataviews-layout/index.js.map +1 -1
  14. package/build/components/dataviews-search/index.js +8 -5
  15. package/build/components/dataviews-search/index.js.map +1 -1
  16. package/build/components/dataviews-view-config/index.js +225 -190
  17. package/build/components/dataviews-view-config/index.js.map +1 -1
  18. package/build/constants.js +6 -1
  19. package/build/constants.js.map +1 -1
  20. package/build/dataforms-layouts/index.js +24 -0
  21. package/build/dataforms-layouts/index.js.map +1 -0
  22. package/build/dataforms-layouts/panel/index.js +129 -0
  23. package/build/dataforms-layouts/panel/index.js.map +1 -0
  24. package/build/dataforms-layouts/regular/index.js +39 -0
  25. package/build/dataforms-layouts/regular/index.js.map +1 -0
  26. package/build/{layouts → dataviews-layouts}/grid/density-picker.js +1 -1
  27. package/build/dataviews-layouts/grid/density-picker.js.map +1 -0
  28. package/build/{layouts → dataviews-layouts}/grid/index.js +8 -8
  29. package/build/dataviews-layouts/grid/index.js.map +1 -0
  30. package/build/dataviews-layouts/index.js.map +1 -0
  31. package/build/dataviews-layouts/list/index.js.map +1 -0
  32. package/build/{layouts → dataviews-layouts}/table/column-header-menu.js +1 -1
  33. package/build/dataviews-layouts/table/column-header-menu.js.map +1 -0
  34. package/build/dataviews-layouts/table/index.js.map +1 -0
  35. package/build/field-types/index.js +46 -0
  36. package/build/field-types/index.js.map +1 -0
  37. package/build/field-types/integer.js +94 -0
  38. package/build/field-types/integer.js.map +1 -0
  39. package/build/field-types/text.js +87 -0
  40. package/build/field-types/text.js.map +1 -0
  41. package/build/filter-and-sort-data-view.js +2 -11
  42. package/build/filter-and-sort-data-view.js.map +1 -1
  43. package/build/index.js +9 -2
  44. package/build/index.js.map +1 -1
  45. package/build/normalize-fields.js +35 -1
  46. package/build/normalize-fields.js.map +1 -1
  47. package/build/types.js.map +1 -1
  48. package/build/validation.js +22 -0
  49. package/build/validation.js.map +1 -0
  50. package/build-module/components/dataform/index.js +10 -61
  51. package/build-module/components/dataform/index.js.map +1 -1
  52. package/build-module/components/dataviews/index.js +14 -5
  53. package/build-module/components/dataviews/index.js.map +1 -1
  54. package/build-module/components/dataviews-bulk-actions/index.js +3 -0
  55. package/build-module/components/dataviews-bulk-actions/index.js.map +1 -1
  56. package/build-module/components/dataviews-filters/add-filter.js +33 -17
  57. package/build-module/components/dataviews-filters/add-filter.js.map +1 -1
  58. package/build-module/components/dataviews-filters/index.js +105 -45
  59. package/build-module/components/dataviews-filters/index.js.map +1 -1
  60. package/build-module/components/dataviews-layout/index.js +1 -1
  61. package/build-module/components/dataviews-layout/index.js.map +1 -1
  62. package/build-module/components/dataviews-search/index.js +8 -5
  63. package/build-module/components/dataviews-search/index.js.map +1 -1
  64. package/build-module/components/dataviews-view-config/index.js +228 -193
  65. package/build-module/components/dataviews-view-config/index.js.map +1 -1
  66. package/build-module/constants.js +5 -0
  67. package/build-module/constants.js.map +1 -1
  68. package/build-module/dataforms-layouts/index.js +16 -0
  69. package/build-module/dataforms-layouts/index.js.map +1 -0
  70. package/build-module/dataforms-layouts/panel/index.js +124 -0
  71. package/build-module/dataforms-layouts/panel/index.js.map +1 -0
  72. package/build-module/dataforms-layouts/regular/index.js +32 -0
  73. package/build-module/dataforms-layouts/regular/index.js.map +1 -0
  74. package/build-module/{layouts → dataviews-layouts}/grid/density-picker.js +2 -2
  75. package/build-module/dataviews-layouts/grid/density-picker.js.map +1 -0
  76. package/build-module/{layouts → dataviews-layouts}/grid/index.js +8 -8
  77. package/build-module/dataviews-layouts/grid/index.js.map +1 -0
  78. package/build-module/dataviews-layouts/index.js.map +1 -0
  79. package/build-module/dataviews-layouts/list/index.js.map +1 -0
  80. package/build-module/{layouts → dataviews-layouts}/table/column-header-menu.js +1 -1
  81. package/build-module/dataviews-layouts/table/column-header-menu.js.map +1 -0
  82. package/build-module/dataviews-layouts/table/index.js.map +1 -0
  83. package/build-module/field-types/index.js +40 -0
  84. package/build-module/field-types/index.js.map +1 -0
  85. package/build-module/field-types/integer.js +87 -0
  86. package/build-module/field-types/integer.js.map +1 -0
  87. package/build-module/field-types/text.js +80 -0
  88. package/build-module/field-types/text.js.map +1 -0
  89. package/build-module/filter-and-sort-data-view.js +2 -11
  90. package/build-module/filter-and-sort-data-view.js.map +1 -1
  91. package/build-module/index.js +2 -1
  92. package/build-module/index.js.map +1 -1
  93. package/build-module/normalize-fields.js +34 -2
  94. package/build-module/normalize-fields.js.map +1 -1
  95. package/build-module/types.js.map +1 -1
  96. package/build-module/validation.js +15 -0
  97. package/build-module/validation.js.map +1 -0
  98. package/build-style/style-rtl.css +175 -6
  99. package/build-style/style.css +175 -6
  100. package/build-types/components/dataform/index.d.ts +2 -13
  101. package/build-types/components/dataform/index.d.ts.map +1 -1
  102. package/build-types/components/dataform/stories/index.story.d.ts +12 -1
  103. package/build-types/components/dataform/stories/index.story.d.ts.map +1 -1
  104. package/build-types/components/dataviews/index.d.ts.map +1 -1
  105. package/build-types/components/dataviews/stories/fixtures.d.ts +6 -0
  106. package/build-types/components/dataviews/stories/fixtures.d.ts.map +1 -1
  107. package/build-types/components/dataviews-bulk-actions/index.d.ts.map +1 -1
  108. package/build-types/components/dataviews-filters/add-filter.d.ts +3 -0
  109. package/build-types/components/dataviews-filters/add-filter.d.ts.map +1 -1
  110. package/build-types/components/dataviews-filters/index.d.ts +11 -1
  111. package/build-types/components/dataviews-filters/index.d.ts.map +1 -1
  112. package/build-types/components/dataviews-search/index.d.ts.map +1 -1
  113. package/build-types/components/dataviews-view-config/index.d.ts +1 -1
  114. package/build-types/components/dataviews-view-config/index.d.ts.map +1 -1
  115. package/build-types/constants.d.ts +4 -0
  116. package/build-types/constants.d.ts.map +1 -1
  117. package/build-types/dataforms-layouts/index.d.ts +9 -0
  118. package/build-types/dataforms-layouts/index.d.ts.map +1 -0
  119. package/build-types/dataforms-layouts/panel/index.d.ts +3 -0
  120. package/build-types/dataforms-layouts/panel/index.d.ts.map +1 -0
  121. package/build-types/dataforms-layouts/regular/index.d.ts +3 -0
  122. package/build-types/dataforms-layouts/regular/index.d.ts.map +1 -0
  123. package/build-types/dataviews-layouts/grid/density-picker.d.ts.map +1 -0
  124. package/build-types/dataviews-layouts/grid/index.d.ts.map +1 -0
  125. package/build-types/dataviews-layouts/index.d.ts.map +1 -0
  126. package/build-types/dataviews-layouts/list/index.d.ts.map +1 -0
  127. package/build-types/dataviews-layouts/table/column-header-menu.d.ts.map +1 -0
  128. package/build-types/dataviews-layouts/table/index.d.ts.map +1 -0
  129. package/build-types/field-types/index.d.ts +20 -0
  130. package/build-types/field-types/index.d.ts.map +1 -0
  131. package/build-types/field-types/integer.d.ts +14 -0
  132. package/build-types/field-types/integer.d.ts.map +1 -0
  133. package/build-types/field-types/text.d.ts +14 -0
  134. package/build-types/field-types/text.d.ts.map +1 -0
  135. package/build-types/filter-and-sort-data-view.d.ts.map +1 -1
  136. package/build-types/index.d.ts +2 -1
  137. package/build-types/index.d.ts.map +1 -1
  138. package/build-types/normalize-fields.d.ts +0 -3
  139. package/build-types/normalize-fields.d.ts.map +1 -1
  140. package/build-types/types.d.ts +38 -3
  141. package/build-types/types.d.ts.map +1 -1
  142. package/build-types/validation.d.ts +3 -0
  143. package/build-types/validation.d.ts.map +1 -0
  144. package/package.json +12 -11
  145. package/src/components/dataform/index.tsx +8 -97
  146. package/src/components/dataform/stories/index.story.tsx +40 -3
  147. package/src/components/dataviews/index.tsx +20 -8
  148. package/src/components/dataviews/stories/fixtures.js +1 -0
  149. package/src/components/dataviews/style.scss +5 -2
  150. package/src/components/dataviews-bulk-actions/index.tsx +5 -0
  151. package/src/components/dataviews-filters/add-filter.tsx +37 -21
  152. package/src/components/dataviews-filters/index.tsx +149 -61
  153. package/src/components/dataviews-filters/style.scss +30 -0
  154. package/src/components/dataviews-layout/index.tsx +1 -1
  155. package/src/components/dataviews-search/index.tsx +8 -5
  156. package/src/components/dataviews-view-config/index.tsx +272 -258
  157. package/src/components/dataviews-view-config/style.scss +44 -0
  158. package/src/constants.ts +5 -0
  159. package/src/dataforms-layouts/index.tsx +20 -0
  160. package/src/dataforms-layouts/panel/index.tsx +164 -0
  161. package/src/dataforms-layouts/panel/style.scss +59 -0
  162. package/src/dataforms-layouts/regular/index.tsx +41 -0
  163. package/src/{layouts → dataviews-layouts}/grid/density-picker.tsx +2 -2
  164. package/src/{layouts → dataviews-layouts}/grid/index.tsx +8 -8
  165. package/src/{layouts → dataviews-layouts}/grid/style.scss +29 -0
  166. package/src/{layouts → dataviews-layouts}/list/style.scss +4 -1
  167. package/src/{layouts → dataviews-layouts}/table/column-header-menu.tsx +1 -1
  168. package/src/field-types/index.tsx +45 -0
  169. package/src/field-types/integer.tsx +103 -0
  170. package/src/field-types/text.tsx +95 -0
  171. package/src/filter-and-sort-data-view.ts +1 -15
  172. package/src/index.ts +2 -1
  173. package/src/normalize-fields.ts +44 -3
  174. package/src/style.scss +6 -3
  175. package/src/test/filter-and-sort-data-view.js +46 -3
  176. package/src/test/validation.ts +131 -0
  177. package/src/types.ts +50 -3
  178. package/src/validation.ts +18 -0
  179. package/tsconfig.json +2 -1
  180. package/tsconfig.tsbuildinfo +1 -1
  181. package/build/layouts/grid/density-picker.js.map +0 -1
  182. package/build/layouts/grid/index.js.map +0 -1
  183. package/build/layouts/index.js.map +0 -1
  184. package/build/layouts/list/index.js.map +0 -1
  185. package/build/layouts/table/column-header-menu.js.map +0 -1
  186. package/build/layouts/table/index.js.map +0 -1
  187. package/build-module/layouts/grid/density-picker.js.map +0 -1
  188. package/build-module/layouts/grid/index.js.map +0 -1
  189. package/build-module/layouts/index.js.map +0 -1
  190. package/build-module/layouts/list/index.js.map +0 -1
  191. package/build-module/layouts/table/column-header-menu.js.map +0 -1
  192. package/build-module/layouts/table/index.js.map +0 -1
  193. package/build-types/layouts/grid/density-picker.d.ts.map +0 -1
  194. package/build-types/layouts/grid/index.d.ts.map +0 -1
  195. package/build-types/layouts/index.d.ts.map +0 -1
  196. package/build-types/layouts/list/index.d.ts.map +0 -1
  197. package/build-types/layouts/table/column-header-menu.d.ts.map +0 -1
  198. package/build-types/layouts/table/index.d.ts.map +0 -1
  199. /package/build/{layouts → dataviews-layouts}/index.js +0 -0
  200. /package/build/{layouts → dataviews-layouts}/list/index.js +0 -0
  201. /package/build/{layouts → dataviews-layouts}/table/index.js +0 -0
  202. /package/build-module/{layouts → dataviews-layouts}/index.js +0 -0
  203. /package/build-module/{layouts → dataviews-layouts}/list/index.js +0 -0
  204. /package/build-module/{layouts → dataviews-layouts}/table/index.js +0 -0
  205. /package/build-types/{layouts → dataviews-layouts}/grid/density-picker.d.ts +0 -0
  206. /package/build-types/{layouts → dataviews-layouts}/grid/index.d.ts +0 -0
  207. /package/build-types/{layouts → dataviews-layouts}/index.d.ts +0 -0
  208. /package/build-types/{layouts → dataviews-layouts}/list/index.d.ts +0 -0
  209. /package/build-types/{layouts → dataviews-layouts}/table/column-header-menu.d.ts +0 -0
  210. /package/build-types/{layouts → dataviews-layouts}/table/index.d.ts +0 -0
  211. /package/src/{layouts → dataviews-layouts}/index.ts +0 -0
  212. /package/src/{layouts → dataviews-layouts}/list/index.tsx +0 -0
  213. /package/src/{layouts → dataviews-layouts}/table/index.tsx +0 -0
  214. /package/src/{layouts → dataviews-layouts}/table/style.scss +0 -0
@@ -1,7 +1,8 @@
1
1
  /**
2
2
  * Internal dependencies
3
3
  */
4
- import type { Field, NormalizedField, ItemRecord } from './types';
4
+ import getFieldTypeDefinition from './field-types';
5
+ import type { Field, NormalizedField } from './types';
5
6
 
6
7
  /**
7
8
  * Apply default values and normalize the fields config.
@@ -13,15 +14,55 @@ export function normalizeFields< Item >(
13
14
  fields: Field< Item >[]
14
15
  ): NormalizedField< Item >[] {
15
16
  return fields.map( ( field ) => {
17
+ const fieldTypeDefinition = getFieldTypeDefinition( field.type );
18
+
16
19
  const getValue =
17
20
  field.getValue ||
18
- ( ( { item }: { item: ItemRecord } ) => item[ field.id ] );
21
+ ( ( { item }: { item: Item } ) => item[ field.id as keyof Item ] );
22
+
23
+ const sort =
24
+ field.sort ??
25
+ function sort( a, b, direction ) {
26
+ return fieldTypeDefinition.sort(
27
+ getValue( { item: a } ),
28
+ getValue( { item: b } ),
29
+ direction
30
+ );
31
+ };
32
+
33
+ const isValid =
34
+ field.isValid ??
35
+ function isValid( item, context ) {
36
+ return fieldTypeDefinition.isValid(
37
+ getValue( { item } ),
38
+ context
39
+ );
40
+ };
41
+
42
+ const Edit = field.Edit || fieldTypeDefinition.Edit;
43
+
44
+ const renderFromElements = ( { item }: { item: Item } ) => {
45
+ const value = getValue( { item } );
46
+ const label = field?.elements?.find( ( element ) => {
47
+ // Intentionally using == here to allow for type coercion.
48
+ // eslint-disable-next-line eqeqeq
49
+ return element.value == value;
50
+ } )?.label;
51
+
52
+ return label || value;
53
+ };
54
+
55
+ const render =
56
+ field.render || ( field.elements ? renderFromElements : getValue );
19
57
 
20
58
  return {
21
59
  ...field,
22
60
  label: field.label || field.id,
23
61
  getValue,
24
- render: field.render || getValue,
62
+ render,
63
+ sort,
64
+ isValid,
65
+ Edit,
25
66
  };
26
67
  } );
27
68
  }
package/src/style.scss CHANGED
@@ -5,7 +5,10 @@
5
5
  @import "./components/dataviews-pagination/style.scss";
6
6
  @import "./components/dataviews-item-actions/style.scss";
7
7
  @import "./components/dataviews-selection-checkbox/style.scss";
8
+ @import "./components/dataviews-view-config/style.scss";
8
9
 
9
- @import "./layouts/grid/style.scss";
10
- @import "./layouts/list/style.scss";
11
- @import "./layouts/table/style.scss";
10
+ @import "./dataviews-layouts/grid/style.scss";
11
+ @import "./dataviews-layouts/list/style.scss";
12
+ @import "./dataviews-layouts/table/style.scss";
13
+
14
+ @import "./dataforms-layouts/panel/style.scss";
@@ -233,7 +233,22 @@ describe( 'filters', () => {
233
233
  } );
234
234
 
235
235
  describe( 'sorting', () => {
236
- it( 'should sort by string', () => {
236
+ it( 'should sort integer field types', () => {
237
+ const { data: result } = filterSortAndPaginate(
238
+ data,
239
+ {
240
+ sort: { field: 'satellites', direction: 'desc' },
241
+ },
242
+ fields
243
+ );
244
+
245
+ expect( result ).toHaveLength( 11 );
246
+ expect( result[ 0 ].title ).toBe( 'Saturn' );
247
+ expect( result[ 1 ].title ).toBe( 'Jupiter' );
248
+ expect( result[ 2 ].title ).toBe( 'Uranus' );
249
+ } );
250
+
251
+ it( 'should sort text field types', () => {
237
252
  const { data: result } = filterSortAndPaginate(
238
253
  data,
239
254
  {
@@ -253,13 +268,18 @@ describe( 'sorting', () => {
253
268
  expect( result[ 1 ].title ).toBe( 'Neptune' );
254
269
  } );
255
270
 
256
- it( 'should sort by number', () => {
271
+ it( 'should sort untyped fields if the value is a number', () => {
257
272
  const { data: result } = filterSortAndPaginate(
258
273
  data,
259
274
  {
260
275
  sort: { field: 'satellites', direction: 'desc' },
261
276
  },
262
- fields
277
+ // Remove type information for satellites field to test sorting untyped fields.
278
+ fields.map( ( field ) =>
279
+ field.id === 'satellites'
280
+ ? { ...field, type: undefined }
281
+ : field
282
+ )
263
283
  );
264
284
 
265
285
  expect( result ).toHaveLength( 11 );
@@ -267,6 +287,29 @@ describe( 'sorting', () => {
267
287
  expect( result[ 1 ].title ).toBe( 'Jupiter' );
268
288
  expect( result[ 2 ].title ).toBe( 'Uranus' );
269
289
  } );
290
+
291
+ it( 'should sort untyped fields if the value is string', () => {
292
+ const { data: result } = filterSortAndPaginate(
293
+ data,
294
+ {
295
+ sort: { field: 'title', direction: 'desc' },
296
+ filters: [
297
+ {
298
+ field: 'type',
299
+ operator: 'isAny',
300
+ value: [ 'Ice giant' ],
301
+ },
302
+ ],
303
+ },
304
+ // Remove type information for the title field to test sorting untyped fields.
305
+ fields.map( ( field ) =>
306
+ field.id === 'title' ? { ...field, type: undefined } : field
307
+ )
308
+ );
309
+ expect( result ).toHaveLength( 2 );
310
+ expect( result[ 0 ].title ).toBe( 'Uranus' );
311
+ expect( result[ 1 ].title ).toBe( 'Neptune' );
312
+ } );
270
313
  } );
271
314
 
272
315
  describe( 'pagination', () => {
@@ -0,0 +1,131 @@
1
+ /**
2
+ * Internal dependencies
3
+ */
4
+ import { isItemValid } from '../validation';
5
+ import type { Field } from '../types';
6
+
7
+ describe( 'validation', () => {
8
+ it( 'fields not visible in form are not validated', () => {
9
+ const item = { id: 1, valid_order: 2, invalid_order: 'd' };
10
+ const fields: Field< {} >[] = [
11
+ {
12
+ id: 'valid_order',
13
+ type: 'integer',
14
+ },
15
+ {
16
+ id: 'invalid_order',
17
+ type: 'integer',
18
+ },
19
+ ];
20
+ const form = { fields: [ 'valid_order' ] };
21
+ const result = isItemValid( item, fields, form );
22
+ expect( result ).toBe( true );
23
+ } );
24
+
25
+ it( 'integer field is valid if value is integer', () => {
26
+ const item = { id: 1, order: 2, title: 'hi' };
27
+ const fields: Field< {} >[] = [
28
+ {
29
+ type: 'integer',
30
+ id: 'order',
31
+ },
32
+ ];
33
+ const form = { fields: [ 'order' ] };
34
+ const result = isItemValid( item, fields, form );
35
+ expect( result ).toBe( true );
36
+ } );
37
+
38
+ it( 'integer field is invalid if value is not integer', () => {
39
+ const item = { id: 1, order: 'd' };
40
+ const fields: Field< {} >[] = [
41
+ {
42
+ id: 'order',
43
+ type: 'integer',
44
+ },
45
+ ];
46
+ const form = { fields: [ 'order' ] };
47
+ const result = isItemValid( item, fields, form );
48
+ expect( result ).toBe( false );
49
+ } );
50
+
51
+ it( 'integer field is invalid if value is empty', () => {
52
+ const item = { id: 1, order: '' };
53
+ const fields: Field< {} >[] = [
54
+ {
55
+ id: 'order',
56
+ type: 'integer',
57
+ },
58
+ ];
59
+ const form = { fields: [ 'order' ] };
60
+ const result = isItemValid( item, fields, form );
61
+ expect( result ).toBe( false );
62
+ } );
63
+
64
+ it( 'integer field is invalid if value is not one of the elements', () => {
65
+ const item = { id: 1, author: 3 };
66
+ const fields: Field< {} >[] = [
67
+ {
68
+ id: 'author',
69
+ type: 'integer',
70
+ elements: [
71
+ { value: 1, label: 'Jane' },
72
+ { value: 2, label: 'John' },
73
+ ],
74
+ },
75
+ ];
76
+ const form = { fields: [ 'author' ] };
77
+ const result = isItemValid( item, fields, form );
78
+ expect( result ).toBe( false );
79
+ } );
80
+
81
+ it( 'text field is invalid if value is not one of the elements', () => {
82
+ const item = { id: 1, author: 'not-in-elements' };
83
+ const fields: Field< {} >[] = [
84
+ {
85
+ id: 'author',
86
+ type: 'text',
87
+ elements: [
88
+ { value: 'jane', label: 'Jane' },
89
+ { value: 'john', label: 'John' },
90
+ ],
91
+ },
92
+ ];
93
+ const form = { fields: [ 'author' ] };
94
+ const result = isItemValid( item, fields, form );
95
+ expect( result ).toBe( false );
96
+ } );
97
+
98
+ it( 'untyped field is invalid if value is not one of the elements', () => {
99
+ const item = { id: 1, author: 'not-in-elements' };
100
+ const fields: Field< {} >[] = [
101
+ {
102
+ id: 'author',
103
+ elements: [
104
+ { value: 'jane', label: 'Jane' },
105
+ { value: 'john', label: 'John' },
106
+ ],
107
+ },
108
+ ];
109
+ const form = { fields: [ 'author' ] };
110
+ const result = isItemValid( item, fields, form );
111
+ expect( result ).toBe( false );
112
+ } );
113
+
114
+ it( 'fields can provide its own isValid function', () => {
115
+ const item = { id: 1, order: 'd' };
116
+ const fields: Field< {} >[] = [
117
+ {
118
+ id: 'order',
119
+ type: 'integer',
120
+ elements: [
121
+ { value: 'a', label: 'A' },
122
+ { value: 'b', label: 'B' },
123
+ ],
124
+ isValid: () => true, // Overrides the validation provided for integer types.
125
+ },
126
+ ];
127
+ const form = { fields: [ 'order' ] };
128
+ const result = isItemValid( item, fields, form );
129
+ expect( result ).toBe( true );
130
+ } );
131
+ } );
package/src/types.ts CHANGED
@@ -1,7 +1,12 @@
1
1
  /**
2
2
  * External dependencies
3
3
  */
4
- import type { ReactElement, ComponentType } from 'react';
4
+ import type {
5
+ ReactElement,
6
+ ComponentType,
7
+ Dispatch,
8
+ SetStateAction,
9
+ } from 'react';
5
10
 
6
11
  /**
7
12
  * Internal dependencies
@@ -44,7 +49,11 @@ export type Operator =
44
49
 
45
50
  export type ItemRecord = Record< string, unknown >;
46
51
 
47
- export type FieldType = 'text';
52
+ export type FieldType = 'text' | 'integer';
53
+
54
+ export type ValidationContext = {
55
+ elements?: Option[];
56
+ };
48
57
 
49
58
  /**
50
59
  * A dataview field for a specific property of a data type.
@@ -65,6 +74,11 @@ export type Field< Item > = {
65
74
  */
66
75
  label?: string;
67
76
 
77
+ /**
78
+ * A description of the field.
79
+ */
80
+ description?: string;
81
+
68
82
  /**
69
83
  * Placeholder for the field.
70
84
  */
@@ -75,6 +89,21 @@ export type Field< Item > = {
75
89
  */
76
90
  render?: ComponentType< { item: Item } >;
77
91
 
92
+ /**
93
+ * Callback used to render an edit control for the field.
94
+ */
95
+ Edit?: ComponentType< DataFormControlProps< Item > >;
96
+
97
+ /**
98
+ * Callback used to sort the field.
99
+ */
100
+ sort?: ( a: Item, b: Item, direction: SortDirection ) => number;
101
+
102
+ /**
103
+ * Callback used to validate the field.
104
+ */
105
+ isValid?: ( item: Item, context?: ValidationContext ) => boolean;
106
+
78
107
  /**
79
108
  * Whether the field is sortable.
80
109
  */
@@ -119,6 +148,9 @@ export type NormalizedField< Item > = Field< Item > & {
119
148
  label: string;
120
149
  getValue: ( args: { item: Item } ) => any;
121
150
  render: ComponentType< { item: Item } >;
151
+ Edit: ComponentType< DataFormControlProps< Item > >;
152
+ sort: ( a: Item, b: Item, direction: SortDirection ) => number;
153
+ isValid: ( item: Item, context?: ValidationContext ) => boolean;
122
154
  };
123
155
 
124
156
  /**
@@ -132,7 +164,15 @@ export type Data< Item > = Item[];
132
164
  * The form configuration.
133
165
  */
134
166
  export type Form = {
135
- visibleFields?: string[];
167
+ type?: 'regular' | 'panel';
168
+ fields?: string[];
169
+ };
170
+
171
+ export type DataFormControlProps< Item > = {
172
+ data: Item;
173
+ field: NormalizedField< Item >;
174
+ onChange: Dispatch< SetStateAction< Item > >;
175
+ hideLabelFromVision?: boolean;
136
176
  };
137
177
 
138
178
  /**
@@ -459,3 +499,10 @@ export interface SupportedLayouts {
459
499
  grid?: Omit< ViewGrid, 'type' >;
460
500
  table?: Omit< ViewTable, 'type' >;
461
501
  }
502
+
503
+ export interface DataFormProps< Item > {
504
+ data: Item;
505
+ fields: Field< Item >[];
506
+ form: Form;
507
+ onChange: Dispatch< SetStateAction< Item > >;
508
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Internal dependencies
3
+ */
4
+ import { normalizeFields } from './normalize-fields';
5
+ import type { Field, Form } from './types';
6
+
7
+ export function isItemValid< Item >(
8
+ item: Item,
9
+ fields: Field< Item >[],
10
+ form: Form
11
+ ): boolean {
12
+ const _fields = normalizeFields(
13
+ fields.filter( ( { id } ) => !! form.fields?.includes( id ) )
14
+ );
15
+ return _fields.every( ( field ) => {
16
+ return field.isValid( item, { elements: field.elements } );
17
+ } );
18
+ }
package/tsconfig.json CHANGED
@@ -14,7 +14,8 @@
14
14
  { "path": "../i18n" },
15
15
  { "path": "../icons" },
16
16
  { "path": "../primitives" },
17
- { "path": "../private-apis" }
17
+ { "path": "../private-apis" },
18
+ { "path": "../warning" }
18
19
  ],
19
20
  "include": [ "src" ]
20
21
  }