@wordpress/dataviews 4.0.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 (285) hide show
  1. package/CHANGELOG.md +33 -5
  2. package/README.md +31 -23
  3. package/build/components/dataform/index.js +10 -61
  4. package/build/components/dataform/index.js.map +1 -1
  5. package/build/components/dataviews/index.js +23 -14
  6. package/build/components/dataviews/index.js.map +1 -1
  7. package/build/components/dataviews-bulk-actions/index.js +3 -0
  8. package/build/components/dataviews-bulk-actions/index.js.map +1 -1
  9. package/build/components/dataviews-filters/add-filter.js +34 -17
  10. package/build/components/dataviews-filters/add-filter.js.map +1 -1
  11. package/build/components/dataviews-filters/index.js +109 -43
  12. package/build/components/dataviews-filters/index.js.map +1 -1
  13. package/build/components/dataviews-filters/search-widget.js +2 -5
  14. package/build/components/dataviews-filters/search-widget.js.map +1 -1
  15. package/build/components/dataviews-layout/index.js +2 -2
  16. package/build/components/dataviews-layout/index.js.map +1 -1
  17. package/build/components/dataviews-pagination/index.js +23 -15
  18. package/build/components/dataviews-pagination/index.js.map +1 -1
  19. package/build/components/dataviews-search/index.js +8 -5
  20. package/build/components/dataviews-search/index.js.map +1 -1
  21. package/build/components/dataviews-view-config/index.js +240 -188
  22. package/build/components/dataviews-view-config/index.js.map +1 -1
  23. package/build/constants.js +6 -1
  24. package/build/constants.js.map +1 -1
  25. package/build/dataform-controls/datetime.js +49 -0
  26. package/build/dataform-controls/datetime.js.map +1 -0
  27. package/build/dataform-controls/index.js +50 -0
  28. package/build/dataform-controls/index.js.map +1 -0
  29. package/build/dataform-controls/integer.js +45 -0
  30. package/build/dataform-controls/integer.js.map +1 -0
  31. package/build/dataform-controls/radio.js +45 -0
  32. package/build/dataform-controls/radio.js.map +1 -0
  33. package/build/dataform-controls/select.js +58 -0
  34. package/build/dataform-controls/select.js.map +1 -0
  35. package/build/dataform-controls/text.js +45 -0
  36. package/build/dataform-controls/text.js.map +1 -0
  37. package/build/dataforms-layouts/index.js +24 -0
  38. package/build/dataforms-layouts/index.js.map +1 -0
  39. package/build/dataforms-layouts/panel/index.js +132 -0
  40. package/build/dataforms-layouts/panel/index.js.map +1 -0
  41. package/build/dataforms-layouts/regular/index.js +42 -0
  42. package/build/dataforms-layouts/regular/index.js.map +1 -0
  43. package/build/dataviews-layouts/grid/density-picker.js +114 -0
  44. package/build/dataviews-layouts/grid/density-picker.js.map +1 -0
  45. package/build/{layouts → dataviews-layouts}/grid/index.js +9 -9
  46. package/build/dataviews-layouts/grid/index.js.map +1 -0
  47. package/build/dataviews-layouts/index.js.map +1 -0
  48. package/build/{layouts → dataviews-layouts}/list/index.js +6 -2
  49. package/build/dataviews-layouts/list/index.js.map +1 -0
  50. package/build/{layouts → dataviews-layouts}/table/column-header-menu.js +3 -6
  51. package/build/dataviews-layouts/table/column-header-menu.js.map +1 -0
  52. package/build/dataviews-layouts/table/index.js.map +1 -0
  53. package/build/field-types/datetime.js +30 -0
  54. package/build/field-types/datetime.js.map +1 -0
  55. package/build/field-types/index.js +50 -0
  56. package/build/field-types/index.js.map +1 -0
  57. package/build/field-types/integer.js +35 -0
  58. package/build/field-types/integer.js.map +1 -0
  59. package/build/field-types/text.js +28 -0
  60. package/build/field-types/text.js.map +1 -0
  61. package/build/filter-and-sort-data-view.js +2 -11
  62. package/build/filter-and-sort-data-view.js.map +1 -1
  63. package/build/index.js +9 -2
  64. package/build/index.js.map +1 -1
  65. package/build/normalize-fields.js +34 -1
  66. package/build/normalize-fields.js.map +1 -1
  67. package/build/types.js.map +1 -1
  68. package/build/validation.js +22 -0
  69. package/build/validation.js.map +1 -0
  70. package/build-module/components/dataform/index.js +10 -61
  71. package/build-module/components/dataform/index.js.map +1 -1
  72. package/build-module/components/dataviews/index.js +21 -14
  73. package/build-module/components/dataviews/index.js.map +1 -1
  74. package/build-module/components/dataviews-bulk-actions/index.js +3 -0
  75. package/build-module/components/dataviews-bulk-actions/index.js.map +1 -1
  76. package/build-module/components/dataviews-filters/add-filter.js +33 -17
  77. package/build-module/components/dataviews-filters/add-filter.js.map +1 -1
  78. package/build-module/components/dataviews-filters/index.js +108 -45
  79. package/build-module/components/dataviews-filters/index.js.map +1 -1
  80. package/build-module/components/dataviews-filters/search-widget.js +2 -5
  81. package/build-module/components/dataviews-filters/search-widget.js.map +1 -1
  82. package/build-module/components/dataviews-layout/index.js +1 -1
  83. package/build-module/components/dataviews-layout/index.js.map +1 -1
  84. package/build-module/components/dataviews-pagination/index.js +23 -15
  85. package/build-module/components/dataviews-pagination/index.js.map +1 -1
  86. package/build-module/components/dataviews-search/index.js +8 -5
  87. package/build-module/components/dataviews-search/index.js.map +1 -1
  88. package/build-module/components/dataviews-view-config/index.js +243 -191
  89. package/build-module/components/dataviews-view-config/index.js.map +1 -1
  90. package/build-module/constants.js +5 -0
  91. package/build-module/constants.js.map +1 -1
  92. package/build-module/dataform-controls/datetime.js +43 -0
  93. package/build-module/dataform-controls/datetime.js.map +1 -0
  94. package/build-module/dataform-controls/index.js +42 -0
  95. package/build-module/dataform-controls/index.js.map +1 -0
  96. package/build-module/dataform-controls/integer.js +38 -0
  97. package/build-module/dataform-controls/integer.js.map +1 -0
  98. package/build-module/dataform-controls/radio.js +38 -0
  99. package/build-module/dataform-controls/radio.js.map +1 -0
  100. package/build-module/dataform-controls/select.js +51 -0
  101. package/build-module/dataform-controls/select.js.map +1 -0
  102. package/build-module/dataform-controls/text.js +38 -0
  103. package/build-module/dataform-controls/text.js.map +1 -0
  104. package/build-module/dataforms-layouts/index.js +16 -0
  105. package/build-module/dataforms-layouts/index.js.map +1 -0
  106. package/build-module/dataforms-layouts/panel/index.js +127 -0
  107. package/build-module/dataforms-layouts/panel/index.js.map +1 -0
  108. package/build-module/dataforms-layouts/regular/index.js +35 -0
  109. package/build-module/dataforms-layouts/regular/index.js.map +1 -0
  110. package/build-module/dataviews-layouts/grid/density-picker.js +107 -0
  111. package/build-module/dataviews-layouts/grid/density-picker.js.map +1 -0
  112. package/build-module/{layouts → dataviews-layouts}/grid/index.js +9 -9
  113. package/build-module/dataviews-layouts/grid/index.js.map +1 -0
  114. package/build-module/dataviews-layouts/index.js.map +1 -0
  115. package/build-module/{layouts → dataviews-layouts}/list/index.js +5 -2
  116. package/build-module/dataviews-layouts/list/index.js.map +1 -0
  117. package/build-module/{layouts → dataviews-layouts}/table/column-header-menu.js +3 -6
  118. package/build-module/dataviews-layouts/table/column-header-menu.js.map +1 -0
  119. package/build-module/dataviews-layouts/table/index.js.map +1 -0
  120. package/build-module/field-types/datetime.js +24 -0
  121. package/build-module/field-types/datetime.js.map +1 -0
  122. package/build-module/field-types/index.js +44 -0
  123. package/build-module/field-types/index.js.map +1 -0
  124. package/build-module/field-types/integer.js +29 -0
  125. package/build-module/field-types/integer.js.map +1 -0
  126. package/build-module/field-types/text.js +22 -0
  127. package/build-module/field-types/text.js.map +1 -0
  128. package/build-module/filter-and-sort-data-view.js +2 -11
  129. package/build-module/filter-and-sort-data-view.js.map +1 -1
  130. package/build-module/index.js +2 -1
  131. package/build-module/index.js.map +1 -1
  132. package/build-module/normalize-fields.js +33 -1
  133. package/build-module/normalize-fields.js.map +1 -1
  134. package/build-module/types.js.map +1 -1
  135. package/build-module/validation.js +15 -0
  136. package/build-module/validation.js.map +1 -0
  137. package/build-style/style-rtl.css +186 -20
  138. package/build-style/style.css +186 -20
  139. package/build-types/components/dataform/index.d.ts +2 -13
  140. package/build-types/components/dataform/index.d.ts.map +1 -1
  141. package/build-types/components/dataform/stories/index.story.d.ts +12 -1
  142. package/build-types/components/dataform/stories/index.story.d.ts.map +1 -1
  143. package/build-types/components/dataviews/index.d.ts.map +1 -1
  144. package/build-types/components/dataviews/stories/fixtures.d.ts +25 -0
  145. package/build-types/components/dataviews/stories/fixtures.d.ts.map +1 -1
  146. package/build-types/components/dataviews/stories/index.story.d.ts +9 -0
  147. package/build-types/components/dataviews/stories/index.story.d.ts.map +1 -1
  148. package/build-types/components/dataviews-bulk-actions/index.d.ts.map +1 -1
  149. package/build-types/components/dataviews-filters/add-filter.d.ts +3 -0
  150. package/build-types/components/dataviews-filters/add-filter.d.ts.map +1 -1
  151. package/build-types/components/dataviews-filters/index.d.ts +11 -1
  152. package/build-types/components/dataviews-filters/index.d.ts.map +1 -1
  153. package/build-types/components/dataviews-filters/search-widget.d.ts.map +1 -1
  154. package/build-types/components/dataviews-pagination/index.d.ts.map +1 -1
  155. package/build-types/components/dataviews-search/index.d.ts.map +1 -1
  156. package/build-types/components/dataviews-view-config/index.d.ts +4 -3
  157. package/build-types/components/dataviews-view-config/index.d.ts.map +1 -1
  158. package/build-types/constants.d.ts +4 -0
  159. package/build-types/constants.d.ts.map +1 -1
  160. package/build-types/dataform-controls/datetime.d.ts +6 -0
  161. package/build-types/dataform-controls/datetime.d.ts.map +1 -0
  162. package/build-types/dataform-controls/index.d.ts +11 -0
  163. package/build-types/dataform-controls/index.d.ts.map +1 -0
  164. package/build-types/dataform-controls/integer.d.ts +6 -0
  165. package/build-types/dataform-controls/integer.d.ts.map +1 -0
  166. package/build-types/dataform-controls/radio.d.ts +6 -0
  167. package/build-types/dataform-controls/radio.d.ts.map +1 -0
  168. package/build-types/dataform-controls/select.d.ts +6 -0
  169. package/build-types/dataform-controls/select.d.ts.map +1 -0
  170. package/build-types/dataform-controls/text.d.ts +6 -0
  171. package/build-types/dataform-controls/text.d.ts.map +1 -0
  172. package/build-types/dataforms-layouts/index.d.ts +9 -0
  173. package/build-types/dataforms-layouts/index.d.ts.map +1 -0
  174. package/build-types/dataforms-layouts/panel/index.d.ts +3 -0
  175. package/build-types/dataforms-layouts/panel/index.d.ts.map +1 -0
  176. package/build-types/dataforms-layouts/regular/index.d.ts +3 -0
  177. package/build-types/dataforms-layouts/regular/index.d.ts.map +1 -0
  178. package/build-types/dataviews-layouts/grid/density-picker.d.ts.map +1 -0
  179. package/build-types/dataviews-layouts/grid/index.d.ts.map +1 -0
  180. package/build-types/dataviews-layouts/index.d.ts.map +1 -0
  181. package/build-types/dataviews-layouts/list/index.d.ts.map +1 -0
  182. package/build-types/dataviews-layouts/table/column-header-menu.d.ts.map +1 -0
  183. package/build-types/dataviews-layouts/table/index.d.ts.map +1 -0
  184. package/build-types/field-types/datetime.d.ts +13 -0
  185. package/build-types/field-types/datetime.d.ts.map +1 -0
  186. package/build-types/field-types/index.d.ts +20 -0
  187. package/build-types/field-types/index.d.ts.map +1 -0
  188. package/build-types/field-types/integer.d.ts +13 -0
  189. package/build-types/field-types/integer.d.ts.map +1 -0
  190. package/build-types/field-types/text.d.ts +13 -0
  191. package/build-types/field-types/text.d.ts.map +1 -0
  192. package/build-types/filter-and-sort-data-view.d.ts.map +1 -1
  193. package/build-types/index.d.ts +2 -1
  194. package/build-types/index.d.ts.map +1 -1
  195. package/build-types/normalize-fields.d.ts +0 -3
  196. package/build-types/normalize-fields.d.ts.map +1 -1
  197. package/build-types/types.d.ts +73 -18
  198. package/build-types/types.d.ts.map +1 -1
  199. package/build-types/validation.d.ts +3 -0
  200. package/build-types/validation.d.ts.map +1 -0
  201. package/package.json +12 -11
  202. package/src/components/dataform/index.tsx +8 -97
  203. package/src/components/dataform/stories/index.story.tsx +82 -4
  204. package/src/components/dataviews/index.tsx +26 -14
  205. package/src/components/dataviews/stories/fixtures.js +30 -1
  206. package/src/components/dataviews/stories/index.story.js +7 -1
  207. package/src/components/dataviews/style.scss +5 -14
  208. package/src/components/dataviews-bulk-actions/index.tsx +5 -0
  209. package/src/components/dataviews-bulk-actions-toolbar/style.scss +1 -1
  210. package/src/components/dataviews-filters/add-filter.tsx +37 -21
  211. package/src/components/dataviews-filters/index.tsx +152 -61
  212. package/src/components/dataviews-filters/search-widget.tsx +1 -8
  213. package/src/components/dataviews-filters/style.scss +31 -1
  214. package/src/components/dataviews-layout/index.tsx +1 -1
  215. package/src/components/dataviews-pagination/index.tsx +35 -16
  216. package/src/components/dataviews-pagination/style.scss +9 -4
  217. package/src/components/dataviews-search/index.tsx +8 -5
  218. package/src/components/dataviews-view-config/index.tsx +300 -257
  219. package/src/components/dataviews-view-config/style.scss +44 -0
  220. package/src/constants.ts +5 -0
  221. package/src/dataform-controls/datetime.tsx +43 -0
  222. package/src/dataform-controls/index.tsx +61 -0
  223. package/src/dataform-controls/integer.tsx +38 -0
  224. package/src/dataform-controls/radio.tsx +42 -0
  225. package/src/dataform-controls/select.tsx +52 -0
  226. package/src/dataform-controls/style.scss +4 -0
  227. package/src/dataform-controls/text.tsx +40 -0
  228. package/src/dataforms-layouts/index.tsx +20 -0
  229. package/src/dataforms-layouts/panel/index.tsx +168 -0
  230. package/src/dataforms-layouts/panel/style.scss +59 -0
  231. package/src/dataforms-layouts/regular/index.tsx +45 -0
  232. package/src/dataviews-layouts/grid/density-picker.tsx +102 -0
  233. package/src/{layouts → dataviews-layouts}/grid/index.tsx +9 -9
  234. package/src/{layouts → dataviews-layouts}/grid/style.scss +29 -4
  235. package/src/{layouts → dataviews-layouts}/list/index.tsx +6 -2
  236. package/src/{layouts → dataviews-layouts}/list/style.scss +4 -1
  237. package/src/{layouts → dataviews-layouts}/table/column-header-menu.tsx +4 -6
  238. package/src/field-types/datetime.tsx +28 -0
  239. package/src/field-types/index.tsx +50 -0
  240. package/src/field-types/integer.tsx +34 -0
  241. package/src/field-types/text.tsx +27 -0
  242. package/src/filter-and-sort-data-view.ts +1 -15
  243. package/src/index.ts +2 -1
  244. package/src/normalize-fields.ts +43 -4
  245. package/src/style.scss +7 -3
  246. package/src/test/filter-and-sort-data-view.js +74 -3
  247. package/src/test/validation.ts +131 -0
  248. package/src/types.ts +92 -23
  249. package/src/validation.ts +18 -0
  250. package/tsconfig.json +2 -1
  251. package/tsconfig.tsbuildinfo +1 -1
  252. package/build/layouts/grid/density-picker.js +0 -143
  253. package/build/layouts/grid/density-picker.js.map +0 -1
  254. package/build/layouts/grid/index.js.map +0 -1
  255. package/build/layouts/index.js.map +0 -1
  256. package/build/layouts/list/index.js.map +0 -1
  257. package/build/layouts/table/column-header-menu.js.map +0 -1
  258. package/build/layouts/table/index.js.map +0 -1
  259. package/build-module/layouts/grid/density-picker.js +0 -138
  260. package/build-module/layouts/grid/density-picker.js.map +0 -1
  261. package/build-module/layouts/grid/index.js.map +0 -1
  262. package/build-module/layouts/index.js.map +0 -1
  263. package/build-module/layouts/list/index.js.map +0 -1
  264. package/build-module/layouts/table/column-header-menu.js.map +0 -1
  265. package/build-module/layouts/table/index.js.map +0 -1
  266. package/build-types/layouts/grid/density-picker.d.ts.map +0 -1
  267. package/build-types/layouts/grid/index.d.ts.map +0 -1
  268. package/build-types/layouts/index.d.ts.map +0 -1
  269. package/build-types/layouts/list/index.d.ts.map +0 -1
  270. package/build-types/layouts/table/column-header-menu.d.ts.map +0 -1
  271. package/build-types/layouts/table/index.d.ts.map +0 -1
  272. package/src/layouts/grid/density-picker.tsx +0 -136
  273. /package/build/{layouts → dataviews-layouts}/index.js +0 -0
  274. /package/build/{layouts → dataviews-layouts}/table/index.js +0 -0
  275. /package/build-module/{layouts → dataviews-layouts}/index.js +0 -0
  276. /package/build-module/{layouts → dataviews-layouts}/table/index.js +0 -0
  277. /package/build-types/{layouts → dataviews-layouts}/grid/density-picker.d.ts +0 -0
  278. /package/build-types/{layouts → dataviews-layouts}/grid/index.d.ts +0 -0
  279. /package/build-types/{layouts → dataviews-layouts}/index.d.ts +0 -0
  280. /package/build-types/{layouts → dataviews-layouts}/list/index.d.ts +0 -0
  281. /package/build-types/{layouts → dataviews-layouts}/table/column-header-menu.d.ts +0 -0
  282. /package/build-types/{layouts → dataviews-layouts}/table/index.d.ts +0 -0
  283. /package/src/{layouts → dataviews-layouts}/index.ts +0 -0
  284. /package/src/{layouts → dataviews-layouts}/table/index.tsx +0 -0
  285. /package/src/{layouts → dataviews-layouts}/table/style.scss +0 -0
@@ -8,131 +8,98 @@ import type { ChangeEvent } from 'react';
8
8
  */
9
9
  import {
10
10
  Button,
11
- privateApis as componentsPrivateApis,
11
+ Popover,
12
+ __experimentalToggleGroupControl as ToggleGroupControl,
13
+ __experimentalToggleGroupControlOption as ToggleGroupControlOption,
14
+ __experimentalToggleGroupControlOptionIcon as ToggleGroupControlOptionIcon,
15
+ SelectControl,
16
+ __experimentalItemGroup as ItemGroup,
17
+ __experimentalItem as Item,
18
+ __experimentalGrid as Grid,
19
+ __experimentalVStack as VStack,
12
20
  __experimentalHStack as HStack,
21
+ __experimentalHeading as Heading,
22
+ __experimentalText as Text,
23
+ privateApis as componentsPrivateApis,
13
24
  } from '@wordpress/components';
14
25
  import { __, _x } from '@wordpress/i18n';
15
- import { memo, useContext } from '@wordpress/element';
16
- import { cog } from '@wordpress/icons';
26
+ import { memo, useContext, useState, useMemo } from '@wordpress/element';
27
+ import { cog, seen, unseen } from '@wordpress/icons';
28
+ import warning from '@wordpress/warning';
17
29
 
18
30
  /**
19
31
  * Internal dependencies
20
32
  */
21
- import { unlock } from '../../lock-unlock';
22
- import { SORTING_DIRECTIONS, sortLabels } from '../../constants';
23
- import { VIEW_LAYOUTS, getMandatoryFields } from '../../layouts';
24
- import type { NormalizedField, View, SupportedLayouts } from '../../types';
33
+ import {
34
+ SORTING_DIRECTIONS,
35
+ LAYOUT_GRID,
36
+ sortIcons,
37
+ sortLabels,
38
+ } from '../../constants';
39
+ import { VIEW_LAYOUTS, getMandatoryFields } from '../../dataviews-layouts';
40
+ import type { SupportedLayouts } from '../../types';
25
41
  import DataViewsContext from '../dataviews-context';
42
+ import { unlock } from '../../lock-unlock';
43
+ import DensityPicker from '../../dataviews-layouts/grid/density-picker';
26
44
 
27
45
  const {
28
46
  DropdownMenuV2: DropdownMenu,
29
- DropdownMenuGroupV2: DropdownMenuGroup,
30
- DropdownMenuItemV2: DropdownMenuItem,
31
47
  DropdownMenuRadioItemV2: DropdownMenuRadioItem,
32
- DropdownMenuCheckboxItemV2: DropdownMenuCheckboxItem,
33
48
  DropdownMenuItemLabelV2: DropdownMenuItemLabel,
34
49
  } = unlock( componentsPrivateApis );
35
50
 
36
51
  interface ViewTypeMenuProps {
37
- view: View;
38
- onChangeView: ( view: View ) => void;
39
- defaultLayouts?: SupportedLayouts;
40
- }
41
-
42
- interface PageSizeMenuProps {
43
- view: View;
44
- onChangeView: ( view: View ) => void;
45
- }
46
-
47
- interface FieldsVisibilityMenuProps< Item > {
48
- view: View;
49
- onChangeView: ( view: View ) => void;
50
- fields: NormalizedField< Item >[];
51
- }
52
-
53
- interface SortMenuProps< Item > {
54
- fields: NormalizedField< Item >[];
55
- view: View;
56
- onChangeView: ( view: View ) => void;
57
- }
58
-
59
- interface ViewActionsProps {
60
52
  defaultLayouts?: SupportedLayouts;
61
53
  }
62
54
 
63
55
  function ViewTypeMenu( {
64
- view,
65
- onChangeView,
66
56
  defaultLayouts = { list: {}, grid: {}, table: {} },
67
57
  }: ViewTypeMenuProps ) {
58
+ const { view, onChangeView } = useContext( DataViewsContext );
68
59
  const availableLayouts = Object.keys( defaultLayouts );
69
60
  if ( availableLayouts.length <= 1 ) {
70
61
  return null;
71
62
  }
72
- return availableLayouts.map( ( layout ) => {
73
- const config = VIEW_LAYOUTS.find( ( v ) => v.type === layout );
74
- if ( ! config ) {
75
- return null;
76
- }
77
- return (
78
- <DropdownMenuRadioItem
79
- key={ layout }
80
- value={ layout }
81
- name="view-actions-available-view"
82
- checked={ layout === view.type }
83
- hideOnClick
84
- onChange={ ( e: ChangeEvent< HTMLInputElement > ) => {
85
- switch ( e.target.value ) {
86
- case 'list':
87
- case 'grid':
88
- case 'table':
89
- return onChangeView( {
90
- ...view,
91
- type: e.target.value,
92
- ...defaultLayouts[ e.target.value ],
93
- } );
94
- }
95
- throw new Error( 'Invalid dataview' );
96
- } }
97
- >
98
- <DropdownMenuItemLabel>{ config.label }</DropdownMenuItemLabel>
99
- </DropdownMenuRadioItem>
100
- );
101
- } );
102
- }
103
-
104
- const PAGE_SIZE_VALUES = [ 10, 20, 50, 100 ];
105
- function PageSizeMenu( { view, onChangeView }: PageSizeMenuProps ) {
63
+ const activeView = VIEW_LAYOUTS.find( ( v ) => view.type === v.type );
106
64
  return (
107
65
  <DropdownMenu
108
66
  trigger={
109
- <DropdownMenuItem
110
- suffix={ <span aria-hidden="true">{ view.perPage }</span> }
111
- >
112
- <DropdownMenuItemLabel>
113
- { __( 'Items per page' ) }
114
- </DropdownMenuItemLabel>
115
- </DropdownMenuItem>
67
+ <Button
68
+ size="compact"
69
+ icon={ activeView?.icon }
70
+ label={ __( 'Layout' ) }
71
+ />
116
72
  }
117
73
  >
118
- { PAGE_SIZE_VALUES.map( ( size ) => {
74
+ { availableLayouts.map( ( layout ) => {
75
+ const config = VIEW_LAYOUTS.find( ( v ) => v.type === layout );
76
+ if ( ! config ) {
77
+ return null;
78
+ }
119
79
  return (
120
80
  <DropdownMenuRadioItem
121
- key={ size }
122
- value={ size }
123
- name="view-actions-page-size"
124
- checked={ view.perPage === size }
125
- onChange={ () => {
126
- onChangeView( {
127
- ...view,
128
- // `e.target.value` holds the same value as `size` but as a string,
129
- // so we use `size` directly to avoid parsing to int.
130
- perPage: size,
131
- page: 1,
132
- } );
81
+ key={ layout }
82
+ value={ layout }
83
+ name="view-actions-available-view"
84
+ checked={ layout === view.type }
85
+ hideOnClick
86
+ onChange={ ( e: ChangeEvent< HTMLInputElement > ) => {
87
+ switch ( e.target.value ) {
88
+ case 'list':
89
+ case 'grid':
90
+ case 'table':
91
+ return onChangeView( {
92
+ ...view,
93
+ type: e.target.value,
94
+ ...defaultLayouts[ e.target.value ],
95
+ } );
96
+ }
97
+ warning( 'Invalid dataview' );
133
98
  } }
134
99
  >
135
- <DropdownMenuItemLabel>{ size }</DropdownMenuItemLabel>
100
+ <DropdownMenuItemLabel>
101
+ { config.label }
102
+ </DropdownMenuItemLabel>
136
103
  </DropdownMenuRadioItem>
137
104
  );
138
105
  } ) }
@@ -140,11 +107,127 @@ function PageSizeMenu( { view, onChangeView }: PageSizeMenuProps ) {
140
107
  );
141
108
  }
142
109
 
143
- function FieldsVisibilityMenu< Item >( {
144
- view,
145
- onChangeView,
146
- fields,
147
- }: FieldsVisibilityMenuProps< Item > ) {
110
+ function SortFieldControl() {
111
+ const { view, fields, onChangeView } = useContext( DataViewsContext );
112
+ const orderOptions = useMemo( () => {
113
+ const sortableFields = fields.filter(
114
+ ( field ) => field.enableSorting !== false
115
+ );
116
+ return sortableFields.map( ( field ) => {
117
+ return {
118
+ label: field.label,
119
+ value: field.id,
120
+ };
121
+ } );
122
+ }, [ fields ] );
123
+
124
+ return (
125
+ <SelectControl
126
+ __nextHasNoMarginBottom
127
+ __next40pxDefaultSize
128
+ label={ __( 'Sort by' ) }
129
+ value={ view.sort?.field }
130
+ options={ orderOptions }
131
+ onChange={ ( value: string ) => {
132
+ onChangeView( {
133
+ ...view,
134
+ sort: {
135
+ direction: view?.sort?.direction || 'desc',
136
+ field: value,
137
+ },
138
+ } );
139
+ } }
140
+ />
141
+ );
142
+ }
143
+
144
+ function SortDirectionControl() {
145
+ const { view, fields, onChangeView } = useContext( DataViewsContext );
146
+ let value = view.sort?.direction;
147
+ if ( ! value && view.sort?.field ) {
148
+ value = 'desc';
149
+ }
150
+ return (
151
+ <ToggleGroupControl
152
+ className="dataviews-view-config__sort-direction"
153
+ __nextHasNoMarginBottom
154
+ __next40pxDefaultSize
155
+ isBlock
156
+ label={ __( 'Order' ) }
157
+ value={ value }
158
+ onChange={ ( newDirection ) => {
159
+ if ( newDirection === 'asc' || newDirection === 'desc' ) {
160
+ onChangeView( {
161
+ ...view,
162
+ sort: {
163
+ direction: newDirection,
164
+ field:
165
+ view.sort?.field ||
166
+ // If there is no field assigned as the sorting field assign the first sortable field.
167
+ fields.find(
168
+ ( field ) => field.enableSorting !== false
169
+ )?.id ||
170
+ '',
171
+ },
172
+ } );
173
+ return;
174
+ }
175
+ warning( 'Invalid direction' );
176
+ } }
177
+ >
178
+ { SORTING_DIRECTIONS.map( ( direction ) => {
179
+ return (
180
+ <ToggleGroupControlOptionIcon
181
+ key={ direction }
182
+ value={ direction }
183
+ icon={ sortIcons[ direction ] }
184
+ label={ sortLabels[ direction ] }
185
+ />
186
+ );
187
+ } ) }
188
+ </ToggleGroupControl>
189
+ );
190
+ }
191
+
192
+ const PAGE_SIZE_VALUES = [ 10, 20, 50, 100 ];
193
+ function ItemsPerPageControl() {
194
+ const { view, onChangeView } = useContext( DataViewsContext );
195
+ return (
196
+ <ToggleGroupControl
197
+ __nextHasNoMarginBottom
198
+ __next40pxDefaultSize
199
+ isBlock
200
+ label={ __( 'Items per page' ) }
201
+ value={ view.perPage || 10 }
202
+ disabled={ ! view?.sort?.field }
203
+ onChange={ ( newItemsPerPage ) => {
204
+ const newItemsPerPageNumber =
205
+ typeof newItemsPerPage === 'number' ||
206
+ newItemsPerPage === undefined
207
+ ? newItemsPerPage
208
+ : parseInt( newItemsPerPage, 10 );
209
+ onChangeView( {
210
+ ...view,
211
+ perPage: newItemsPerPageNumber,
212
+ page: 1,
213
+ } );
214
+ } }
215
+ >
216
+ { PAGE_SIZE_VALUES.map( ( value ) => {
217
+ return (
218
+ <ToggleGroupControlOption
219
+ key={ value }
220
+ value={ value }
221
+ label={ value.toString() }
222
+ />
223
+ );
224
+ } ) }
225
+ </ToggleGroupControl>
226
+ );
227
+ }
228
+
229
+ function FieldControl() {
230
+ const { view, fields, onChangeView } = useContext( DataViewsContext );
148
231
  const mandatoryFields = getMandatoryFields( view );
149
232
  const hidableFields = fields.filter(
150
233
  ( field ) =>
@@ -156,185 +239,145 @@ function FieldsVisibilityMenu< Item >( {
156
239
  return null;
157
240
  }
158
241
  return (
159
- <DropdownMenu
160
- trigger={
161
- <DropdownMenuItem>
162
- <DropdownMenuItemLabel>
163
- { __( 'Fields' ) }
164
- </DropdownMenuItemLabel>
165
- </DropdownMenuItem>
166
- }
167
- >
242
+ <ItemGroup isBordered isSeparated>
168
243
  { hidableFields?.map( ( field ) => {
244
+ const isVisible = viewFields.includes( field.id );
169
245
  return (
170
- <DropdownMenuCheckboxItem
171
- key={ field.id }
172
- value={ field.id }
173
- checked={ viewFields.includes( field.id ) }
174
- onChange={ () => {
175
- onChangeView( {
176
- ...view,
177
- fields: viewFields.includes( field.id )
178
- ? viewFields.filter(
179
- ( id ) => id !== field.id
180
- )
181
- : [ ...viewFields, field.id ],
182
- } );
183
- } }
184
- >
185
- <DropdownMenuItemLabel>
186
- { field.label }
187
- </DropdownMenuItemLabel>
188
- </DropdownMenuCheckboxItem>
246
+ <Item key={ field.id }>
247
+ <HStack expanded>
248
+ <span>{ field.label }</span>
249
+ <Button
250
+ size="compact"
251
+ onClick={ () =>
252
+ onChangeView( {
253
+ ...view,
254
+ fields: isVisible
255
+ ? viewFields.filter(
256
+ ( id ) => id !== field.id
257
+ )
258
+ : [ ...viewFields, field.id ],
259
+ } )
260
+ }
261
+ icon={ isVisible ? seen : unseen }
262
+ label={
263
+ isVisible
264
+ ? __( 'Hide field' )
265
+ : __( 'Show field' )
266
+ }
267
+ />
268
+ </HStack>
269
+ </Item>
189
270
  );
190
271
  } ) }
191
- </DropdownMenu>
272
+ </ItemGroup>
192
273
  );
193
274
  }
194
275
 
195
- function SortMenu< Item >( {
196
- fields,
197
- view,
198
- onChangeView,
199
- }: SortMenuProps< Item > ) {
200
- const sortableFields = fields.filter(
201
- ( field ) => field.enableSorting !== false
202
- );
203
- if ( ! sortableFields?.length ) {
204
- return null;
205
- }
206
- const currentSortedField = fields.find(
207
- ( field ) => field.id === view.sort?.field
208
- );
276
+ function SettingsSection( {
277
+ title,
278
+ description,
279
+ children,
280
+ }: {
281
+ title: string;
282
+ description?: string;
283
+ children: React.ReactNode;
284
+ } ) {
209
285
  return (
210
- <DropdownMenu
211
- trigger={
212
- <DropdownMenuItem
213
- suffix={
214
- <span aria-hidden="true">
215
- { currentSortedField?.label }
216
- </span>
217
- }
286
+ <Grid columns={ 12 } className="dataviews-settings-section" gap={ 4 }>
287
+ <div className="dataviews-settings-section__sidebar">
288
+ <Heading
289
+ level={ 2 }
290
+ className="dataviews-settings-section__title"
218
291
  >
219
- <DropdownMenuItemLabel>
220
- { __( 'Sort by' ) }
221
- </DropdownMenuItemLabel>
222
- </DropdownMenuItem>
223
- }
224
- >
225
- { sortableFields?.map( ( field ) => {
226
- const sortedDirection = view.sort?.direction;
227
- return (
228
- <DropdownMenu
229
- key={ field.id }
230
- trigger={
231
- <DropdownMenuItem>
232
- <DropdownMenuItemLabel>
233
- { field.label }
234
- </DropdownMenuItemLabel>
235
- </DropdownMenuItem>
236
- }
237
- style={ {
238
- minWidth: '220px',
239
- } }
292
+ { title }
293
+ </Heading>
294
+ { description && (
295
+ <Text
296
+ variant="muted"
297
+ className="dataviews-settings-section__description"
240
298
  >
241
- { SORTING_DIRECTIONS.map( ( direction ) => {
242
- const isChecked =
243
- currentSortedField !== undefined &&
244
- sortedDirection === direction &&
245
- field.id === currentSortedField.id;
246
-
247
- const value = `${ field.id }-${ direction }`;
299
+ { description }
300
+ </Text>
301
+ ) }
302
+ </div>
303
+ <Grid
304
+ columns={ 8 }
305
+ gap={ 4 }
306
+ className="dataviews-settings-section__content"
307
+ >
308
+ { children }
309
+ </Grid>
310
+ </Grid>
311
+ );
312
+ }
248
313
 
249
- return (
250
- <DropdownMenuRadioItem
251
- key={ value }
252
- // All sorting radio items share the same name, so that
253
- // selecting a sorting option automatically deselects the
254
- // previously selected one, even if it is displayed in
255
- // another submenu. The field and direction are passed via
256
- // the `value` prop.
257
- name="view-actions-sorting"
258
- value={ value }
259
- checked={ isChecked }
260
- onChange={ () => {
261
- onChangeView( {
262
- ...view,
263
- sort: {
264
- field: field.id,
265
- direction,
266
- },
267
- } );
268
- } }
269
- >
270
- <DropdownMenuItemLabel>
271
- { sortLabels[ direction ] }
272
- </DropdownMenuItemLabel>
273
- </DropdownMenuRadioItem>
274
- );
275
- } ) }
276
- </DropdownMenu>
277
- );
278
- } ) }
279
- </DropdownMenu>
314
+ function DataviewsViewConfigContent( {
315
+ density,
316
+ setDensity,
317
+ }: {
318
+ density: number;
319
+ setDensity: React.Dispatch< React.SetStateAction< number > >;
320
+ } ) {
321
+ const { view } = useContext( DataViewsContext );
322
+ return (
323
+ <VStack className="dataviews-view-config" spacing={ 6 }>
324
+ <SettingsSection title={ __( 'Appearance' ) }>
325
+ <HStack expanded className="is-divided-in-two">
326
+ <SortFieldControl />
327
+ <SortDirectionControl />
328
+ </HStack>
329
+ { view.type === LAYOUT_GRID && (
330
+ <DensityPicker
331
+ density={ density }
332
+ setDensity={ setDensity }
333
+ />
334
+ ) }
335
+ <ItemsPerPageControl />
336
+ </SettingsSection>
337
+ <SettingsSection title={ __( 'Properties' ) }>
338
+ <FieldControl />
339
+ </SettingsSection>
340
+ </VStack>
280
341
  );
281
342
  }
282
343
 
283
- function _DataViewsViewConfig( { defaultLayouts }: ViewActionsProps ) {
284
- const { view, fields, onChangeView } = useContext( DataViewsContext );
285
- const activeView = VIEW_LAYOUTS.find( ( v ) => view.type === v.type );
344
+ function _DataViewsViewConfig( {
345
+ density,
346
+ setDensity,
347
+ defaultLayouts = { list: {}, grid: {}, table: {} },
348
+ }: {
349
+ density: number;
350
+ setDensity: React.Dispatch< React.SetStateAction< number > >;
351
+ defaultLayouts?: SupportedLayouts;
352
+ } ) {
353
+ const [ isShowingViewPopover, setIsShowingViewPopover ] =
354
+ useState< boolean >( false );
355
+
286
356
  return (
287
357
  <>
288
- <HStack
289
- spacing={ 1 }
290
- expanded={ false }
291
- style={ { flexShrink: 0 } }
292
- >
293
- <DropdownMenu
294
- trigger={
295
- <Button
296
- size="compact"
297
- icon={ activeView?.icon }
298
- label={ __( 'Layout' ) }
299
- />
300
- }
301
- >
302
- <ViewTypeMenu
303
- view={ view }
304
- onChangeView={ onChangeView }
305
- defaultLayouts={ defaultLayouts }
306
- />
307
- </DropdownMenu>
308
- <DropdownMenu
309
- trigger={
310
- <Button
311
- size="compact"
312
- icon={ cog }
313
- label={ _x(
314
- 'View options',
315
- 'View is used as a noun'
316
- ) }
317
- />
318
- }
319
- >
320
- <DropdownMenuGroup>
321
- <SortMenu
322
- fields={ fields }
323
- view={ view }
324
- onChangeView={ onChangeView }
325
- />
326
- <FieldsVisibilityMenu
327
- fields={ fields }
328
- view={ view }
329
- onChangeView={ onChangeView }
330
- />
331
- <PageSizeMenu
332
- view={ view }
333
- onChangeView={ onChangeView }
358
+ <ViewTypeMenu defaultLayouts={ defaultLayouts } />
359
+ <div>
360
+ <Button
361
+ size="compact"
362
+ icon={ cog }
363
+ label={ _x( 'View options', 'View is used as a noun' ) }
364
+ onClick={ () => setIsShowingViewPopover( true ) }
365
+ />
366
+ { isShowingViewPopover && (
367
+ <Popover
368
+ placement="bottom-end"
369
+ onClose={ () => {
370
+ setIsShowingViewPopover( false );
371
+ } }
372
+ focusOnMount
373
+ >
374
+ <DataviewsViewConfigContent
375
+ density={ density }
376
+ setDensity={ setDensity }
334
377
  />
335
- </DropdownMenuGroup>
336
- </DropdownMenu>
337
- </HStack>
378
+ </Popover>
379
+ ) }
380
+ </div>
338
381
  </>
339
382
  );
340
383
  }
@@ -0,0 +1,44 @@
1
+ .dataviews-view-config {
2
+ width: 320px;
3
+ /* stylelint-disable-next-line property-no-unknown -- the linter needs to be updated to accepted the container-type property */
4
+ container-type: inline-size;
5
+ padding: $grid-unit-20;
6
+ }
7
+ .dataviews-view-config__sort-direction .components-toggle-group-control-option-base {
8
+ text-transform: uppercase;
9
+ }
10
+
11
+ .dataviews-settings-section__title.dataviews-settings-section__title {
12
+ line-height: $grid-unit-30;
13
+ font-size: 15px;
14
+ }
15
+
16
+ .dataviews-settings-section__sidebar {
17
+ grid-column: span 4;
18
+ }
19
+
20
+ .dataviews-settings-section__content,
21
+ .dataviews-settings-section__content > * {
22
+ grid-column: span 8;
23
+ }
24
+
25
+ .dataviews-settings-section__content .is-divided-in-two {
26
+ display: contents;
27
+ & > * {
28
+ grid-column: span 4;
29
+ }
30
+ }
31
+
32
+ /* stylelint-disable-next-line scss/at-rule-no-unknown -- '@container' not globally permitted */
33
+ @container (max-width: 500px) {
34
+ .dataviews-settings-section.dataviews-settings-section {
35
+ grid-template-columns: repeat(2, 1fr);
36
+ .dataviews-settings-section__sidebar {
37
+ grid-column: span 2;
38
+ }
39
+
40
+ .dataviews-settings-section__content {
41
+ grid-column: span 2;
42
+ }
43
+ }
44
+ }
package/src/constants.ts CHANGED
@@ -2,6 +2,7 @@
2
2
  * WordPress dependencies
3
3
  */
4
4
  import { __ } from '@wordpress/i18n';
5
+ import { arrowDown, arrowUp } from '@wordpress/icons';
5
6
 
6
7
  /**
7
8
  * Internal dependencies
@@ -58,6 +59,10 @@ export const sortLabels = {
58
59
  asc: __( 'Sort ascending' ),
59
60
  desc: __( 'Sort descending' ),
60
61
  };
62
+ export const sortIcons = {
63
+ asc: arrowUp,
64
+ desc: arrowDown,
65
+ };
61
66
 
62
67
  // View layouts.
63
68
  export const LAYOUT_TABLE = 'table';