@wordpress/dataviews 8.0.1-next.e256d081a.0 → 9.0.1-next.6870dfe5b.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 (269) hide show
  1. package/CHANGELOG.md +24 -1
  2. package/README.md +96 -1
  3. package/build/components/dataform-context/index.js +1 -0
  4. package/build/components/dataform-context/index.js.map +1 -1
  5. package/build/components/dataviews/index.js +11 -1
  6. package/build/components/dataviews/index.js.map +1 -1
  7. package/build/components/dataviews-context/index.js +1 -0
  8. package/build/components/dataviews-context/index.js.map +1 -1
  9. package/build/components/dataviews-layout/index.js +2 -1
  10. package/build/components/dataviews-layout/index.js.map +1 -1
  11. package/build/components/dataviews-picker/footer.js +145 -0
  12. package/build/components/dataviews-picker/footer.js.map +1 -0
  13. package/build/components/dataviews-picker/index.js +201 -0
  14. package/build/components/dataviews-picker/index.js.map +1 -0
  15. package/build/components/dataviews-selection-checkbox/index.js +4 -2
  16. package/build/components/dataviews-selection-checkbox/index.js.map +1 -1
  17. package/build/components/dataviews-view-config/index.js +1 -0
  18. package/build/components/dataviews-view-config/index.js.map +1 -1
  19. package/build/constants.js +4 -1
  20. package/build/constants.js.map +1 -1
  21. package/build/dataform-controls/checkbox.js +23 -2
  22. package/build/dataform-controls/checkbox.js.map +1 -1
  23. package/build/dataform-controls/color.js +128 -0
  24. package/build/dataform-controls/color.js.map +1 -0
  25. package/build/dataform-controls/email.js +10 -45
  26. package/build/dataform-controls/email.js.map +1 -1
  27. package/build/dataform-controls/index.js +8 -2
  28. package/build/dataform-controls/index.js.map +1 -1
  29. package/build/dataform-controls/telephone.js +34 -0
  30. package/build/dataform-controls/telephone.js.map +1 -0
  31. package/build/dataform-controls/text.js +7 -48
  32. package/build/dataform-controls/text.js.map +1 -1
  33. package/build/dataform-controls/{boolean.js → toggle.js} +6 -4
  34. package/build/dataform-controls/toggle.js.map +1 -0
  35. package/build/dataform-controls/url.js +34 -0
  36. package/build/dataform-controls/url.js.map +1 -0
  37. package/build/dataform-controls/utils/validated-text.js +76 -0
  38. package/build/dataform-controls/utils/validated-text.js.map +1 -0
  39. package/build/dataforms-layouts/card/index.js +6 -7
  40. package/build/dataforms-layouts/card/index.js.map +1 -1
  41. package/build/dataforms-layouts/data-form-layout.js +16 -4
  42. package/build/dataforms-layouts/data-form-layout.js.map +1 -1
  43. package/build/dataforms-layouts/index.js +31 -1
  44. package/build/dataforms-layouts/index.js.map +1 -1
  45. package/build/dataforms-layouts/row/index.js +113 -0
  46. package/build/dataforms-layouts/row/index.js.map +1 -0
  47. package/build/dataviews-layouts/grid/index.js +16 -11
  48. package/build/dataviews-layouts/grid/index.js.map +1 -1
  49. package/build/dataviews-layouts/index.js +9 -1
  50. package/build/dataviews-layouts/index.js.map +1 -1
  51. package/build/dataviews-layouts/picker-grid/index.js +357 -0
  52. package/build/dataviews-layouts/picker-grid/index.js.map +1 -0
  53. package/build/dataviews-layouts/utils/grid-items.js +37 -0
  54. package/build/dataviews-layouts/utils/grid-items.js.map +1 -0
  55. package/build/dataviews-layouts/utils/preview-size-picker.js +81 -0
  56. package/build/dataviews-layouts/utils/preview-size-picker.js.map +1 -0
  57. package/build/field-types/boolean.js +1 -1
  58. package/build/field-types/boolean.js.map +1 -1
  59. package/build/field-types/color.js +113 -0
  60. package/build/field-types/color.js.map +1 -0
  61. package/build/field-types/index.js +12 -0
  62. package/build/field-types/index.js.map +1 -1
  63. package/build/field-types/telephone.js +57 -0
  64. package/build/field-types/telephone.js.map +1 -0
  65. package/build/field-types/url.js +57 -0
  66. package/build/field-types/url.js.map +1 -0
  67. package/build/normalize-form-fields.js +6 -0
  68. package/build/normalize-form-fields.js.map +1 -1
  69. package/build/types.js.map +1 -1
  70. package/build/validation.js +1 -1
  71. package/build/validation.js.map +1 -1
  72. package/build-module/components/dataform-context/index.js +1 -0
  73. package/build-module/components/dataform-context/index.js.map +1 -1
  74. package/build-module/components/dataviews/index.js +11 -1
  75. package/build-module/components/dataviews/index.js.map +1 -1
  76. package/build-module/components/dataviews-context/index.js +1 -0
  77. package/build-module/components/dataviews-context/index.js.map +1 -1
  78. package/build-module/components/dataviews-layout/index.js +2 -1
  79. package/build-module/components/dataviews-layout/index.js.map +1 -1
  80. package/build-module/components/dataviews-picker/footer.js +136 -0
  81. package/build-module/components/dataviews-picker/footer.js.map +1 -0
  82. package/build-module/components/dataviews-picker/index.js +191 -0
  83. package/build-module/components/dataviews-picker/index.js.map +1 -0
  84. package/build-module/components/dataviews-selection-checkbox/index.js +4 -2
  85. package/build-module/components/dataviews-selection-checkbox/index.js.map +1 -1
  86. package/build-module/components/dataviews-view-config/index.js +1 -0
  87. package/build-module/components/dataviews-view-config/index.js.map +1 -1
  88. package/build-module/constants.js +3 -0
  89. package/build-module/constants.js.map +1 -1
  90. package/build-module/dataform-controls/checkbox.js +25 -3
  91. package/build-module/dataform-controls/checkbox.js.map +1 -1
  92. package/build-module/dataform-controls/color.js +122 -0
  93. package/build-module/dataform-controls/color.js.map +1 -0
  94. package/build-module/dataform-controls/email.js +9 -45
  95. package/build-module/dataform-controls/email.js.map +1 -1
  96. package/build-module/dataform-controls/index.js +8 -2
  97. package/build-module/dataform-controls/index.js.map +1 -1
  98. package/build-module/dataform-controls/telephone.js +27 -0
  99. package/build-module/dataform-controls/telephone.js.map +1 -0
  100. package/build-module/dataform-controls/text.js +6 -48
  101. package/build-module/dataform-controls/text.js.map +1 -1
  102. package/build-module/dataform-controls/{boolean.js → toggle.js} +5 -3
  103. package/build-module/dataform-controls/toggle.js.map +1 -0
  104. package/build-module/dataform-controls/url.js +27 -0
  105. package/build-module/dataform-controls/url.js.map +1 -0
  106. package/build-module/dataform-controls/utils/validated-text.js +70 -0
  107. package/build-module/dataform-controls/utils/validated-text.js.map +1 -0
  108. package/build-module/dataforms-layouts/card/index.js +6 -7
  109. package/build-module/dataforms-layouts/card/index.js.map +1 -1
  110. package/build-module/dataforms-layouts/data-form-layout.js +14 -4
  111. package/build-module/dataforms-layouts/data-form-layout.js.map +1 -1
  112. package/build-module/dataforms-layouts/index.js +32 -1
  113. package/build-module/dataforms-layouts/index.js.map +1 -1
  114. package/build-module/dataforms-layouts/row/index.js +106 -0
  115. package/build-module/dataforms-layouts/row/index.js.map +1 -0
  116. package/build-module/dataviews-layouts/grid/index.js +16 -11
  117. package/build-module/dataviews-layouts/grid/index.js.map +1 -1
  118. package/build-module/dataviews-layouts/index.js +10 -2
  119. package/build-module/dataviews-layouts/index.js.map +1 -1
  120. package/build-module/dataviews-layouts/picker-grid/index.js +348 -0
  121. package/build-module/dataviews-layouts/picker-grid/index.js.map +1 -0
  122. package/build-module/dataviews-layouts/utils/grid-items.js +29 -0
  123. package/build-module/dataviews-layouts/utils/grid-items.js.map +1 -0
  124. package/build-module/dataviews-layouts/utils/preview-size-picker.js +73 -0
  125. package/build-module/dataviews-layouts/utils/preview-size-picker.js.map +1 -0
  126. package/build-module/field-types/boolean.js +1 -1
  127. package/build-module/field-types/boolean.js.map +1 -1
  128. package/build-module/field-types/color.js +107 -0
  129. package/build-module/field-types/color.js.map +1 -0
  130. package/build-module/field-types/index.js +12 -0
  131. package/build-module/field-types/index.js.map +1 -1
  132. package/build-module/field-types/telephone.js +51 -0
  133. package/build-module/field-types/telephone.js.map +1 -0
  134. package/build-module/field-types/url.js +51 -0
  135. package/build-module/field-types/url.js.map +1 -0
  136. package/build-module/normalize-form-fields.js +6 -0
  137. package/build-module/normalize-form-fields.js.map +1 -1
  138. package/build-module/types.js.map +1 -1
  139. package/build-module/validation.js +1 -1
  140. package/build-module/validation.js.map +1 -1
  141. package/build-style/style-rtl.css +252 -12
  142. package/build-style/style.css +252 -12
  143. package/build-types/components/dataform/stories/index.story.d.ts +19 -4
  144. package/build-types/components/dataform/stories/index.story.d.ts.map +1 -1
  145. package/build-types/components/dataform-context/index.d.ts.map +1 -1
  146. package/build-types/components/dataviews/index.d.ts +1 -1
  147. package/build-types/components/dataviews/index.d.ts.map +1 -1
  148. package/build-types/components/dataviews/stories/index.story.d.ts.map +1 -1
  149. package/build-types/components/dataviews-context/index.d.ts +1 -0
  150. package/build-types/components/dataviews-context/index.d.ts.map +1 -1
  151. package/build-types/components/dataviews-layout/index.d.ts.map +1 -1
  152. package/build-types/components/dataviews-picker/footer.d.ts +4 -0
  153. package/build-types/components/dataviews-picker/footer.d.ts.map +1 -0
  154. package/build-types/components/dataviews-picker/index.d.ts +55 -0
  155. package/build-types/components/dataviews-picker/index.d.ts.map +1 -0
  156. package/build-types/components/dataviews-picker/stories/index.story.d.ts +42 -0
  157. package/build-types/components/dataviews-picker/stories/index.story.d.ts.map +1 -0
  158. package/build-types/components/dataviews-selection-checkbox/index.d.ts +2 -1
  159. package/build-types/components/dataviews-selection-checkbox/index.d.ts.map +1 -1
  160. package/build-types/components/dataviews-view-config/index.d.ts.map +1 -1
  161. package/build-types/constants.d.ts +1 -0
  162. package/build-types/constants.d.ts.map +1 -1
  163. package/build-types/dataform-controls/checkbox.d.ts.map +1 -1
  164. package/build-types/dataform-controls/color.d.ts +6 -0
  165. package/build-types/dataform-controls/color.d.ts.map +1 -0
  166. package/build-types/dataform-controls/email.d.ts.map +1 -1
  167. package/build-types/dataform-controls/index.d.ts.map +1 -1
  168. package/build-types/dataform-controls/telephone.d.ts +6 -0
  169. package/build-types/dataform-controls/telephone.d.ts.map +1 -0
  170. package/build-types/dataform-controls/text.d.ts.map +1 -1
  171. package/build-types/dataform-controls/toggle.d.ts +6 -0
  172. package/build-types/dataform-controls/toggle.d.ts.map +1 -0
  173. package/build-types/dataform-controls/url.d.ts +6 -0
  174. package/build-types/dataform-controls/url.d.ts.map +1 -0
  175. package/build-types/dataform-controls/utils/validated-text.d.ts +16 -0
  176. package/build-types/dataform-controls/utils/validated-text.d.ts.map +1 -0
  177. package/build-types/dataforms-layouts/card/index.d.ts +0 -3
  178. package/build-types/dataforms-layouts/card/index.d.ts.map +1 -1
  179. package/build-types/dataforms-layouts/data-form-layout.d.ts +4 -1
  180. package/build-types/dataforms-layouts/data-form-layout.d.ts.map +1 -1
  181. package/build-types/dataforms-layouts/index.d.ts +10 -0
  182. package/build-types/dataforms-layouts/index.d.ts.map +1 -1
  183. package/build-types/dataforms-layouts/row/index.d.ts +6 -0
  184. package/build-types/dataforms-layouts/row/index.d.ts.map +1 -0
  185. package/build-types/dataviews-layouts/grid/index.d.ts.map +1 -1
  186. package/build-types/dataviews-layouts/index.d.ts +12 -1
  187. package/build-types/dataviews-layouts/index.d.ts.map +1 -1
  188. package/build-types/dataviews-layouts/picker-grid/index.d.ts +4 -0
  189. package/build-types/dataviews-layouts/picker-grid/index.d.ts.map +1 -0
  190. package/build-types/dataviews-layouts/utils/grid-items.d.ts +5 -0
  191. package/build-types/dataviews-layouts/utils/grid-items.d.ts.map +1 -0
  192. package/build-types/dataviews-layouts/utils/preview-size-picker.d.ts +2 -0
  193. package/build-types/dataviews-layouts/utils/preview-size-picker.d.ts.map +1 -0
  194. package/build-types/field-types/color.d.ts +20 -0
  195. package/build-types/field-types/color.d.ts.map +1 -0
  196. package/build-types/field-types/index.d.ts.map +1 -1
  197. package/build-types/field-types/stories/index.story.d.ts +81 -0
  198. package/build-types/field-types/stories/index.story.d.ts.map +1 -0
  199. package/build-types/field-types/telephone.d.ts +20 -0
  200. package/build-types/field-types/telephone.d.ts.map +1 -0
  201. package/build-types/field-types/url.d.ts +20 -0
  202. package/build-types/field-types/url.d.ts.map +1 -0
  203. package/build-types/normalize-form-fields.d.ts.map +1 -1
  204. package/build-types/test/dataviews-picker.d.ts +2 -0
  205. package/build-types/test/dataviews-picker.d.ts.map +1 -0
  206. package/build-types/types.d.ts +36 -5
  207. package/build-types/types.d.ts.map +1 -1
  208. package/build-types/validation.d.ts.map +1 -1
  209. package/build-wp/index.js +5061 -4013
  210. package/package.json +16 -15
  211. package/src/components/dataform/stories/index.story.tsx +333 -11
  212. package/src/components/dataform-context/index.tsx +1 -0
  213. package/src/components/dataviews/index.tsx +25 -1
  214. package/src/components/dataviews/stories/fixtures.tsx +1 -1
  215. package/src/components/dataviews/stories/index.story.tsx +14 -0
  216. package/src/components/dataviews/style.scss +4 -2
  217. package/src/components/dataviews-context/index.ts +3 -0
  218. package/src/components/dataviews-layout/index.tsx +4 -2
  219. package/src/components/dataviews-picker/footer.tsx +207 -0
  220. package/src/components/dataviews-picker/index.tsx +284 -0
  221. package/src/components/dataviews-picker/stories/index.story.tsx +251 -0
  222. package/src/components/dataviews-picker/style.scss +10 -0
  223. package/src/components/dataviews-selection-checkbox/index.tsx +3 -0
  224. package/src/components/dataviews-view-config/index.tsx +1 -0
  225. package/src/constants.ts +3 -0
  226. package/src/dataform-controls/checkbox.tsx +33 -3
  227. package/src/dataform-controls/color.tsx +139 -0
  228. package/src/dataform-controls/email.tsx +10 -52
  229. package/src/dataform-controls/index.tsx +8 -2
  230. package/src/dataform-controls/telephone.tsx +30 -0
  231. package/src/dataform-controls/text.tsx +2 -57
  232. package/src/dataform-controls/{boolean.tsx → toggle.tsx} +3 -2
  233. package/src/dataform-controls/url.tsx +30 -0
  234. package/src/dataform-controls/utils/validated-text.tsx +96 -0
  235. package/src/dataforms-layouts/card/index.tsx +5 -4
  236. package/src/dataforms-layouts/card/style.scss +7 -0
  237. package/src/dataforms-layouts/data-form-layout.tsx +15 -3
  238. package/src/dataforms-layouts/index.tsx +35 -0
  239. package/src/dataforms-layouts/row/index.tsx +115 -0
  240. package/src/dataforms-layouts/row/style.scss +3 -0
  241. package/src/dataviews-layouts/grid/index.tsx +38 -33
  242. package/src/dataviews-layouts/grid/style.scss +42 -20
  243. package/src/dataviews-layouts/index.ts +16 -2
  244. package/src/dataviews-layouts/picker-grid/index.tsx +490 -0
  245. package/src/dataviews-layouts/picker-grid/style.scss +171 -0
  246. package/src/dataviews-layouts/utils/grid-items.scss +21 -0
  247. package/src/dataviews-layouts/utils/grid-items.tsx +35 -0
  248. package/src/dataviews-layouts/utils/preview-size-picker.tsx +87 -0
  249. package/src/field-types/boolean.tsx +1 -1
  250. package/src/field-types/color.tsx +115 -0
  251. package/src/field-types/index.tsx +15 -0
  252. package/src/field-types/stories/index.story.tsx +719 -0
  253. package/src/field-types/telephone.tsx +71 -0
  254. package/src/field-types/url.tsx +71 -0
  255. package/src/normalize-form-fields.ts +6 -0
  256. package/src/style.scss +4 -0
  257. package/src/test/dataform.tsx +2 -2
  258. package/src/test/dataviews-picker.tsx +478 -0
  259. package/src/test/dataviews.tsx +86 -0
  260. package/src/types.ts +56 -4
  261. package/src/validation.ts +3 -0
  262. package/tsconfig.tsbuildinfo +1 -1
  263. package/build/dataform-controls/boolean.js.map +0 -1
  264. package/build-module/dataform-controls/boolean.js.map +0 -1
  265. package/build-types/components/stories/index.story.d.ts +0 -63
  266. package/build-types/components/stories/index.story.d.ts.map +0 -1
  267. package/build-types/dataform-controls/boolean.d.ts +0 -6
  268. package/build-types/dataform-controls/boolean.d.ts.map +0 -1
  269. package/src/components/stories/index.story.tsx +0 -372
@@ -0,0 +1,251 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import type { Meta } from '@storybook/react';
5
+
6
+ /**
7
+ * WordPress dependencies
8
+ */
9
+ import { useState, useMemo, useCallback, useEffect } from '@wordpress/element';
10
+
11
+ /**
12
+ * Internal dependencies
13
+ */
14
+ import DataViewsPicker from '../index';
15
+ import {
16
+ data,
17
+ fields,
18
+ type SpaceObject,
19
+ } from '../../dataviews/stories/fixtures';
20
+ import { LAYOUT_PICKER_GRID } from '../../../constants';
21
+ import { filterSortAndPaginate } from '../../../filter-and-sort-data-view';
22
+ import type { ActionButton, View } from '../../../types';
23
+
24
+ const meta = {
25
+ title: 'DataViews/DataViewsPicker',
26
+ component: DataViewsPicker,
27
+ } as Meta< typeof DataViewsPicker >;
28
+
29
+ export default meta;
30
+
31
+ export const Default = ( {
32
+ perPageSizes = [ 10, 25, 50, 100 ],
33
+ isMultiselectable,
34
+ isGrouped,
35
+ infiniteScrollEnabled,
36
+ }: {
37
+ perPageSizes: number[];
38
+ isMultiselectable: boolean;
39
+ isGrouped: boolean;
40
+ infiniteScrollEnabled: boolean;
41
+ } ) => {
42
+ const [ view, setView ] = useState< View >( {
43
+ type: LAYOUT_PICKER_GRID,
44
+ fields: [],
45
+ titleField: 'title',
46
+ mediaField: 'image',
47
+ search: '',
48
+ page: 1,
49
+ perPage: 10,
50
+ filters: [],
51
+ groupByField: isGrouped ? 'type' : undefined,
52
+ infiniteScrollEnabled,
53
+ } );
54
+ const { data: shownData, paginationInfo: normalPaginationInfo } =
55
+ useMemo( () => {
56
+ return filterSortAndPaginate( data, view, fields );
57
+ }, [ view ] );
58
+
59
+ useEffect( () => {
60
+ setView( ( prevView ) => ( {
61
+ ...prevView,
62
+ groupByField:
63
+ isGrouped && ! infiniteScrollEnabled ? 'type' : undefined,
64
+ infiniteScrollEnabled,
65
+ } ) );
66
+ }, [ isGrouped, infiniteScrollEnabled ] );
67
+
68
+ const [ selection, setSelection ] = useState< string[] >( [] );
69
+
70
+ const actions: ActionButton< SpaceObject >[] = [
71
+ {
72
+ id: 'cancel',
73
+ label: 'Cancel',
74
+ supportsBulk: isMultiselectable,
75
+ callback() {
76
+ setSelection( [] );
77
+ },
78
+ },
79
+ {
80
+ id: 'confirm',
81
+ label: 'Confirm',
82
+ isPrimary: true,
83
+ supportsBulk: isMultiselectable,
84
+ callback() {
85
+ const selectedItemNames = data
86
+ .filter(
87
+ ( item ) => selection?.includes( String( item.id ) )
88
+ )
89
+ .map( ( item ) => item.title )
90
+ .join( ', ' );
91
+ // eslint-disable-next-line no-alert
92
+ window.alert( selectedItemNames );
93
+ },
94
+ },
95
+ ];
96
+
97
+ const {
98
+ data: infiniteScrollData,
99
+ paginationInfo: infiniteScrollPaginationInfo,
100
+ isLoadingMore,
101
+ } = useInfiniteScroll( {
102
+ view,
103
+ setView,
104
+ data: shownData,
105
+ getItemId: ( item ) => item.id.toString(),
106
+ } );
107
+
108
+ return (
109
+ <>
110
+ { infiniteScrollEnabled && (
111
+ <style>{ `
112
+ .dataviews-wrapper {
113
+ height: 600px;
114
+ overflow: auto;
115
+ }
116
+ ` }</style>
117
+ ) }
118
+ <DataViewsPicker
119
+ actions={ actions }
120
+ selection={ selection }
121
+ onChangeSelection={ ( selectedIds ) => {
122
+ setSelection( selectedIds );
123
+ } }
124
+ getItemId={ ( item ) => item.id.toString() }
125
+ paginationInfo={
126
+ infiniteScrollEnabled
127
+ ? infiniteScrollPaginationInfo
128
+ : normalPaginationInfo
129
+ }
130
+ data={ infiniteScrollEnabled ? infiniteScrollData : shownData }
131
+ isLoading={ infiniteScrollEnabled ? isLoadingMore : undefined }
132
+ view={ view }
133
+ fields={ fields }
134
+ onChangeView={ setView }
135
+ config={ { perPageSizes } }
136
+ itemListLabel="Galactic Bodies"
137
+ defaultLayouts={ {
138
+ [ LAYOUT_PICKER_GRID ]: {},
139
+ } }
140
+ />
141
+ </>
142
+ );
143
+ };
144
+
145
+ Default.args = {
146
+ perPageSizes: [ 10, 25, 50, 100 ],
147
+ isMultiselectable: false,
148
+ isGrouped: false,
149
+ };
150
+
151
+ Default.argTypes = {
152
+ isMultiselectable: {
153
+ control: 'boolean',
154
+ description: 'Whether multiselection is supported',
155
+ },
156
+ perPageSizes: {
157
+ control: 'object',
158
+ description: 'Array of available page sizes',
159
+ },
160
+ isGrouped: {
161
+ control: 'boolean',
162
+ description: 'Whether the items are grouped or ungrouped',
163
+ },
164
+ infiniteScrollEnabled: {
165
+ control: 'boolean',
166
+ description:
167
+ 'Whether the infinite scroll is enabled. Enabling this disables the "Is grouped" option',
168
+ },
169
+ };
170
+
171
+ function useInfiniteScroll( {
172
+ view,
173
+ setView,
174
+ data: shownData,
175
+ getItemId,
176
+ }: {
177
+ view: View;
178
+ setView: ( view: View ) => void;
179
+ data: SpaceObject[];
180
+ getItemId: ( item: SpaceObject ) => string;
181
+ } ): {
182
+ data: SpaceObject[];
183
+ paginationInfo: {
184
+ totalItems: number;
185
+ totalPages: number;
186
+ infiniteScrollHandler?: ( () => void ) | undefined;
187
+ };
188
+ isLoadingMore: boolean;
189
+ hasMoreData: boolean;
190
+ } {
191
+ // Custom pagination handler that simulates server-side pagination
192
+ const [ allLoadedRecords, setAllLoadedRecords ] = useState< SpaceObject[] >(
193
+ []
194
+ );
195
+ const [ isLoadingMore, setIsLoadingMore ] = useState( false );
196
+
197
+ const totalItems = data.length;
198
+ const totalPages = Math.ceil( totalItems / 6 ); // perPage is 6.
199
+ const currentPage = view.page || 1;
200
+ const hasMoreData = currentPage < totalPages;
201
+
202
+ const infiniteScrollHandler = useCallback( () => {
203
+ if ( isLoadingMore || currentPage >= totalPages ) {
204
+ return;
205
+ }
206
+
207
+ setIsLoadingMore( true );
208
+
209
+ setView( {
210
+ ...view,
211
+ page: currentPage + 1,
212
+ } );
213
+ }, [ isLoadingMore, currentPage, totalPages, view ] );
214
+
215
+ // Initialize data on first load or when view changes significantly
216
+ useEffect( () => {
217
+ if ( currentPage === 1 || ! view.infiniteScrollEnabled ) {
218
+ // First page - replace all data
219
+ setAllLoadedRecords( shownData );
220
+ } else {
221
+ // Subsequent pages - append to existing data
222
+ setAllLoadedRecords( ( prev ) => {
223
+ const existingIds = new Set( prev.map( getItemId ) );
224
+ const newRecords = shownData.filter(
225
+ ( record ) => ! existingIds.has( getItemId( record ) )
226
+ );
227
+ return [ ...prev, ...newRecords ];
228
+ } );
229
+ }
230
+ setIsLoadingMore( false );
231
+ }, [
232
+ view.search,
233
+ view.filters,
234
+ view.perPage,
235
+ currentPage,
236
+ view.infiniteScrollEnabled,
237
+ ] );
238
+
239
+ const paginationInfo = {
240
+ totalItems,
241
+ totalPages,
242
+ infiniteScrollHandler,
243
+ };
244
+
245
+ return {
246
+ data: allLoadedRecords,
247
+ paginationInfo,
248
+ isLoadingMore,
249
+ hasMoreData,
250
+ };
251
+ }
@@ -0,0 +1,10 @@
1
+ // For mobile viewports:
2
+ // - align bulk selection checkbox to the left.
3
+ // - align footer actions to the right.
4
+ .dataviews-picker-footer__bulk-selection {
5
+ align-self: flex-start;
6
+ height: $grid-unit-40;
7
+ }
8
+ .dataviews-picker-footer__actions {
9
+ align-self: flex-end;
10
+ }
@@ -17,6 +17,7 @@ interface DataViewsSelectionCheckboxProps< Item > {
17
17
  getItemId: ( item: Item ) => string;
18
18
  titleField?: NormalizedField< Item >;
19
19
  disabled: boolean;
20
+ tabIndex?: number;
20
21
  }
21
22
 
22
23
  export default function DataViewsSelectionCheckbox< Item >( {
@@ -26,6 +27,7 @@ export default function DataViewsSelectionCheckbox< Item >( {
26
27
  getItemId,
27
28
  titleField,
28
29
  disabled,
30
+ ...extraProps
29
31
  }: DataViewsSelectionCheckboxProps< Item > ) {
30
32
  const id = getItemId( item );
31
33
  const checked = ! disabled && selection.includes( id );
@@ -52,6 +54,7 @@ export default function DataViewsSelectionCheckbox< Item >( {
52
54
  : [ ...selection, id ]
53
55
  );
54
56
  } }
57
+ { ...extraProps }
55
58
  />
56
59
  );
57
60
  }
@@ -99,6 +99,7 @@ export function ViewTypeMenu() {
99
99
  case 'list':
100
100
  case 'grid':
101
101
  case 'table':
102
+ case 'pickerGrid':
102
103
  const viewWithoutLayout = { ...view };
103
104
  if ( 'layout' in viewWithoutLayout ) {
104
105
  delete viewWithoutLayout.layout;
package/src/constants.ts CHANGED
@@ -183,3 +183,6 @@ export const sortIcons = {
183
183
  export const LAYOUT_TABLE = 'table';
184
184
  export const LAYOUT_GRID = 'grid';
185
185
  export const LAYOUT_LIST = 'list';
186
+
187
+ // Picker view layouts.
188
+ export const LAYOUT_PICKER_GRID = 'pickerGrid';
@@ -1,12 +1,16 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
- import { CheckboxControl } from '@wordpress/components';
4
+ import { privateApis } from '@wordpress/components';
5
+ import { useState } from '@wordpress/element';
5
6
 
6
7
  /**
7
8
  * Internal dependencies
8
9
  */
9
10
  import type { DataFormControlProps } from '../types';
11
+ import { unlock } from '../lock-unlock';
12
+
13
+ const { ValidatedCheckboxControl } = unlock( privateApis );
10
14
 
11
15
  export default function Checkbox< Item >( {
12
16
  field,
@@ -15,10 +19,36 @@ export default function Checkbox< Item >( {
15
19
  hideLabelFromVision,
16
20
  }: DataFormControlProps< Item > ) {
17
21
  const { id, getValue, label, description } = field;
22
+ const [ customValidity, setCustomValidity ] =
23
+ useState<
24
+ React.ComponentProps<
25
+ typeof ValidatedCheckboxControl
26
+ >[ 'customValidity' ]
27
+ >( undefined );
18
28
 
19
29
  return (
20
- <CheckboxControl
21
- __nextHasNoMarginBottom
30
+ <ValidatedCheckboxControl
31
+ required={ !! field.isValid?.required }
32
+ onValidate={ ( newValue: any ) => {
33
+ const message = field.isValid?.custom?.(
34
+ {
35
+ ...data,
36
+ [ id ]: newValue,
37
+ },
38
+ field
39
+ );
40
+
41
+ if ( message ) {
42
+ setCustomValidity( {
43
+ type: 'invalid',
44
+ message,
45
+ } );
46
+ return;
47
+ }
48
+
49
+ setCustomValidity( undefined );
50
+ } }
51
+ customValidity={ customValidity }
22
52
  hidden={ hideLabelFromVision }
23
53
  label={ label }
24
54
  help={ description }
@@ -0,0 +1,139 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import { colord } from 'colord';
5
+
6
+ /**
7
+ * WordPress dependencies
8
+ */
9
+ import {
10
+ Dropdown,
11
+ privateApis,
12
+ __experimentalInputControlPrefixWrapper as InputControlPrefixWrapper,
13
+ } from '@wordpress/components';
14
+ import { useCallback, useState } from '@wordpress/element';
15
+
16
+ /**
17
+ * Internal dependencies
18
+ */
19
+ import type { DataFormControlProps } from '../types';
20
+ import { unlock } from '../lock-unlock';
21
+
22
+ const { ValidatedInputControl, Picker } = unlock( privateApis );
23
+
24
+ const ColorPicker = ( {
25
+ color,
26
+ onColorChange,
27
+ }: {
28
+ color: string;
29
+ onColorChange: ( colorObject: any ) => void;
30
+ } ) => {
31
+ const validColor = color && colord( color ).isValid() ? color : '#ffffff';
32
+
33
+ return (
34
+ <Dropdown
35
+ renderToggle={ ( { onToggle, isOpen } ) => (
36
+ <InputControlPrefixWrapper variant="icon">
37
+ <button
38
+ type="button"
39
+ onClick={ onToggle }
40
+ style={ {
41
+ width: '24px',
42
+ height: '24px',
43
+ borderRadius: '50%',
44
+ backgroundColor: validColor,
45
+ border: '1px solid #ddd',
46
+ cursor: 'pointer',
47
+ outline: isOpen ? '2px solid #007cba' : 'none',
48
+ outlineOffset: '2px',
49
+ display: 'flex',
50
+ alignItems: 'center',
51
+ justifyContent: 'center',
52
+ padding: 0,
53
+ margin: 0,
54
+ } }
55
+ aria-label="Open color picker"
56
+ />
57
+ </InputControlPrefixWrapper>
58
+ ) }
59
+ renderContent={ () => (
60
+ <div style={ { padding: '16px' } }>
61
+ <Picker
62
+ color={ colord( validColor ) }
63
+ onChange={ onColorChange }
64
+ enableAlpha
65
+ />
66
+ </div>
67
+ ) }
68
+ />
69
+ );
70
+ };
71
+
72
+ export default function Color< Item >( {
73
+ data,
74
+ field,
75
+ onChange,
76
+ hideLabelFromVision,
77
+ }: DataFormControlProps< Item > ) {
78
+ const { id, label, placeholder, description } = field;
79
+ const value = field.getValue( { item: data } ) || '';
80
+ const [ customValidity, setCustomValidity ] =
81
+ useState<
82
+ React.ComponentProps<
83
+ typeof ValidatedInputControl
84
+ >[ 'customValidity' ]
85
+ >( undefined );
86
+
87
+ const handleColorChange = useCallback(
88
+ ( colorObject: any ) => {
89
+ onChange( { [ id ]: colorObject.toHex() } );
90
+ },
91
+ [ id, onChange ]
92
+ );
93
+
94
+ const handleInputChange = useCallback(
95
+ ( newValue: string | undefined ) => {
96
+ onChange( { [ id ]: newValue || '' } );
97
+ },
98
+ [ id, onChange ]
99
+ );
100
+
101
+ return (
102
+ <ValidatedInputControl
103
+ required={ !! field.isValid?.required }
104
+ onValidate={ ( newValue: any ) => {
105
+ const message = field.isValid?.custom?.(
106
+ {
107
+ ...data,
108
+ [ id ]: newValue,
109
+ },
110
+ field
111
+ );
112
+
113
+ if ( message ) {
114
+ setCustomValidity( {
115
+ type: 'invalid',
116
+ message,
117
+ } );
118
+ return;
119
+ }
120
+
121
+ setCustomValidity( undefined );
122
+ } }
123
+ customValidity={ customValidity }
124
+ label={ label }
125
+ placeholder={ placeholder }
126
+ value={ value }
127
+ help={ description }
128
+ onChange={ handleInputChange }
129
+ hideLabelFromVision={ hideLabelFromVision }
130
+ type="text"
131
+ prefix={
132
+ <ColorPicker
133
+ color={ value }
134
+ onColorChange={ handleColorChange }
135
+ />
136
+ }
137
+ />
138
+ );
139
+ }
@@ -1,16 +1,13 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
- import { privateApis } from '@wordpress/components';
5
- import { useCallback, useState } from '@wordpress/element';
4
+ import { atSymbol } from '@wordpress/icons';
6
5
 
7
6
  /**
8
7
  * Internal dependencies
9
8
  */
10
9
  import type { DataFormControlProps } from '../types';
11
- import { unlock } from '../lock-unlock';
12
-
13
- const { ValidatedTextControl } = unlock( privateApis );
10
+ import ValidatedText from './utils/validated-text';
14
11
 
15
12
  export default function Email< Item >( {
16
13
  data,
@@ -18,55 +15,16 @@ export default function Email< Item >( {
18
15
  onChange,
19
16
  hideLabelFromVision,
20
17
  }: DataFormControlProps< Item > ) {
21
- const { id, label, placeholder, description } = field;
22
- const value = field.getValue( { item: data } );
23
- const [ customValidity, setCustomValidity ] =
24
- useState<
25
- React.ComponentProps<
26
- typeof ValidatedTextControl
27
- >[ 'customValidity' ]
28
- >( undefined );
29
-
30
- const onChangeControl = useCallback(
31
- ( newValue: string ) =>
32
- onChange( {
33
- [ id ]: newValue,
34
- } ),
35
- [ id, onChange ]
36
- );
37
-
38
18
  return (
39
- <ValidatedTextControl
40
- required={ !! field.isValid?.required }
41
- onValidate={ ( newValue: any ) => {
42
- const message = field.isValid?.custom?.(
43
- {
44
- ...data,
45
- [ id ]: newValue,
46
- },
47
- field
48
- );
49
-
50
- if ( message ) {
51
- setCustomValidity( {
52
- type: 'invalid',
53
- message,
54
- } );
55
- return;
56
- }
57
-
58
- setCustomValidity( undefined );
19
+ <ValidatedText
20
+ { ...{
21
+ data,
22
+ field,
23
+ onChange,
24
+ hideLabelFromVision,
25
+ type: 'email',
26
+ icon: atSymbol,
59
27
  } }
60
- customValidity={ customValidity }
61
- type="email"
62
- label={ label }
63
- placeholder={ placeholder }
64
- value={ value ?? '' }
65
- help={ description }
66
- onChange={ onChangeControl }
67
- __next40pxDefaultSize
68
- __nextHasNoMarginBottom
69
- hideLabelFromVision={ hideLabelFromVision }
70
28
  />
71
29
  );
72
30
  }
@@ -15,13 +15,16 @@ import checkbox from './checkbox';
15
15
  import datetime from './datetime';
16
16
  import date from './date';
17
17
  import email from './email';
18
+ import telephone from './telephone';
19
+ import url from './url';
18
20
  import integer from './integer';
19
21
  import radio from './radio';
20
22
  import select from './select';
21
23
  import text from './text';
24
+ import toggle from './toggle';
22
25
  import toggleGroup from './toggle-group';
23
- import boolean from './boolean';
24
26
  import array from './array';
27
+ import color from './color';
25
28
 
26
29
  interface FormControls {
27
30
  [ key: string ]: ComponentType< DataFormControlProps< any > >;
@@ -29,15 +32,18 @@ interface FormControls {
29
32
 
30
33
  const FORM_CONTROLS: FormControls = {
31
34
  array,
32
- boolean,
33
35
  checkbox,
36
+ color,
34
37
  datetime,
35
38
  date,
36
39
  email,
40
+ telephone,
41
+ url,
37
42
  integer,
38
43
  radio,
39
44
  select,
40
45
  text,
46
+ toggle,
41
47
  toggleGroup,
42
48
  };
43
49
 
@@ -0,0 +1,30 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { mobile } from '@wordpress/icons';
5
+
6
+ /**
7
+ * Internal dependencies
8
+ */
9
+ import type { DataFormControlProps } from '../types';
10
+ import ValidatedText from './utils/validated-text';
11
+
12
+ export default function Telephone< Item >( {
13
+ data,
14
+ field,
15
+ onChange,
16
+ hideLabelFromVision,
17
+ }: DataFormControlProps< Item > ) {
18
+ return (
19
+ <ValidatedText
20
+ { ...{
21
+ data,
22
+ field,
23
+ onChange,
24
+ hideLabelFromVision,
25
+ type: 'tel',
26
+ icon: mobile,
27
+ } }
28
+ />
29
+ );
30
+ }