@wordpress/dataviews 10.3.1-next.2f1c7c01b.0 → 10.4.1-next.dc3f6d3c1.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 (149) hide show
  1. package/CHANGELOG.md +23 -5
  2. package/README.md +413 -148
  3. package/build/components/dataviews-filters/filter.js +11 -1
  4. package/build/components/dataviews-filters/filter.js.map +2 -2
  5. package/build/components/dataviews-view-config/index.js +11 -396
  6. package/build/components/dataviews-view-config/index.js.map +3 -3
  7. package/build/components/dataviews-view-config/properties-section.js +177 -0
  8. package/build/components/dataviews-view-config/properties-section.js.map +7 -0
  9. package/build/constants.js +3 -0
  10. package/build/constants.js.map +2 -2
  11. package/build/dataform-controls/date.js +23 -7
  12. package/build/dataform-controls/date.js.map +2 -2
  13. package/build/dataform-controls/email.js +1 -1
  14. package/build/dataform-controls/email.js.map +1 -1
  15. package/build/dataform-layouts/details/index.js +78 -0
  16. package/build/dataform-layouts/details/index.js.map +7 -0
  17. package/build/dataform-layouts/index.js +5 -0
  18. package/build/dataform-layouts/index.js.map +3 -3
  19. package/build/dataform-layouts/normalize-form.js +5 -0
  20. package/build/dataform-layouts/normalize-form.js.map +2 -2
  21. package/build/dataviews-layouts/index.js +9 -0
  22. package/build/dataviews-layouts/index.js.map +3 -3
  23. package/build/dataviews-layouts/picker-table/index.js +422 -0
  24. package/build/dataviews-layouts/picker-table/index.js.map +7 -0
  25. package/build/dataviews-layouts/table/column-header-menu.js.map +2 -2
  26. package/build/dataviews-layouts/table/column-primary.js +1 -6
  27. package/build/dataviews-layouts/table/column-primary.js.map +2 -2
  28. package/build/dataviews-layouts/table/index.js +47 -2
  29. package/build/dataviews-layouts/table/index.js.map +2 -2
  30. package/build/field-types/date.js +4 -2
  31. package/build/field-types/date.js.map +2 -2
  32. package/build/types/dataform.js.map +1 -1
  33. package/build/types/dataviews.js.map +1 -1
  34. package/build/types/field-api.js.map +1 -1
  35. package/build/utils/normalize-fields.js +23 -3
  36. package/build/utils/normalize-fields.js.map +2 -2
  37. package/build/utils/week-starts-on.js +59 -0
  38. package/build/utils/week-starts-on.js.map +7 -0
  39. package/build-module/components/dataviews-filters/filter.js +11 -1
  40. package/build-module/components/dataviews-filters/filter.js.map +2 -2
  41. package/build-module/components/dataviews-view-config/index.js +15 -412
  42. package/build-module/components/dataviews-view-config/index.js.map +2 -2
  43. package/build-module/components/dataviews-view-config/properties-section.js +149 -0
  44. package/build-module/components/dataviews-view-config/properties-section.js.map +7 -0
  45. package/build-module/constants.js +2 -0
  46. package/build-module/constants.js.map +2 -2
  47. package/build-module/dataform-controls/date.js +23 -7
  48. package/build-module/dataform-controls/date.js.map +2 -2
  49. package/build-module/dataform-controls/email.js +2 -2
  50. package/build-module/dataform-controls/email.js.map +1 -1
  51. package/build-module/dataform-layouts/details/index.js +47 -0
  52. package/build-module/dataform-layouts/details/index.js.map +7 -0
  53. package/build-module/dataform-layouts/index.js +5 -0
  54. package/build-module/dataform-layouts/index.js.map +2 -2
  55. package/build-module/dataform-layouts/normalize-form.js +5 -0
  56. package/build-module/dataform-layouts/normalize-form.js.map +2 -2
  57. package/build-module/dataviews-layouts/index.js +11 -1
  58. package/build-module/dataviews-layouts/index.js.map +2 -2
  59. package/build-module/dataviews-layouts/picker-table/index.js +397 -0
  60. package/build-module/dataviews-layouts/picker-table/index.js.map +7 -0
  61. package/build-module/dataviews-layouts/table/column-header-menu.js.map +2 -2
  62. package/build-module/dataviews-layouts/table/column-primary.js +1 -6
  63. package/build-module/dataviews-layouts/table/column-primary.js.map +2 -2
  64. package/build-module/dataviews-layouts/table/index.js +48 -3
  65. package/build-module/dataviews-layouts/table/index.js.map +2 -2
  66. package/build-module/field-types/date.js +5 -3
  67. package/build-module/field-types/date.js.map +2 -2
  68. package/build-module/utils/normalize-fields.js +23 -3
  69. package/build-module/utils/normalize-fields.js.map +2 -2
  70. package/build-module/utils/week-starts-on.js +32 -0
  71. package/build-module/utils/week-starts-on.js.map +7 -0
  72. package/build-style/style-rtl.css +58 -54
  73. package/build-style/style.css +58 -54
  74. package/build-types/components/dataviews-filters/filter.d.ts.map +1 -1
  75. package/build-types/components/dataviews-filters/utils.d.ts.map +1 -1
  76. package/build-types/components/dataviews-view-config/index.d.ts.map +1 -1
  77. package/build-types/components/dataviews-view-config/properties-section.d.ts +4 -0
  78. package/build-types/components/dataviews-view-config/properties-section.d.ts.map +1 -0
  79. package/build-types/constants.d.ts +1 -0
  80. package/build-types/constants.d.ts.map +1 -1
  81. package/build-types/dataform-controls/date.d.ts.map +1 -1
  82. package/build-types/dataform-layouts/details/index.d.ts +6 -0
  83. package/build-types/dataform-layouts/details/index.d.ts.map +1 -0
  84. package/build-types/dataform-layouts/get-summary-fields.d.ts.map +1 -1
  85. package/build-types/dataform-layouts/index.d.ts +5 -0
  86. package/build-types/dataform-layouts/index.d.ts.map +1 -1
  87. package/build-types/dataform-layouts/normalize-form.d.ts.map +1 -1
  88. package/build-types/dataviews-layouts/index.d.ts +8 -0
  89. package/build-types/dataviews-layouts/index.d.ts.map +1 -1
  90. package/build-types/dataviews-layouts/picker-table/index.d.ts +4 -0
  91. package/build-types/dataviews-layouts/picker-table/index.d.ts.map +1 -0
  92. package/build-types/dataviews-layouts/table/column-header-menu.d.ts +3 -3
  93. package/build-types/dataviews-layouts/table/column-header-menu.d.ts.map +1 -1
  94. package/build-types/dataviews-layouts/table/column-primary.d.ts.map +1 -1
  95. package/build-types/dataviews-layouts/table/index.d.ts.map +1 -1
  96. package/build-types/field-types/date.d.ts.map +1 -1
  97. package/build-types/stories/dataform.story.d.ts +3 -0
  98. package/build-types/stories/dataform.story.d.ts.map +1 -1
  99. package/build-types/stories/dataviews-picker.story.d.ts +2 -0
  100. package/build-types/stories/dataviews-picker.story.d.ts.map +1 -1
  101. package/build-types/stories/dataviews.story.d.ts +7 -1
  102. package/build-types/stories/dataviews.story.d.ts.map +1 -1
  103. package/build-types/stories/field-types.story.d.ts +27 -1
  104. package/build-types/stories/field-types.story.d.ts.map +1 -1
  105. package/build-types/types/dataform.d.ts +11 -3
  106. package/build-types/types/dataform.d.ts.map +1 -1
  107. package/build-types/types/dataviews.d.ts +23 -2
  108. package/build-types/types/dataviews.d.ts.map +1 -1
  109. package/build-types/types/field-api.d.ts +28 -1
  110. package/build-types/types/field-api.d.ts.map +1 -1
  111. package/build-types/utils/normalize-fields.d.ts.map +1 -1
  112. package/build-types/utils/week-starts-on.d.ts +20 -0
  113. package/build-types/utils/week-starts-on.d.ts.map +1 -0
  114. package/build-wp/index.js +1497 -1188
  115. package/package.json +15 -15
  116. package/src/components/dataviews/style.scss +2 -0
  117. package/src/components/dataviews-filters/filter.tsx +11 -1
  118. package/src/components/dataviews-footer/style.scss +1 -1
  119. package/src/components/dataviews-view-config/index.tsx +8 -504
  120. package/src/components/dataviews-view-config/properties-section.tsx +201 -0
  121. package/src/components/dataviews-view-config/style.scss +2 -39
  122. package/src/constants.ts +1 -0
  123. package/src/dataform-controls/date.tsx +24 -6
  124. package/src/dataform-controls/email.tsx +2 -2
  125. package/src/dataform-layouts/details/index.tsx +71 -0
  126. package/src/dataform-layouts/details/style.scss +5 -0
  127. package/src/dataform-layouts/index.tsx +5 -0
  128. package/src/dataform-layouts/normalize-form.ts +6 -0
  129. package/src/dataviews-layouts/index.ts +10 -0
  130. package/src/dataviews-layouts/list/style.scss +1 -0
  131. package/src/dataviews-layouts/picker-table/index.tsx +487 -0
  132. package/src/dataviews-layouts/picker-table/style.scss +47 -0
  133. package/src/dataviews-layouts/table/column-header-menu.tsx +3 -2
  134. package/src/dataviews-layouts/table/column-primary.tsx +4 -7
  135. package/src/dataviews-layouts/table/index.tsx +55 -2
  136. package/src/dataviews-layouts/table/style.scss +36 -19
  137. package/src/field-types/date.tsx +11 -5
  138. package/src/stories/dataform.story.tsx +84 -0
  139. package/src/stories/dataviews-picker.story.tsx +11 -6
  140. package/src/stories/dataviews.story.tsx +10 -2
  141. package/src/stories/field-types.story.tsx +67 -2
  142. package/src/style.scss +2 -0
  143. package/src/test/normalize-fields.ts +53 -0
  144. package/src/types/dataform.ts +18 -3
  145. package/src/types/dataviews.ts +36 -2
  146. package/src/types/field-api.ts +42 -1
  147. package/src/utils/normalize-fields.ts +51 -2
  148. package/src/utils/week-starts-on.ts +46 -0
  149. package/tsconfig.tsbuildinfo +1 -1
@@ -11,6 +11,7 @@
11
11
  position: relative;
12
12
  color: $gray-700;
13
13
  margin-bottom: auto;
14
+ background-color: inherit;
14
15
 
15
16
  th {
16
17
  text-align: left;
@@ -29,7 +30,7 @@
29
30
  &.dataviews-view-table__actions-column--sticky {
30
31
  position: sticky;
31
32
  right: 0;
32
- background-color: $white;
33
+ background-color: inherit;
33
34
  }
34
35
 
35
36
  &.dataviews-view-table__actions-column--stuck {
@@ -47,7 +48,6 @@
47
48
 
48
49
  &.dataviews-view-table__checkbox-column {
49
50
  padding-right: 0;
50
- width: 1%;
51
51
 
52
52
  .dataviews-view-table__cell-content-wrapper {
53
53
  max-width: auto;
@@ -57,6 +57,7 @@
57
57
  }
58
58
  tr {
59
59
  border-top: 1px solid $gray-100;
60
+ background-color: inherit;
60
61
 
61
62
  .dataviews-view-table-header-button {
62
63
  gap: $grid-unit-05;
@@ -80,11 +81,6 @@
80
81
  border-bottom: 0;
81
82
  }
82
83
 
83
- &.is-hovered,
84
- &.is-hovered .dataviews-view-table__actions-column--sticky {
85
- background-color: #f8f8f8;
86
- }
87
-
88
84
  .components-checkbox-control__input.components-checkbox-control__input {
89
85
  opacity: 0;
90
86
 
@@ -99,15 +95,6 @@
99
95
  opacity: 0;
100
96
  }
101
97
 
102
- &:focus-within,
103
- &.is-hovered,
104
- &:hover {
105
- .components-checkbox-control__input,
106
- .dataviews-item-actions .components-button:not(.dataviews-all-actions-button) {
107
- opacity: 1;
108
- }
109
- }
110
-
111
98
  @media (hover: none) {
112
99
  // Show checkboxes and quick-actions on devices that do not support hover.
113
100
  .components-checkbox-control__input.components-checkbox-control__input,
@@ -117,7 +104,7 @@
117
104
  }
118
105
 
119
106
  &.is-selected {
120
- background-color: rgba(var(--wp-admin-theme-color--rgb), 0.04);
107
+ background-color: color-mix(in srgb, rgb(var(--wp-admin-theme-color--rgb)) 4%, $white);
121
108
  color: $gray-700;
122
109
 
123
110
  &,
@@ -126,7 +113,7 @@
126
113
  }
127
114
 
128
115
  &:hover {
129
- background-color: rgba(var(--wp-admin-theme-color--rgb), 0.08);
116
+ background-color: color-mix(in srgb, rgb(var(--wp-admin-theme-color--rgb)) 8%, $white);
130
117
  }
131
118
 
132
119
  .dataviews-view-table__actions-column--sticky {
@@ -138,10 +125,34 @@
138
125
  }
139
126
  }
140
127
  }
128
+
129
+ // Hover styles only apply when bulk actions are available
130
+ &.has-bulk-actions {
131
+ tr {
132
+ // Only apply hover background to non-selected rows
133
+ &:not(.is-selected) {
134
+ &.is-hovered,
135
+ &.is-hovered .dataviews-view-table__actions-column--sticky {
136
+ background-color: #f8f8f8;
137
+ }
138
+ }
139
+
140
+ &:focus-within,
141
+ &.is-hovered,
142
+ &:hover {
143
+ .components-checkbox-control__input,
144
+ .dataviews-item-actions .components-button:not(.dataviews-all-actions-button) {
145
+ opacity: 1;
146
+ }
147
+ }
148
+ }
149
+ }
150
+
141
151
  thead {
142
152
  position: sticky;
143
153
  inset-block-start: 0;
144
154
  z-index: z-index(".dataviews-view-table thead");
155
+ background-color: inherit;
145
156
 
146
157
  tr {
147
158
  border: 0;
@@ -151,7 +162,7 @@
151
162
  }
152
163
  }
153
164
  th {
154
- background-color: $white;
165
+ background-color: inherit;
155
166
  padding-top: $grid-unit-10;
156
167
  padding-bottom: $grid-unit-10;
157
168
  padding-left: $grid-unit-15;
@@ -172,6 +183,7 @@
172
183
  min-height: $grid-unit-40;
173
184
  display: flex;
174
185
  align-items: center;
186
+ white-space: nowrap;
175
187
 
176
188
  &.dataviews-view-table__cell-align-end {
177
189
  justify-content: flex-end;
@@ -313,3 +325,8 @@
313
325
  color: $gray-900;
314
326
  }
315
327
  }
328
+
329
+ /* Column width intents via colgroup: make non-primary columns shrink-to-fit */
330
+ .dataviews-view-table col[class^="dataviews-view-table__col-"]:not(.dataviews-view-table__col-primary) {
331
+ width: 1%;
332
+ }
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
- import { dateI18n, getDate, getSettings } from '@wordpress/date';
4
+ import { dateI18n, getDate } from '@wordpress/date';
5
5
 
6
6
  /**
7
7
  * Internal dependencies
@@ -24,9 +24,6 @@ import {
24
24
  OPERATOR_BETWEEN,
25
25
  } from '../constants';
26
26
 
27
- const getFormattedDate = ( dateToDisplay: string | null ) =>
28
- dateI18n( getSettings().formats.date, getDate( dateToDisplay ) );
29
-
30
27
  function sort( a: any, b: any, direction: SortDirection ) {
31
28
  const timeA = new Date( a ).getTime();
32
29
  const timeB = new Date( b ).getTime();
@@ -51,7 +48,16 @@ export default {
51
48
  return '';
52
49
  }
53
50
 
54
- return getFormattedDate( value );
51
+ // Not all fields have format, but date fields do.
52
+ //
53
+ // At runtime, this method will never be called for non-date fields.
54
+ // However, the type system does not know this, so we need to check it.
55
+ // There's an opportunity here to improve the type system.
56
+ if ( field.type !== 'date' ) {
57
+ return '';
58
+ }
59
+
60
+ return dateI18n( field.format.date, getDate( value ) );
55
61
  },
56
62
  enableSorting: true,
57
63
  filterBy: {
@@ -268,6 +268,19 @@ const fields: Field< SamplePost >[] = [
268
268
  label: 'Seat',
269
269
  type: 'text',
270
270
  },
271
+ {
272
+ id: 'metadata_summary',
273
+ label: 'Metadata',
274
+ type: 'text',
275
+ render: ( { item } ) => {
276
+ return (
277
+ <span>
278
+ <>Metadata</>
279
+ { item.filesize ? `, ${ item.filesize } KB` : '' }
280
+ </span>
281
+ );
282
+ },
283
+ },
271
284
  ];
272
285
 
273
286
  const LayoutRegularComponent = ( {
@@ -1850,6 +1863,73 @@ const LayoutRowComponent = ( {
1850
1863
  );
1851
1864
  };
1852
1865
 
1866
+ const LayoutDetailsComponent = () => {
1867
+ const [ post, setPost ] = useState< SamplePost >( {
1868
+ title: 'Hello, World!',
1869
+ order: 2,
1870
+ author: 1,
1871
+ status: 'draft',
1872
+ reviewer: 'fulano',
1873
+ date: '2021-01-01T12:00:00',
1874
+ birthdate: '1950-02-23T12:00:00',
1875
+ filesize: 1024,
1876
+ dimensions: '1920x1080',
1877
+ comment_status: 'open',
1878
+ ping_status: true,
1879
+ tags: [ 'photography' ],
1880
+ } );
1881
+
1882
+ const form: Form = {
1883
+ fields: [
1884
+ {
1885
+ id: 'discussion',
1886
+ label: 'Discussion',
1887
+ children: [ 'comment_status', 'ping_status' ],
1888
+ layout: {
1889
+ type: 'details',
1890
+ summary: 'discussion',
1891
+ },
1892
+ },
1893
+ {
1894
+ id: 'metadata',
1895
+ label: 'Metadata',
1896
+ children: [ 'filesize', 'dimensions' ],
1897
+ layout: {
1898
+ type: 'details',
1899
+ summary: 'metadata_summary',
1900
+ },
1901
+ },
1902
+ {
1903
+ id: 'categorization',
1904
+ label: 'Categorization',
1905
+ children: [ 'tags', 'description' ],
1906
+ layout: { type: 'details' },
1907
+ },
1908
+ {
1909
+ id: 'scheduling',
1910
+ children: [ 'date', 'birthdate' ],
1911
+ layout: {
1912
+ type: 'details',
1913
+ },
1914
+ },
1915
+ ],
1916
+ };
1917
+
1918
+ return (
1919
+ <DataForm< SamplePost >
1920
+ data={ post }
1921
+ fields={ fields }
1922
+ form={ form }
1923
+ onChange={ ( edits ) =>
1924
+ setPost( ( prev ) => ( {
1925
+ ...prev,
1926
+ ...edits,
1927
+ } ) )
1928
+ }
1929
+ />
1930
+ );
1931
+ };
1932
+
1853
1933
  const LayoutMixedComponent = () => {
1854
1934
  const [ post, setPost ] = useState< SamplePost >( {
1855
1935
  title: 'Hello, World!',
@@ -1977,6 +2057,10 @@ export const LayoutRow = {
1977
2057
  },
1978
2058
  };
1979
2059
 
2060
+ export const LayoutDetails = {
2061
+ render: LayoutDetailsComponent,
2062
+ };
2063
+
1980
2064
  export const LayoutMixed = {
1981
2065
  render: LayoutMixedComponent,
1982
2066
  };
@@ -17,7 +17,7 @@ import {
17
17
  * Internal dependencies
18
18
  */
19
19
  import DataViewsPicker from '../components/dataviews-picker/index';
20
- import { LAYOUT_PICKER_GRID } from '../constants';
20
+ import { LAYOUT_PICKER_GRID, LAYOUT_PICKER_TABLE } from '../constants';
21
21
  import filterSortAndPaginate from '../utils/filter-sort-and-paginate';
22
22
  import type { ActionButton, View } from '../types';
23
23
  import { data, fields, type SpaceObject } from './dataviews.fixtures';
@@ -33,6 +33,7 @@ const storyArgs = {
33
33
  perPageSizes: [ 10, 25, 50, 100 ],
34
34
  isMultiselectable: false,
35
35
  isGrouped: false,
36
+ infiniteScrollEnabled: false,
36
37
  };
37
38
 
38
39
  const storyArgTypes = {
@@ -73,7 +74,6 @@ const DataViewsPickerContent = ( {
73
74
  selection: customSelection,
74
75
  }: PickerContentProps ) => {
75
76
  const [ view, setView ] = useState< View >( {
76
- type: LAYOUT_PICKER_GRID,
77
77
  fields: [],
78
78
  titleField: 'title',
79
79
  mediaField: 'image',
@@ -81,6 +81,7 @@ const DataViewsPickerContent = ( {
81
81
  page: 1,
82
82
  perPage: 10,
83
83
  filters: [],
84
+ type: LAYOUT_PICKER_GRID,
84
85
  groupByField: isGrouped ? 'type' : undefined,
85
86
  infiniteScrollEnabled,
86
87
  } );
@@ -138,13 +139,14 @@ const DataViewsPickerContent = ( {
138
139
  setView,
139
140
  data: shownData,
140
141
  getItemId: ( item ) => item.id.toString(),
142
+ totalDataLength: data.length,
141
143
  } );
142
144
 
143
145
  return (
144
146
  <>
145
147
  { infiniteScrollEnabled && (
146
148
  <style>{ `
147
- .dataviews-wrapper {
149
+ .dataviews-picker-wrapper {
148
150
  height: 600px;
149
151
  overflow: auto;
150
152
  }
@@ -171,6 +173,7 @@ const DataViewsPickerContent = ( {
171
173
  itemListLabel="Galactic Bodies"
172
174
  defaultLayouts={ {
173
175
  [ LAYOUT_PICKER_GRID ]: {},
176
+ [ LAYOUT_PICKER_TABLE ]: { perPage: 20 },
174
177
  } }
175
178
  />
176
179
  </>
@@ -292,11 +295,13 @@ function useInfiniteScroll( {
292
295
  setView,
293
296
  data: shownData,
294
297
  getItemId,
298
+ totalDataLength,
295
299
  }: {
296
300
  view: View;
297
301
  setView: ( view: View ) => void;
298
302
  data: SpaceObject[];
299
303
  getItemId: ( item: SpaceObject ) => string;
304
+ totalDataLength: number;
300
305
  } ): {
301
306
  data: SpaceObject[];
302
307
  paginationInfo: {
@@ -313,8 +318,8 @@ function useInfiniteScroll( {
313
318
  );
314
319
  const [ isLoadingMore, setIsLoadingMore ] = useState( false );
315
320
 
316
- const totalItems = data.length;
317
- const totalPages = Math.ceil( totalItems / 6 ); // perPage is 6.
321
+ const totalItems = totalDataLength;
322
+ const totalPages = Math.ceil( totalItems / ( view.perPage || 10 ) );
318
323
  const currentPage = view.page || 1;
319
324
  const hasMoreData = currentPage < totalPages;
320
325
 
@@ -329,7 +334,7 @@ function useInfiniteScroll( {
329
334
  ...view,
330
335
  page: currentPage + 1,
331
336
  } );
332
- }, [ isLoadingMore, currentPage, totalPages, view ] );
337
+ }, [ isLoadingMore, currentPage, totalPages, view, setView ] );
333
338
 
334
339
  // Initialize data on first load or when view changes significantly
335
340
  useEffect( () => {
@@ -70,7 +70,10 @@ const defaultLayouts = {
70
70
  [ LAYOUT_LIST ]: {},
71
71
  };
72
72
 
73
- export const Default = ( { perPageSizes = [ 10, 25, 50, 100 ] } ) => {
73
+ export const Default = ( {
74
+ perPageSizes = [ 10, 25, 50, 100 ],
75
+ hasClickableItems = true,
76
+ } ) => {
74
77
  const [ view, setView ] = useState< View >( {
75
78
  ...DEFAULT_VIEW,
76
79
  fields: [ 'categories' ],
@@ -100,7 +103,7 @@ export const Default = ( { perPageSizes = [ 10, 25, 50, 100 ] } ) => {
100
103
  { ...props }
101
104
  />
102
105
  ) }
103
- isItemClickable={ () => true }
106
+ isItemClickable={ () => hasClickableItems }
104
107
  defaultLayouts={ defaultLayouts }
105
108
  config={ { perPageSizes } }
106
109
  />
@@ -109,6 +112,7 @@ export const Default = ( { perPageSizes = [ 10, 25, 50, 100 ] } ) => {
109
112
 
110
113
  Default.args = {
111
114
  perPageSizes: [ 10, 25, 50, 100 ],
115
+ hasClickableItems: true,
112
116
  };
113
117
 
114
118
  Default.argTypes = {
@@ -116,6 +120,10 @@ Default.argTypes = {
116
120
  control: 'object',
117
121
  description: 'Array of available page sizes',
118
122
  },
123
+ hasClickableItems: {
124
+ control: 'boolean',
125
+ description: 'Are the items clickable',
126
+ },
119
127
  };
120
128
 
121
129
  export const Empty = () => {
@@ -832,14 +832,53 @@ export const DateComponent = ( {
832
832
  type,
833
833
  Edit,
834
834
  asyncElements,
835
+ formatDate,
836
+ formatWeekStartsOn,
835
837
  }: {
836
838
  type: PanelTypes;
837
839
  Edit: ControlTypes;
838
840
  asyncElements: boolean;
841
+ formatDate?: string;
842
+ formatWeekStartsOn?:
843
+ | 'sunday'
844
+ | 'monday'
845
+ | 'tuesday'
846
+ | 'wednesday'
847
+ | 'thursday'
848
+ | 'friday'
849
+ | 'saturday';
839
850
  } ) => {
840
851
  const dateFields = useMemo(
841
- () => fields.filter( ( field ) => field.type === 'date' ),
842
- []
852
+ () =>
853
+ fields
854
+ .filter( ( field ) => field.type === 'date' )
855
+ .map( ( field ) => {
856
+ if ( formatDate || formatWeekStartsOn !== undefined ) {
857
+ const format: {
858
+ date?: string;
859
+ weekStartsOn?:
860
+ | 'sunday'
861
+ | 'monday'
862
+ | 'tuesday'
863
+ | 'wednesday'
864
+ | 'thursday'
865
+ | 'friday'
866
+ | 'saturday';
867
+ } = {};
868
+ if ( formatDate ) {
869
+ format.date = formatDate;
870
+ }
871
+ if ( formatWeekStartsOn !== undefined ) {
872
+ format.weekStartsOn = formatWeekStartsOn;
873
+ }
874
+ return {
875
+ ...field,
876
+ format,
877
+ };
878
+ }
879
+ return field;
880
+ } ),
881
+ [ formatDate, formatWeekStartsOn ]
843
882
  );
844
883
 
845
884
  return (
@@ -852,6 +891,32 @@ export const DateComponent = ( {
852
891
  );
853
892
  };
854
893
  DateComponent.storyName = 'date';
894
+ DateComponent.args = {
895
+ formatDate: '',
896
+ formatWeekStartsOn: undefined,
897
+ };
898
+ DateComponent.argTypes = {
899
+ formatDate: {
900
+ control: 'text',
901
+ description:
902
+ 'Custom PHP date format string (e.g., "F j, Y" for "November 6, 2010"). Leave empty to use WordPress default.',
903
+ },
904
+ formatWeekStartsOn: {
905
+ control: 'select',
906
+ options: {
907
+ Default: undefined,
908
+ Sunday: 'sunday',
909
+ Monday: 'monday',
910
+ Tuesday: 'tuesday',
911
+ Wednesday: 'wednesday',
912
+ Thursday: 'thursday',
913
+ Friday: 'friday',
914
+ Saturday: 'saturday',
915
+ },
916
+ description:
917
+ 'Day that the week starts on. Leave as Default to use WordPress default.',
918
+ },
919
+ };
855
920
 
856
921
  export const EmailComponent = ( {
857
922
  type,
package/src/style.scss CHANGED
@@ -12,10 +12,12 @@
12
12
  @use "./dataviews-layouts/list/style.scss" as *;
13
13
  @use "./dataviews-layouts/table/style.scss" as *;
14
14
  @use "./dataviews-layouts/picker-grid/style.scss" as *;
15
+ @use "./dataviews-layouts/picker-table/style.scss" as *;
15
16
 
16
17
  @use "./dataform-controls/style.scss" as *;
17
18
  @use "./dataform-layouts/panel/style.scss" as *;
18
19
  @use "./dataform-layouts/regular/style.scss" as *;
19
20
  @use "./dataform-layouts/card/style.scss" as *;
21
+ @use "./dataform-layouts/details/style.scss" as *;
20
22
  @use "./dataform-layouts/row/style.scss" as *;
21
23
  @use "./dataform-layouts/style.scss" as *;
@@ -333,4 +333,57 @@ describe( 'normalizeFields: default getValue', () => {
333
333
  } );
334
334
  } );
335
335
  } );
336
+
337
+ describe( 'format normalization', () => {
338
+ it( 'applies default format when not provided for date fields', () => {
339
+ const fields: Field< {} >[] = [
340
+ {
341
+ id: 'publishDate',
342
+ type: 'date',
343
+ },
344
+ ];
345
+ const normalizedFields = normalizeFields( fields );
346
+ expect( normalizedFields[ 0 ].format ).toBeDefined();
347
+ expect( normalizedFields[ 0 ].format.date ).toBeDefined();
348
+ expect( typeof normalizedFields[ 0 ].format.date ).toBe( 'string' );
349
+ expect( normalizedFields[ 0 ].format.weekStartsOn ).toBeDefined();
350
+ expect( typeof normalizedFields[ 0 ].format.weekStartsOn ).toBe(
351
+ 'string'
352
+ );
353
+ } );
354
+
355
+ it( 'preserves custom format when provided', () => {
356
+ const fields: Field< {} >[] = [
357
+ {
358
+ id: 'publishDate',
359
+ type: 'date',
360
+ format: {
361
+ date: 'F j, Y',
362
+ weekStartsOn: 'monday',
363
+ },
364
+ },
365
+ ];
366
+ const normalizedFields = normalizeFields( fields );
367
+ expect( normalizedFields[ 0 ].format.date ).toBe( 'F j, Y' );
368
+ expect( normalizedFields[ 0 ].format.weekStartsOn ).toBe(
369
+ 'monday'
370
+ );
371
+ } );
372
+
373
+ it( 'adds empty format for non-date field types', () => {
374
+ const fields: Field< {} >[] = [
375
+ {
376
+ id: 'title',
377
+ type: 'text',
378
+ },
379
+ {
380
+ id: 'count',
381
+ type: 'integer',
382
+ },
383
+ ];
384
+ const normalizedFields = normalizeFields( fields );
385
+ expect( normalizedFields[ 0 ].format ).toEqual( {} );
386
+ expect( normalizedFields[ 1 ].format ).toEqual( {} );
387
+ } );
388
+ } );
336
389
  } );
@@ -6,7 +6,7 @@ import type { Field, FieldValidity } from './field-api';
6
6
  /**
7
7
  * DataForm layouts.
8
8
  */
9
- export type LayoutType = 'regular' | 'panel' | 'card' | 'row';
9
+ export type LayoutType = 'regular' | 'panel' | 'card' | 'row' | 'details';
10
10
  export type LabelPosition = 'top' | 'side' | 'none';
11
11
 
12
12
  export type PanelSummaryField = string | string[];
@@ -97,12 +97,27 @@ export type NormalizedRowLayout = {
97
97
  styles: Record< string, { flex?: React.CSSProperties[ 'flex' ] } >;
98
98
  };
99
99
 
100
- export type Layout = RegularLayout | PanelLayout | CardLayout | RowLayout;
100
+ export type DetailsLayout = {
101
+ type: 'details';
102
+ summary?: string;
103
+ };
104
+ export type NormalizedDetailsLayout = {
105
+ type: 'details';
106
+ summary: string;
107
+ };
108
+
109
+ export type Layout =
110
+ | RegularLayout
111
+ | PanelLayout
112
+ | CardLayout
113
+ | RowLayout
114
+ | DetailsLayout;
101
115
  export type NormalizedLayout =
102
116
  | NormalizedRegularLayout
103
117
  | NormalizedPanelLayout
104
118
  | NormalizedCardLayout
105
- | NormalizedRowLayout;
119
+ | NormalizedRowLayout
120
+ | NormalizedDetailsLayout;
106
121
 
107
122
  export type NormalizedSummaryField =
108
123
  | NormalizedPanelSummaryField
@@ -269,7 +269,33 @@ export interface ViewPickerGrid extends ViewBase {
269
269
  };
270
270
  }
271
271
 
272
- export type View = ViewList | ViewGrid | ViewTable | ViewPickerGrid;
272
+ export interface ViewPickerTable extends ViewBase {
273
+ type: 'pickerTable';
274
+
275
+ layout?: {
276
+ /**
277
+ * The styles for the columns.
278
+ */
279
+ styles?: Record< string, ColumnStyle >;
280
+
281
+ /**
282
+ * The density of the view.
283
+ */
284
+ density?: Density;
285
+
286
+ /**
287
+ * Whether the view allows column moving.
288
+ */
289
+ enableMoving?: boolean;
290
+ };
291
+ }
292
+
293
+ export type View =
294
+ | ViewList
295
+ | ViewGrid
296
+ | ViewTable
297
+ | ViewPickerGrid
298
+ | ViewPickerTable;
273
299
 
274
300
  interface ActionBase< Item > {
275
301
  /**
@@ -428,16 +454,24 @@ export interface ViewPickerGridProps< Item >
428
454
  view: ViewPickerGrid;
429
455
  }
430
456
 
457
+ export interface ViewPickerTableProps< Item >
458
+ extends Omit< ViewPickerBaseProps< Item >, 'view' > {
459
+ view: ViewPickerTable;
460
+ }
461
+
431
462
  export type ViewProps< Item > =
432
463
  | ViewTableProps< Item >
433
464
  | ViewGridProps< Item >
434
465
  | ViewListProps< Item >;
435
466
 
436
- export type ViewPickerProps< Item > = ViewPickerGridProps< Item >;
467
+ export type ViewPickerProps< Item > =
468
+ | ViewPickerGridProps< Item >
469
+ | ViewPickerTableProps< Item >;
437
470
 
438
471
  export interface SupportedLayouts {
439
472
  list?: Omit< ViewList, 'type' >;
440
473
  grid?: Omit< ViewGrid, 'type' >;
441
474
  table?: Omit< ViewTable, 'type' >;
442
475
  pickerGrid?: Omit< ViewPickerGrid, 'type' >;
476
+ pickerTable?: Omit< ViewPickerTable, 'type' >;
443
477
  }