@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
@@ -0,0 +1,164 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import {
5
+ __experimentalVStack as VStack,
6
+ __experimentalHStack as HStack,
7
+ __experimentalHeading as Heading,
8
+ __experimentalSpacer as Spacer,
9
+ Dropdown,
10
+ Button,
11
+ } from '@wordpress/components';
12
+ import { useState, useMemo } from '@wordpress/element';
13
+ import { sprintf, __ } from '@wordpress/i18n';
14
+ import { closeSmall } from '@wordpress/icons';
15
+
16
+ /**
17
+ * Internal dependencies
18
+ */
19
+ import { normalizeFields } from '../../normalize-fields';
20
+ import type { DataFormProps, NormalizedField } from '../../types';
21
+
22
+ interface FormFieldProps< Item > {
23
+ data: Item;
24
+ field: NormalizedField< Item >;
25
+ onChange: ( value: any ) => void;
26
+ }
27
+
28
+ function DropdownHeader( {
29
+ title,
30
+ onClose,
31
+ }: {
32
+ title: string;
33
+ onClose: () => void;
34
+ } ) {
35
+ return (
36
+ <VStack
37
+ className="dataforms-layouts-panel__dropdown-header"
38
+ spacing={ 4 }
39
+ >
40
+ <HStack alignment="center">
41
+ <Heading level={ 2 } size={ 13 }>
42
+ { title }
43
+ </Heading>
44
+ <Spacer />
45
+ { onClose && (
46
+ <Button
47
+ className="dataforms-layouts-panel__dropdown-header-action"
48
+ label={ __( 'Close' ) }
49
+ icon={ closeSmall }
50
+ onClick={ onClose }
51
+ />
52
+ ) }
53
+ </HStack>
54
+ </VStack>
55
+ );
56
+ }
57
+
58
+ function FormField< Item >( {
59
+ data,
60
+ field,
61
+ onChange,
62
+ }: FormFieldProps< Item > ) {
63
+ // Use internal state instead of a ref to make sure that the component
64
+ // re-renders when the popover's anchor updates.
65
+ const [ popoverAnchor, setPopoverAnchor ] = useState< HTMLElement | null >(
66
+ null
67
+ );
68
+ // Memoize popoverProps to avoid returning a new object every time.
69
+ const popoverProps = useMemo(
70
+ () => ( {
71
+ // Anchor the popover to the middle of the entire row so that it doesn't
72
+ // move around when the label changes.
73
+ anchor: popoverAnchor,
74
+ placement: 'left-start',
75
+ offset: 36,
76
+ shift: true,
77
+ } ),
78
+ [ popoverAnchor ]
79
+ );
80
+
81
+ return (
82
+ <HStack
83
+ ref={ setPopoverAnchor }
84
+ className="dataforms-layouts-panel__field"
85
+ >
86
+ <div className="dataforms-layouts-panel__field-label">
87
+ { field.label }
88
+ </div>
89
+ <div>
90
+ <Dropdown
91
+ contentClassName="dataforms-layouts-panel__field-dropdown"
92
+ popoverProps={ popoverProps }
93
+ focusOnMount
94
+ toggleProps={ {
95
+ size: 'compact',
96
+ variant: 'tertiary',
97
+ tooltipPosition: 'middle left',
98
+ } }
99
+ renderToggle={ ( { isOpen, onToggle } ) => (
100
+ <Button
101
+ className="dataforms-layouts-panel__field-control"
102
+ size="compact"
103
+ variant="tertiary"
104
+ aria-expanded={ isOpen }
105
+ aria-label={ sprintf(
106
+ // translators: %s: Field name.
107
+ __( 'Edit %s' ),
108
+ field.label
109
+ ) }
110
+ onClick={ onToggle }
111
+ >
112
+ <field.render item={ data } />
113
+ </Button>
114
+ ) }
115
+ renderContent={ ( { onClose } ) => (
116
+ <>
117
+ <DropdownHeader
118
+ title={ field.label }
119
+ onClose={ onClose }
120
+ />
121
+ <field.Edit
122
+ key={ field.id }
123
+ data={ data }
124
+ field={ field }
125
+ onChange={ onChange }
126
+ hideLabelFromVision
127
+ />
128
+ </>
129
+ ) }
130
+ />
131
+ </div>
132
+ </HStack>
133
+ );
134
+ }
135
+
136
+ export default function FormPanel< Item >( {
137
+ data,
138
+ fields,
139
+ form,
140
+ onChange,
141
+ }: DataFormProps< Item > ) {
142
+ const visibleFields = useMemo(
143
+ () =>
144
+ normalizeFields(
145
+ fields.filter( ( { id } ) => !! form.fields?.includes( id ) )
146
+ ),
147
+ [ fields, form.fields ]
148
+ );
149
+
150
+ return (
151
+ <VStack spacing={ 2 }>
152
+ { visibleFields.map( ( field ) => {
153
+ return (
154
+ <FormField
155
+ key={ field.id }
156
+ data={ data }
157
+ field={ field }
158
+ onChange={ onChange }
159
+ />
160
+ );
161
+ } ) }
162
+ </VStack>
163
+ );
164
+ }
@@ -0,0 +1,59 @@
1
+ .dataforms-layouts-panel__field {
2
+ width: 100%;
3
+ min-height: $grid-unit-40;
4
+ justify-content: flex-start !important;
5
+ align-items: flex-start !important;
6
+ }
7
+
8
+ .dataforms-layouts-panel__field-label {
9
+ width: 38%;
10
+ flex-shrink: 0;
11
+ min-height: $grid-unit-40;
12
+ display: flex;
13
+ align-items: center;
14
+ padding: 6px 0; // Matches button to ensure alignment
15
+ line-height: $grid-unit-05 * 5;
16
+ hyphens: auto;
17
+ }
18
+
19
+ .dataforms-layouts-panel__field-control {
20
+ flex-grow: 1;
21
+ min-height: $grid-unit-40;
22
+ display: flex;
23
+ align-items: center;
24
+
25
+ .components-button {
26
+ max-width: 100%;
27
+ text-align: left;
28
+ white-space: normal;
29
+ text-wrap: balance; // Fallback for Safari.
30
+ text-wrap: pretty;
31
+ min-height: $button-size-compact;
32
+ }
33
+
34
+ .components-dropdown {
35
+ max-width: 100%;
36
+ }
37
+ }
38
+
39
+ .dataforms-layouts-panel__field-dropdown .components-popover__content {
40
+ min-width: 320px;
41
+ padding: $grid-unit-20;
42
+ }
43
+
44
+ .dataforms-layouts-panel__dropdown-header {
45
+ margin-bottom: $grid-unit-20;
46
+ }
47
+
48
+ [class].dataforms-layouts-panel__dropdown-header-action {
49
+ height: $icon-size;
50
+
51
+ &.has-icon {
52
+ min-width: $icon-size;
53
+ padding: 0;
54
+ }
55
+
56
+ &:not(.has-icon) {
57
+ text-decoration: underline;
58
+ }
59
+ }
@@ -0,0 +1,41 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { __experimentalVStack as VStack } from '@wordpress/components';
5
+ import { useMemo } from '@wordpress/element';
6
+
7
+ /**
8
+ * Internal dependencies
9
+ */
10
+ import { normalizeFields } from '../../normalize-fields';
11
+ import type { DataFormProps } from '../../types';
12
+
13
+ export default function FormRegular< Item >( {
14
+ data,
15
+ fields,
16
+ form,
17
+ onChange,
18
+ }: DataFormProps< Item > ) {
19
+ const visibleFields = useMemo(
20
+ () =>
21
+ normalizeFields(
22
+ fields.filter( ( { id } ) => !! form.fields?.includes( id ) )
23
+ ),
24
+ [ fields, form.fields ]
25
+ );
26
+
27
+ return (
28
+ <VStack spacing={ 4 }>
29
+ { visibleFields.map( ( field ) => {
30
+ return (
31
+ <field.Edit
32
+ key={ field.id }
33
+ data={ data }
34
+ field={ field }
35
+ onChange={ onChange }
36
+ />
37
+ );
38
+ } ) }
39
+ </VStack>
40
+ );
41
+ }
@@ -4,7 +4,7 @@
4
4
  import { RangeControl, Button } from '@wordpress/components';
5
5
  import { __ } from '@wordpress/i18n';
6
6
  import { useViewportMatch } from '@wordpress/compose';
7
- import { plus, lineSolid } from '@wordpress/icons';
7
+ import { plus, reset } from '@wordpress/icons';
8
8
  import { useEffect } from '@wordpress/element';
9
9
 
10
10
  const viewportBreaks = {
@@ -90,7 +90,7 @@ export default function DensityPicker( {
90
90
  <>
91
91
  <Button
92
92
  size="compact"
93
- icon={ lineSolid }
93
+ icon={ reset }
94
94
  disabled={ rangeValue <= 0 }
95
95
  accessibleWhenDisabled
96
96
  label={ __( 'Decrease size' ) }
@@ -84,18 +84,18 @@ function GridItem< Item >( {
84
84
  <div className="dataviews-view-grid__media">
85
85
  { renderedMediaField }
86
86
  </div>
87
+ <SingleSelectionCheckbox
88
+ item={ item }
89
+ selection={ selection }
90
+ onChangeSelection={ onChangeSelection }
91
+ getItemId={ getItemId }
92
+ primaryField={ primaryField }
93
+ disabled={ ! hasBulkAction }
94
+ />
87
95
  <HStack
88
96
  justify="space-between"
89
97
  className="dataviews-view-grid__title-actions"
90
98
  >
91
- <SingleSelectionCheckbox
92
- item={ item }
93
- selection={ selection }
94
- onChangeSelection={ onChangeSelection }
95
- getItemId={ getItemId }
96
- primaryField={ primaryField }
97
- disabled={ ! hasBulkAction }
98
- />
99
99
  <HStack className="dataviews-view-grid__primary-field">
100
100
  { renderedPrimaryField }
101
101
  </HStack>
@@ -9,6 +9,7 @@
9
9
  .dataviews-view-grid__card {
10
10
  height: 100%;
11
11
  justify-content: flex-start;
12
+ position: relative;
12
13
 
13
14
  .dataviews-view-grid__title-actions {
14
15
  padding: $grid-unit-10 0 $grid-unit-05;
@@ -22,6 +23,11 @@
22
23
  .dataviews-view-grid__fields .dataviews-view-grid__field .dataviews-view-grid__field-value {
23
24
  color: $gray-900;
24
25
  }
26
+
27
+ .dataviews-view-grid__media::after {
28
+ background-color: rgba(var(--wp-admin-theme-color--rgb), 0.08);
29
+ box-shadow: inset 0 0 0 $border-width var(--wp-admin-theme-color);
30
+ }
25
31
  }
26
32
  }
27
33
 
@@ -61,10 +67,20 @@
61
67
  padding: 0 0 $grid-unit-15;
62
68
  }
63
69
 
70
+ .dataviews-view-grid__field-value:not(:empty) {
71
+ min-height: $grid-unit-30;
72
+ line-height: $grid-unit-05 * 5;
73
+ padding-top: math.div($grid-unit-05, 2);
74
+ }
75
+
64
76
  .dataviews-view-grid__field {
65
77
  align-items: flex-start;
66
78
  min-height: $grid-unit-30;
67
79
 
80
+ &:not(:has(.dataviews-view-grid__field-value:not(:empty))) {
81
+ display: none;
82
+ }
83
+
68
84
  &:not(.is-column) {
69
85
  align-items: center;
70
86
 
@@ -138,3 +154,16 @@
138
154
  .dataviews-view-grid__field:empty {
139
155
  display: none;
140
156
  }
157
+
158
+ .dataviews-view-grid__card .dataviews-selection-checkbox {
159
+ position: absolute;
160
+ top: -9999em;
161
+ left: $grid-unit-10;
162
+ z-index: z-index(".dataviews-view-grid__card .dataviews-selection-checkbox");
163
+ }
164
+
165
+ .dataviews-view-grid__card:hover .dataviews-selection-checkbox,
166
+ .dataviews-view-grid__card:focus-within .dataviews-selection-checkbox,
167
+ .dataviews-view-grid__card.is-selected .dataviews-selection-checkbox {
168
+ top: $grid-unit-10;
169
+ }
@@ -179,7 +179,10 @@
179
179
  }
180
180
 
181
181
  .dataviews-view-list__field-value {
182
- line-height: $grid-unit-05 * 6;
182
+ min-height: $grid-unit-30;
183
+ line-height: $grid-unit-05 * 5;
184
+ display: flex;
185
+ align-items: center;
183
186
  }
184
187
  }
185
188
 
@@ -249,7 +249,7 @@ const _HeaderMenu = forwardRef( function HeaderMenu< Item >(
249
249
  } }
250
250
  >
251
251
  <DropdownMenuItemLabel>
252
- { __( 'Hide' ) }
252
+ { __( 'Hide column' ) }
253
253
  </DropdownMenuItemLabel>
254
254
  </DropdownMenuItem>
255
255
  ) }
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Internal dependencies
3
+ */
4
+ import type { FieldType, SortDirection, ValidationContext } from '../types';
5
+ import { default as integer } from './integer';
6
+ import { default as text } from './text';
7
+
8
+ /**
9
+ *
10
+ * @param {FieldType} type The field type definition to get.
11
+ *
12
+ * @return A field type definition.
13
+ */
14
+ export default function getFieldTypeDefinition( type?: FieldType ) {
15
+ if ( 'integer' === type ) {
16
+ return integer;
17
+ }
18
+
19
+ if ( 'text' === type ) {
20
+ return text;
21
+ }
22
+
23
+ return {
24
+ sort: ( a: any, b: any, direction: SortDirection ) => {
25
+ if ( typeof a === 'number' && typeof b === 'number' ) {
26
+ return direction === 'asc' ? a - b : b - a;
27
+ }
28
+
29
+ return direction === 'asc'
30
+ ? a.localeCompare( b )
31
+ : b.localeCompare( a );
32
+ },
33
+ isValid: ( value: any, context?: ValidationContext ) => {
34
+ if ( context?.elements ) {
35
+ const validValues = context?.elements?.map( ( f ) => f.value );
36
+ if ( ! validValues.includes( value ) ) {
37
+ return false;
38
+ }
39
+ }
40
+
41
+ return true;
42
+ },
43
+ Edit: () => null,
44
+ };
45
+ }
@@ -0,0 +1,103 @@
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
+ /**
12
+ * Internal dependencies
13
+ */
14
+ import type {
15
+ SortDirection,
16
+ ValidationContext,
17
+ DataFormControlProps,
18
+ } from '../types';
19
+
20
+ function sort( a: any, b: any, direction: SortDirection ) {
21
+ return direction === 'asc' ? a - b : b - a;
22
+ }
23
+
24
+ function isValid( value: any, context?: ValidationContext ) {
25
+ // TODO: this implicitely means the value is required.
26
+ if ( value === '' ) {
27
+ return false;
28
+ }
29
+
30
+ if ( ! Number.isInteger( Number( value ) ) ) {
31
+ return false;
32
+ }
33
+
34
+ if ( context?.elements ) {
35
+ const validValues = context?.elements.map( ( f ) => f.value );
36
+ if ( ! validValues.includes( Number( value ) ) ) {
37
+ return false;
38
+ }
39
+ }
40
+
41
+ return true;
42
+ }
43
+
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
+ export default {
100
+ sort,
101
+ isValid,
102
+ Edit,
103
+ };
@@ -0,0 +1,95 @@
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
+ /**
9
+ * Internal dependencies
10
+ */
11
+ import type {
12
+ SortDirection,
13
+ ValidationContext,
14
+ DataFormControlProps,
15
+ } from '../types';
16
+
17
+ function sort( valueA: any, valueB: any, direction: SortDirection ) {
18
+ return direction === 'asc'
19
+ ? valueA.localeCompare( valueB )
20
+ : valueB.localeCompare( valueA );
21
+ }
22
+
23
+ function isValid( value: any, context?: ValidationContext ) {
24
+ if ( context?.elements ) {
25
+ const validValues = context?.elements?.map( ( f ) => f.value );
26
+ if ( ! validValues.includes( value ) ) {
27
+ return false;
28
+ }
29
+ }
30
+
31
+ return true;
32
+ }
33
+
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
+ export default {
92
+ sort,
93
+ isValid,
94
+ Edit,
95
+ };
@@ -140,21 +140,7 @@ export function filterSortAndPaginate< Item >(
140
140
  } );
141
141
  if ( fieldToSort ) {
142
142
  filteredData.sort( ( a, b ) => {
143
- const valueA = fieldToSort.getValue( { item: a } ) ?? '';
144
- const valueB = fieldToSort.getValue( { item: b } ) ?? '';
145
-
146
- if (
147
- typeof valueA === 'number' &&
148
- typeof valueB === 'number'
149
- ) {
150
- return view.sort?.direction === 'asc'
151
- ? valueA - valueB
152
- : valueB - valueA;
153
- }
154
-
155
- return view.sort?.direction === 'asc'
156
- ? valueA.localeCompare( valueB )
157
- : valueB.localeCompare( valueA );
143
+ return fieldToSort.sort( a, b, view.sort?.direction ?? 'desc' );
158
144
  } );
159
145
  }
160
146
  }
package/src/index.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export { default as DataViews } from './components/dataviews';
2
2
  export { default as DataForm } from './components/dataform';
3
- export { VIEW_LAYOUTS } from './layouts';
3
+ export { VIEW_LAYOUTS } from './dataviews-layouts';
4
4
  export { filterSortAndPaginate } from './filter-and-sort-data-view';
5
5
  export type * from './types';
6
+ export { isItemValid } from './validation';