@wordpress/dataviews 4.1.0 → 4.2.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 (170) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +31 -23
  3. package/build/components/dataviews/index.js +9 -11
  4. package/build/components/dataviews/index.js.map +1 -1
  5. package/build/components/dataviews-filters/index.js +3 -0
  6. package/build/components/dataviews-filters/index.js.map +1 -1
  7. package/build/components/dataviews-filters/search-widget.js +2 -5
  8. package/build/components/dataviews-filters/search-widget.js.map +1 -1
  9. package/build/components/dataviews-pagination/index.js +23 -15
  10. package/build/components/dataviews-pagination/index.js.map +1 -1
  11. package/build/components/dataviews-view-config/index.js +26 -9
  12. package/build/components/dataviews-view-config/index.js.map +1 -1
  13. package/build/dataform-controls/datetime.js +49 -0
  14. package/build/dataform-controls/datetime.js.map +1 -0
  15. package/build/dataform-controls/index.js +50 -0
  16. package/build/dataform-controls/index.js.map +1 -0
  17. package/build/dataform-controls/integer.js +45 -0
  18. package/build/dataform-controls/integer.js.map +1 -0
  19. package/build/dataform-controls/radio.js +45 -0
  20. package/build/dataform-controls/radio.js.map +1 -0
  21. package/build/dataform-controls/select.js +58 -0
  22. package/build/dataform-controls/select.js.map +1 -0
  23. package/build/dataform-controls/text.js +45 -0
  24. package/build/dataform-controls/text.js.map +1 -0
  25. package/build/dataforms-layouts/panel/index.js +6 -3
  26. package/build/dataforms-layouts/panel/index.js.map +1 -1
  27. package/build/dataforms-layouts/regular/index.js +6 -3
  28. package/build/dataforms-layouts/regular/index.js.map +1 -1
  29. package/build/dataviews-layouts/grid/density-picker.js +23 -52
  30. package/build/dataviews-layouts/grid/density-picker.js.map +1 -1
  31. package/build/dataviews-layouts/grid/index.js +1 -1
  32. package/build/dataviews-layouts/grid/index.js.map +1 -1
  33. package/build/dataviews-layouts/list/index.js +6 -2
  34. package/build/dataviews-layouts/list/index.js.map +1 -1
  35. package/build/dataviews-layouts/table/column-header-menu.js +2 -5
  36. package/build/dataviews-layouts/table/column-header-menu.js.map +1 -1
  37. package/build/field-types/datetime.js +30 -0
  38. package/build/field-types/datetime.js.map +1 -0
  39. package/build/field-types/index.js +4 -0
  40. package/build/field-types/index.js.map +1 -1
  41. package/build/field-types/integer.js +1 -60
  42. package/build/field-types/integer.js.map +1 -1
  43. package/build/field-types/text.js +1 -60
  44. package/build/field-types/text.js.map +1 -1
  45. package/build/normalize-fields.js +6 -7
  46. package/build/normalize-fields.js.map +1 -1
  47. package/build/types.js.map +1 -1
  48. package/build-module/components/dataviews/index.js +9 -11
  49. package/build-module/components/dataviews/index.js.map +1 -1
  50. package/build-module/components/dataviews-filters/index.js +3 -0
  51. package/build-module/components/dataviews-filters/index.js.map +1 -1
  52. package/build-module/components/dataviews-filters/search-widget.js +2 -5
  53. package/build-module/components/dataviews-filters/search-widget.js.map +1 -1
  54. package/build-module/components/dataviews-pagination/index.js +23 -15
  55. package/build-module/components/dataviews-pagination/index.js.map +1 -1
  56. package/build-module/components/dataviews-view-config/index.js +27 -10
  57. package/build-module/components/dataviews-view-config/index.js.map +1 -1
  58. package/build-module/dataform-controls/datetime.js +43 -0
  59. package/build-module/dataform-controls/datetime.js.map +1 -0
  60. package/build-module/dataform-controls/index.js +42 -0
  61. package/build-module/dataform-controls/index.js.map +1 -0
  62. package/build-module/dataform-controls/integer.js +38 -0
  63. package/build-module/dataform-controls/integer.js.map +1 -0
  64. package/build-module/dataform-controls/radio.js +38 -0
  65. package/build-module/dataform-controls/radio.js.map +1 -0
  66. package/build-module/dataform-controls/select.js +51 -0
  67. package/build-module/dataform-controls/select.js.map +1 -0
  68. package/build-module/dataform-controls/text.js +38 -0
  69. package/build-module/dataform-controls/text.js.map +1 -0
  70. package/build-module/dataforms-layouts/panel/index.js +6 -3
  71. package/build-module/dataforms-layouts/panel/index.js.map +1 -1
  72. package/build-module/dataforms-layouts/regular/index.js +6 -3
  73. package/build-module/dataforms-layouts/regular/index.js.map +1 -1
  74. package/build-module/dataviews-layouts/grid/density-picker.js +25 -56
  75. package/build-module/dataviews-layouts/grid/density-picker.js.map +1 -1
  76. package/build-module/dataviews-layouts/grid/index.js +1 -1
  77. package/build-module/dataviews-layouts/grid/index.js.map +1 -1
  78. package/build-module/dataviews-layouts/list/index.js +5 -2
  79. package/build-module/dataviews-layouts/list/index.js.map +1 -1
  80. package/build-module/dataviews-layouts/table/column-header-menu.js +2 -5
  81. package/build-module/dataviews-layouts/table/column-header-menu.js.map +1 -1
  82. package/build-module/field-types/datetime.js +24 -0
  83. package/build-module/field-types/datetime.js.map +1 -0
  84. package/build-module/field-types/index.js +4 -0
  85. package/build-module/field-types/index.js.map +1 -1
  86. package/build-module/field-types/integer.js +2 -60
  87. package/build-module/field-types/integer.js.map +1 -1
  88. package/build-module/field-types/text.js +2 -60
  89. package/build-module/field-types/text.js.map +1 -1
  90. package/build-module/normalize-fields.js +7 -7
  91. package/build-module/normalize-fields.js.map +1 -1
  92. package/build-module/types.js.map +1 -1
  93. package/build-style/style-rtl.css +15 -18
  94. package/build-style/style.css +15 -18
  95. package/build-types/components/dataform/stories/index.story.d.ts.map +1 -1
  96. package/build-types/components/dataviews/index.d.ts.map +1 -1
  97. package/build-types/components/dataviews/stories/fixtures.d.ts +22 -3
  98. package/build-types/components/dataviews/stories/fixtures.d.ts.map +1 -1
  99. package/build-types/components/dataviews/stories/index.story.d.ts +9 -0
  100. package/build-types/components/dataviews/stories/index.story.d.ts.map +1 -1
  101. package/build-types/components/dataviews-filters/index.d.ts +1 -1
  102. package/build-types/components/dataviews-filters/index.d.ts.map +1 -1
  103. package/build-types/components/dataviews-filters/search-widget.d.ts.map +1 -1
  104. package/build-types/components/dataviews-pagination/index.d.ts.map +1 -1
  105. package/build-types/components/dataviews-view-config/index.d.ts +4 -3
  106. package/build-types/components/dataviews-view-config/index.d.ts.map +1 -1
  107. package/build-types/dataform-controls/datetime.d.ts +6 -0
  108. package/build-types/dataform-controls/datetime.d.ts.map +1 -0
  109. package/build-types/dataform-controls/index.d.ts +11 -0
  110. package/build-types/dataform-controls/index.d.ts.map +1 -0
  111. package/build-types/dataform-controls/integer.d.ts +6 -0
  112. package/build-types/dataform-controls/integer.d.ts.map +1 -0
  113. package/build-types/dataform-controls/radio.d.ts +6 -0
  114. package/build-types/dataform-controls/radio.d.ts.map +1 -0
  115. package/build-types/dataform-controls/select.d.ts +6 -0
  116. package/build-types/dataform-controls/select.d.ts.map +1 -0
  117. package/build-types/dataform-controls/text.d.ts +6 -0
  118. package/build-types/dataform-controls/text.d.ts.map +1 -0
  119. package/build-types/dataforms-layouts/panel/index.d.ts.map +1 -1
  120. package/build-types/dataforms-layouts/regular/index.d.ts.map +1 -1
  121. package/build-types/dataviews-layouts/grid/density-picker.d.ts.map +1 -1
  122. package/build-types/dataviews-layouts/list/index.d.ts.map +1 -1
  123. package/build-types/dataviews-layouts/table/column-header-menu.d.ts.map +1 -1
  124. package/build-types/field-types/datetime.d.ts +13 -0
  125. package/build-types/field-types/datetime.d.ts.map +1 -0
  126. package/build-types/field-types/index.d.ts +1 -1
  127. package/build-types/field-types/index.d.ts.map +1 -1
  128. package/build-types/field-types/integer.d.ts +2 -3
  129. package/build-types/field-types/integer.d.ts.map +1 -1
  130. package/build-types/field-types/text.d.ts +2 -3
  131. package/build-types/field-types/text.d.ts.map +1 -1
  132. package/build-types/normalize-fields.d.ts.map +1 -1
  133. package/build-types/types.d.ts +41 -21
  134. package/build-types/types.d.ts.map +1 -1
  135. package/package.json +12 -12
  136. package/src/components/dataform/stories/index.story.tsx +43 -2
  137. package/src/components/dataviews/index.tsx +13 -13
  138. package/src/components/dataviews/stories/fixtures.js +29 -1
  139. package/src/components/dataviews/stories/index.story.js +7 -1
  140. package/src/components/dataviews/style.scss +0 -12
  141. package/src/components/dataviews-bulk-actions-toolbar/style.scss +1 -1
  142. package/src/components/dataviews-filters/index.tsx +3 -0
  143. package/src/components/dataviews-filters/search-widget.tsx +1 -8
  144. package/src/components/dataviews-filters/style.scss +1 -1
  145. package/src/components/dataviews-pagination/index.tsx +35 -16
  146. package/src/components/dataviews-pagination/style.scss +9 -4
  147. package/src/components/dataviews-view-config/index.tsx +45 -16
  148. package/src/dataform-controls/datetime.tsx +43 -0
  149. package/src/dataform-controls/index.tsx +61 -0
  150. package/src/dataform-controls/integer.tsx +38 -0
  151. package/src/dataform-controls/radio.tsx +42 -0
  152. package/src/dataform-controls/select.tsx +52 -0
  153. package/src/dataform-controls/style.scss +4 -0
  154. package/src/dataform-controls/text.tsx +40 -0
  155. package/src/dataforms-layouts/panel/index.tsx +6 -2
  156. package/src/dataforms-layouts/regular/index.tsx +6 -2
  157. package/src/dataviews-layouts/grid/density-picker.tsx +33 -67
  158. package/src/dataviews-layouts/grid/index.tsx +1 -1
  159. package/src/dataviews-layouts/grid/style.scss +0 -4
  160. package/src/dataviews-layouts/list/index.tsx +6 -2
  161. package/src/dataviews-layouts/table/column-header-menu.tsx +3 -5
  162. package/src/field-types/datetime.tsx +28 -0
  163. package/src/field-types/index.tsx +5 -0
  164. package/src/field-types/integer.tsx +2 -71
  165. package/src/field-types/text.tsx +2 -70
  166. package/src/normalize-fields.ts +8 -10
  167. package/src/style.scss +1 -0
  168. package/src/test/filter-and-sort-data-view.js +28 -0
  169. package/src/types.ts +54 -32
  170. package/tsconfig.tsbuildinfo +1 -1
@@ -0,0 +1,52 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { SelectControl } from '@wordpress/components';
5
+ import { useCallback } from '@wordpress/element';
6
+ import { __ } from '@wordpress/i18n';
7
+
8
+ /**
9
+ * Internal dependencies
10
+ */
11
+ import type { DataFormControlProps } from '../types';
12
+
13
+ export default function Select< Item >( {
14
+ data,
15
+ field,
16
+ onChange,
17
+ hideLabelFromVision,
18
+ }: DataFormControlProps< Item > ) {
19
+ const { id, label } = field;
20
+ const value = field.getValue( { item: data } ) ?? '';
21
+ const onChangeControl = useCallback(
22
+ ( newValue: any ) =>
23
+ onChange( {
24
+ [ id ]: newValue,
25
+ } ),
26
+ [ id, onChange ]
27
+ );
28
+
29
+ const elements = [
30
+ /*
31
+ * Value can be undefined when:
32
+ *
33
+ * - the field is not required
34
+ * - in bulk editing
35
+ *
36
+ */
37
+ { label: __( 'Select item' ), value: '' },
38
+ ...( field?.elements ?? [] ),
39
+ ];
40
+
41
+ return (
42
+ <SelectControl
43
+ label={ label }
44
+ value={ value }
45
+ options={ elements }
46
+ onChange={ onChangeControl }
47
+ __next40pxDefaultSize
48
+ __nextHasNoMarginBottom
49
+ hideLabelFromVision={ hideLabelFromVision }
50
+ />
51
+ );
52
+ }
@@ -0,0 +1,4 @@
1
+ .dataviews-controls__datetime {
2
+ border: none;
3
+ padding: 0;
4
+ }
@@ -0,0 +1,40 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { TextControl } from '@wordpress/components';
5
+ import { useCallback } from '@wordpress/element';
6
+
7
+ /**
8
+ * Internal dependencies
9
+ */
10
+ import type { DataFormControlProps } from '../types';
11
+
12
+ export default function Text< Item >( {
13
+ data,
14
+ field,
15
+ onChange,
16
+ hideLabelFromVision,
17
+ }: DataFormControlProps< Item > ) {
18
+ const { id, label, placeholder } = field;
19
+ const value = field.getValue( { item: data } );
20
+
21
+ const onChangeControl = useCallback(
22
+ ( newValue: string ) =>
23
+ onChange( {
24
+ [ id ]: newValue,
25
+ } ),
26
+ [ id, onChange ]
27
+ );
28
+
29
+ return (
30
+ <TextControl
31
+ label={ label }
32
+ placeholder={ placeholder }
33
+ value={ value ?? '' }
34
+ onChange={ onChangeControl }
35
+ __next40pxDefaultSize
36
+ __nextHasNoMarginBottom
37
+ hideLabelFromVision={ hideLabelFromVision }
38
+ />
39
+ );
40
+ }
@@ -17,7 +17,7 @@ import { closeSmall } from '@wordpress/icons';
17
17
  * Internal dependencies
18
18
  */
19
19
  import { normalizeFields } from '../../normalize-fields';
20
- import type { DataFormProps, NormalizedField } from '../../types';
20
+ import type { DataFormProps, NormalizedField, Field } from '../../types';
21
21
 
22
22
  interface FormFieldProps< Item > {
23
23
  data: Item;
@@ -142,7 +142,11 @@ export default function FormPanel< Item >( {
142
142
  const visibleFields = useMemo(
143
143
  () =>
144
144
  normalizeFields(
145
- fields.filter( ( { id } ) => !! form.fields?.includes( id ) )
145
+ ( form.fields ?? [] )
146
+ .map( ( fieldId ) =>
147
+ fields.find( ( { id } ) => id === fieldId )
148
+ )
149
+ .filter( ( field ): field is Field< Item > => !! field )
146
150
  ),
147
151
  [ fields, form.fields ]
148
152
  );
@@ -8,7 +8,7 @@ import { useMemo } from '@wordpress/element';
8
8
  * Internal dependencies
9
9
  */
10
10
  import { normalizeFields } from '../../normalize-fields';
11
- import type { DataFormProps } from '../../types';
11
+ import type { DataFormProps, Field } from '../../types';
12
12
 
13
13
  export default function FormRegular< Item >( {
14
14
  data,
@@ -19,7 +19,11 @@ export default function FormRegular< Item >( {
19
19
  const visibleFields = useMemo(
20
20
  () =>
21
21
  normalizeFields(
22
- fields.filter( ( { id } ) => !! form.fields?.includes( id ) )
22
+ ( form.fields ?? [] )
23
+ .map( ( fieldId ) =>
24
+ fields.find( ( { id } ) => id === fieldId )
25
+ )
26
+ .filter( ( field ): field is Field< Item > => !! field )
23
27
  ),
24
28
  [ fields, form.fields ]
25
29
  );
@@ -1,11 +1,10 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
- import { RangeControl, Button } from '@wordpress/components';
4
+ import { RangeControl } from '@wordpress/components';
5
5
  import { __ } from '@wordpress/i18n';
6
6
  import { useViewportMatch } from '@wordpress/compose';
7
- import { plus, reset } from '@wordpress/icons';
8
- import { useEffect } from '@wordpress/element';
7
+ import { useEffect, useMemo } from '@wordpress/element';
9
8
 
10
9
  const viewportBreaks = {
11
10
  xhuge: { min: 3, max: 6, default: 5 },
@@ -40,21 +39,6 @@ function useViewPortBreakpoint() {
40
39
  return null;
41
40
  }
42
41
 
43
- // Value is number from 0 to 100 representing how big an item is in the grid
44
- // 100 being the biggest and 0 being the smallest.
45
- // The size is relative to the viewport size, if one a given viewport the
46
- // number of allowed items in a grid is 3 to 6 a 0 ( the smallest ) will mean that the grid will
47
- // have 6 items in a row, a 100 ( the biggest ) will mean that the grid will have 3 items in a row.
48
- // A value of 75 will mean that the grid will have 4 items in a row.
49
- function getRangeValue(
50
- density: number,
51
- breakValues: { min: number; max: number; default: number }
52
- ) {
53
- const inverseDensity = breakValues.max - density;
54
- const max = breakValues.max - breakValues.min;
55
- return Math.round( ( inverseDensity * 100 ) / max );
56
- }
57
-
58
42
  export default function DensityPicker( {
59
43
  density,
60
44
  setDensity,
@@ -78,59 +62,41 @@ export default function DensityPicker( {
78
62
  return _density;
79
63
  } );
80
64
  }, [ setDensity, viewport ] );
65
+ const breakValues = viewportBreaks[ viewport || 'mobile' ];
66
+ const densityToUse = density || breakValues.default;
67
+
68
+ const marks = useMemo(
69
+ () =>
70
+ Array.from(
71
+ { length: breakValues.max - breakValues.min + 1 },
72
+ ( _, i ) => {
73
+ return {
74
+ value: breakValues.min + i,
75
+ };
76
+ }
77
+ ),
78
+ [ breakValues ]
79
+ );
80
+
81
81
  if ( ! viewport ) {
82
82
  return null;
83
83
  }
84
- const breakValues = viewportBreaks[ viewport ];
85
- const densityToUse = density || breakValues.default;
86
- const rangeValue = getRangeValue( densityToUse, breakValues );
87
84
 
88
- const step = 100 / ( breakValues.max - breakValues.min + 1 );
89
85
  return (
90
- <>
91
- <Button
92
- size="compact"
93
- icon={ reset }
94
- disabled={ rangeValue <= 0 }
95
- accessibleWhenDisabled
96
- label={ __( 'Decrease size' ) }
97
- onClick={ () => {
98
- setDensity( densityToUse + 1 );
99
- } }
100
- />
101
- <RangeControl
102
- __nextHasNoMarginBottom
103
- showTooltip={ false }
104
- className="dataviews-density-picker__range-control"
105
- label={ __( 'Item size' ) }
106
- hideLabelFromVision
107
- value={ rangeValue }
108
- min={ 0 }
109
- max={ 100 }
110
- withInputField={ false }
111
- onChange={ ( value = 0 ) => {
112
- const inverseValue = 100 - value;
113
- setDensity(
114
- Math.round(
115
- ( inverseValue *
116
- ( breakValues.max - breakValues.min ) ) /
117
- 100 +
118
- breakValues.min
119
- )
120
- );
121
- } }
122
- step={ step }
123
- />
124
- <Button
125
- size="compact"
126
- icon={ plus }
127
- disabled={ rangeValue >= 100 }
128
- accessibleWhenDisabled
129
- label={ __( 'Increase size' ) }
130
- onClick={ () => {
131
- setDensity( densityToUse - 1 );
132
- } }
133
- />
134
- </>
86
+ <RangeControl
87
+ __nextHasNoMarginBottom
88
+ __next40pxDefaultSize
89
+ showTooltip={ false }
90
+ label={ __( 'Preview size' ) }
91
+ value={ breakValues.max + breakValues.min - densityToUse }
92
+ marks={ marks }
93
+ min={ breakValues.min }
94
+ max={ breakValues.max }
95
+ withInputField={ false }
96
+ onChange={ ( value = 0 ) => {
97
+ setDensity( breakValues.max + breakValues.min - value );
98
+ } }
99
+ step={ 1 }
100
+ />
135
101
  );
136
102
  }
@@ -145,7 +145,7 @@ function GridItem< Item >( {
145
145
  >
146
146
  <>
147
147
  <FlexItem className="dataviews-view-grid__field-name">
148
- { field.label }
148
+ { field.header }
149
149
  </FlexItem>
150
150
  <FlexItem
151
151
  className="dataviews-view-grid__field-value"
@@ -146,10 +146,6 @@
146
146
  }
147
147
  }
148
148
 
149
- .dataviews-density-picker__range-control {
150
- width: 200px;
151
- }
152
-
153
149
  .dataviews-view-grid__field-value:empty,
154
150
  .dataviews-view-grid__field:empty {
155
151
  display: none;
@@ -2,6 +2,9 @@
2
2
  * External dependencies
3
3
  */
4
4
  import clsx from 'clsx';
5
+ // TODO: use the @wordpress/components one once public
6
+ // eslint-disable-next-line no-restricted-imports
7
+ import { useStoreState } from '@ariakit/react';
5
8
  // Import CompositeStore type, which is not exported from @wordpress/components.
6
9
  // eslint-disable-next-line no-restricted-imports
7
10
  import type { CompositeStore } from '@ariakit/react';
@@ -358,10 +361,11 @@ export default function ViewList< Item >( props: ViewListProps< Item > ) {
358
361
 
359
362
  const store = useCompositeStore( {
360
363
  defaultActiveId: getItemDomId( selectedItem ),
361
- } );
364
+ } ) as CompositeStore; // TODO, remove once composite APIs are public
362
365
 
363
366
  // Manage focused item, when the active one is removed from the list.
364
- const isActiveIdInList = store.useState(
367
+ const isActiveIdInList = useStoreState(
368
+ store,
365
369
  ( state: { items: any[]; activeId: any } ) =>
366
370
  state.items.some(
367
371
  ( item: { id: any } ) => item.id === state.activeId
@@ -72,7 +72,7 @@ const _HeaderMenu = forwardRef( function HeaderMenu< Item >(
72
72
  );
73
73
  const index = view.fields?.indexOf( fieldId ) as number;
74
74
  if ( !! combinedField ) {
75
- return combinedField.label;
75
+ return combinedField.header || combinedField.label;
76
76
  }
77
77
  const field = fields.find( ( f ) => f.id === fieldId );
78
78
  if ( ! field ) {
@@ -91,9 +91,7 @@ const _HeaderMenu = forwardRef( function HeaderMenu< Item >(
91
91
  !! field.elements?.length &&
92
92
  !! operators.length &&
93
93
  ! field.filterBy?.isPrimary;
94
- if ( ! isSortable && ! isHidable && ! canAddFilter ) {
95
- return field.label;
96
- }
94
+
97
95
  return (
98
96
  <DropdownMenu
99
97
  align="start"
@@ -104,7 +102,7 @@ const _HeaderMenu = forwardRef( function HeaderMenu< Item >(
104
102
  ref={ ref }
105
103
  variant="tertiary"
106
104
  >
107
- { field.label }
105
+ { field.header }
108
106
  { view.sort && isSorted && (
109
107
  <span aria-hidden="true">
110
108
  { sortArrows[ view.sort.direction ] }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Internal dependencies
3
+ */
4
+ import type { SortDirection, ValidationContext } from '../types';
5
+
6
+ function sort( a: any, b: any, direction: SortDirection ) {
7
+ const timeA = new Date( a ).getTime();
8
+ const timeB = new Date( b ).getTime();
9
+
10
+ return direction === 'asc' ? timeA - timeB : timeB - timeA;
11
+ }
12
+
13
+ function isValid( value: any, context?: ValidationContext ) {
14
+ if ( context?.elements ) {
15
+ const validValues = context?.elements.map( ( f ) => f.value );
16
+ if ( ! validValues.includes( value ) ) {
17
+ return false;
18
+ }
19
+ }
20
+
21
+ return true;
22
+ }
23
+
24
+ export default {
25
+ sort,
26
+ isValid,
27
+ Edit: 'datetime',
28
+ };
@@ -4,6 +4,7 @@
4
4
  import type { FieldType, SortDirection, ValidationContext } from '../types';
5
5
  import { default as integer } from './integer';
6
6
  import { default as text } from './text';
7
+ import { default as datetime } from './datetime';
7
8
 
8
9
  /**
9
10
  *
@@ -20,6 +21,10 @@ export default function getFieldTypeDefinition( type?: FieldType ) {
20
21
  return text;
21
22
  }
22
23
 
24
+ if ( 'datetime' === type ) {
25
+ return datetime;
26
+ }
27
+
23
28
  return {
24
29
  sort: ( a: any, b: any, direction: SortDirection ) => {
25
30
  if ( typeof a === 'number' && typeof b === 'number' ) {
@@ -1,21 +1,7 @@
1
- /**
2
- * WordPress dependencies
3
- */
4
- import {
5
- __experimentalNumberControl as NumberControl,
6
- SelectControl,
7
- } from '@wordpress/components';
8
- import { useCallback } from '@wordpress/element';
9
- import { __ } from '@wordpress/i18n';
10
-
11
1
  /**
12
2
  * Internal dependencies
13
3
  */
14
- import type {
15
- SortDirection,
16
- ValidationContext,
17
- DataFormControlProps,
18
- } from '../types';
4
+ import type { SortDirection, ValidationContext } from '../types';
19
5
 
20
6
  function sort( a: any, b: any, direction: SortDirection ) {
21
7
  return direction === 'asc' ? a - b : b - a;
@@ -41,63 +27,8 @@ function isValid( value: any, context?: ValidationContext ) {
41
27
  return true;
42
28
  }
43
29
 
44
- function Edit< Item >( {
45
- data,
46
- field,
47
- onChange,
48
- hideLabelFromVision,
49
- }: DataFormControlProps< Item > ) {
50
- const { id, label, description } = field;
51
- const value = field.getValue( { item: data } ) ?? '';
52
- const onChangeControl = useCallback(
53
- ( newValue: string | undefined ) =>
54
- onChange( ( prevItem: Item ) => ( {
55
- ...prevItem,
56
- [ id ]: newValue,
57
- } ) ),
58
- [ id, onChange ]
59
- );
60
-
61
- if ( field.elements ) {
62
- const elements = [
63
- /*
64
- * Value can be undefined when:
65
- *
66
- * - the field is not required
67
- * - in bulk editing
68
- *
69
- */
70
- { label: __( 'Select item' ), value: '' },
71
- ...field.elements,
72
- ];
73
-
74
- return (
75
- <SelectControl
76
- label={ label }
77
- value={ value }
78
- options={ elements }
79
- onChange={ onChangeControl }
80
- __next40pxDefaultSize
81
- __nextHasNoMarginBottom
82
- hideLabelFromVision={ hideLabelFromVision }
83
- />
84
- );
85
- }
86
-
87
- return (
88
- <NumberControl
89
- label={ label }
90
- help={ description }
91
- value={ value }
92
- onChange={ onChangeControl }
93
- __next40pxDefaultSize
94
- hideLabelFromVision={ hideLabelFromVision }
95
- />
96
- );
97
- }
98
-
99
30
  export default {
100
31
  sort,
101
32
  isValid,
102
- Edit,
33
+ Edit: 'integer',
103
34
  };
@@ -1,18 +1,7 @@
1
- /**
2
- * WordPress dependencies
3
- */
4
- import { SelectControl, TextControl } from '@wordpress/components';
5
- import { useCallback } from '@wordpress/element';
6
- import { __ } from '@wordpress/i18n';
7
-
8
1
  /**
9
2
  * Internal dependencies
10
3
  */
11
- import type {
12
- SortDirection,
13
- ValidationContext,
14
- DataFormControlProps,
15
- } from '../types';
4
+ import type { SortDirection, ValidationContext } from '../types';
16
5
 
17
6
  function sort( valueA: any, valueB: any, direction: SortDirection ) {
18
7
  return direction === 'asc'
@@ -31,65 +20,8 @@ function isValid( value: any, context?: ValidationContext ) {
31
20
  return true;
32
21
  }
33
22
 
34
- function Edit< Item >( {
35
- data,
36
- field,
37
- onChange,
38
- hideLabelFromVision,
39
- }: DataFormControlProps< Item > ) {
40
- const { id, label, placeholder } = field;
41
- const value = field.getValue( { item: data } );
42
-
43
- const onChangeControl = useCallback(
44
- ( newValue: string ) =>
45
- onChange( ( prevItem: Item ) => ( {
46
- ...prevItem,
47
- [ id ]: newValue,
48
- } ) ),
49
- [ id, onChange ]
50
- );
51
-
52
- if ( field.elements ) {
53
- const elements = [
54
- /*
55
- * Value can be undefined when:
56
- *
57
- * - the field is not required
58
- * - in bulk editing
59
- *
60
- */
61
- { label: __( 'Select item' ), value: '' },
62
- ...field.elements,
63
- ];
64
-
65
- return (
66
- <SelectControl
67
- label={ label }
68
- value={ value }
69
- options={ elements }
70
- onChange={ onChangeControl }
71
- __next40pxDefaultSize
72
- __nextHasNoMarginBottom
73
- hideLabelFromVision={ hideLabelFromVision }
74
- />
75
- );
76
- }
77
-
78
- return (
79
- <TextControl
80
- label={ label }
81
- placeholder={ placeholder }
82
- value={ value ?? '' }
83
- onChange={ onChangeControl }
84
- __next40pxDefaultSize
85
- __nextHasNoMarginBottom
86
- hideLabelFromVision={ hideLabelFromVision }
87
- />
88
- );
89
- }
90
-
91
23
  export default {
92
24
  sort,
93
25
  isValid,
94
- Edit,
26
+ Edit: 'text',
95
27
  };
@@ -3,6 +3,7 @@
3
3
  */
4
4
  import getFieldTypeDefinition from './field-types';
5
5
  import type { Field, NormalizedField } from './types';
6
+ import { getControl } from './dataform-controls';
6
7
 
7
8
  /**
8
9
  * Apply default values and normalize the fields config.
@@ -17,8 +18,7 @@ export function normalizeFields< Item >(
17
18
  const fieldTypeDefinition = getFieldTypeDefinition( field.type );
18
19
 
19
20
  const getValue =
20
- field.getValue ||
21
- ( ( { item }: { item: Item } ) => item[ field.id as keyof Item ] );
21
+ field.getValue || ( ( { item } ) => ( item as any )[ field.id ] );
22
22
 
23
23
  const sort =
24
24
  field.sort ??
@@ -39,17 +39,14 @@ export function normalizeFields< Item >(
39
39
  );
40
40
  };
41
41
 
42
- const Edit = field.Edit || fieldTypeDefinition.Edit;
42
+ const Edit = getControl( field, fieldTypeDefinition );
43
43
 
44
44
  const renderFromElements = ( { item }: { item: Item } ) => {
45
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;
46
+ return (
47
+ field?.elements?.find( ( element ) => element.value === value )
48
+ ?.label || getValue( { item } )
49
+ );
53
50
  };
54
51
 
55
52
  const render =
@@ -58,6 +55,7 @@ export function normalizeFields< Item >(
58
55
  return {
59
56
  ...field,
60
57
  label: field.label || field.id,
58
+ header: field.header || field.label || field.id,
61
59
  getValue,
62
60
  render,
63
61
  sort,
package/src/style.scss CHANGED
@@ -11,4 +11,5 @@
11
11
  @import "./dataviews-layouts/list/style.scss";
12
12
  @import "./dataviews-layouts/table/style.scss";
13
13
 
14
+ @import "./dataform-controls/style.scss";
14
15
  @import "./dataforms-layouts/panel/style.scss";
@@ -268,6 +268,34 @@ describe( 'sorting', () => {
268
268
  expect( result[ 1 ].title ).toBe( 'Neptune' );
269
269
  } );
270
270
 
271
+ it( 'should sort datetime field types', () => {
272
+ const { data: resultDesc } = filterSortAndPaginate(
273
+ data,
274
+ {
275
+ sort: { field: 'date', direction: 'desc' },
276
+ },
277
+ fields
278
+ );
279
+ expect( resultDesc ).toHaveLength( 11 );
280
+ expect( resultDesc[ 0 ].title ).toBe( 'NASA' );
281
+ expect( resultDesc[ 1 ].title ).toBe( 'Earth' );
282
+ expect( resultDesc[ 9 ].title ).toBe( 'Space' );
283
+ expect( resultDesc[ 10 ].title ).toBe( 'Jupiter' );
284
+
285
+ const { data: resultAsc } = filterSortAndPaginate(
286
+ data,
287
+ {
288
+ sort: { field: 'date', direction: 'asc' },
289
+ },
290
+ fields
291
+ );
292
+ expect( resultAsc ).toHaveLength( 11 );
293
+ expect( resultAsc[ 0 ].title ).toBe( 'Jupiter' );
294
+ expect( resultAsc[ 1 ].title ).toBe( 'Space' );
295
+ expect( resultAsc[ 9 ].title ).toBe( 'Earth' );
296
+ expect( resultAsc[ 10 ].title ).toBe( 'NASA' );
297
+ } );
298
+
271
299
  it( 'should sort untyped fields if the value is a number', () => {
272
300
  const { data: result } = filterSortAndPaginate(
273
301
  data,