@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
@@ -0,0 +1,201 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import {
5
+ __experimentalItemGroup as ItemGroup,
6
+ __experimentalItem as Item,
7
+ __experimentalVStack as VStack,
8
+ __experimentalHStack as HStack,
9
+ BaseControl,
10
+ Icon,
11
+ } from '@wordpress/components';
12
+ import { __ } from '@wordpress/i18n';
13
+ import { useContext } from '@wordpress/element';
14
+ import { check } from '@wordpress/icons';
15
+
16
+ /**
17
+ * Internal dependencies
18
+ */
19
+ import type { NormalizedField } from '../../types';
20
+ import DataViewsContext from '../dataviews-context';
21
+
22
+ function FieldItem( {
23
+ field,
24
+ isVisible,
25
+ onToggleVisibility,
26
+ }: {
27
+ field: NormalizedField< any >;
28
+ isVisible: boolean;
29
+ onToggleVisibility?: () => void;
30
+ } ) {
31
+ return (
32
+ <Item onClick={ field.enableHiding ? onToggleVisibility : undefined }>
33
+ <HStack expanded justify="flex-start" alignment="center">
34
+ <div style={ { height: 24, width: 24 } }>
35
+ { isVisible && <Icon icon={ check } /> }
36
+ </div>
37
+ <span className="dataviews-view-config__label">
38
+ { field.label }
39
+ </span>
40
+ </HStack>
41
+ </Item>
42
+ );
43
+ }
44
+
45
+ function isDefined< T >( item: T | undefined ): item is T {
46
+ return !! item;
47
+ }
48
+
49
+ export function PropertiesSection( {
50
+ showLabel = true,
51
+ }: {
52
+ showLabel?: boolean;
53
+ } ) {
54
+ const { view, fields, onChangeView } = useContext( DataViewsContext );
55
+
56
+ const togglableFields = [
57
+ view?.titleField,
58
+ view?.mediaField,
59
+ view?.descriptionField,
60
+ ].filter( Boolean );
61
+
62
+ // Get all regular fields (non-locked) in their original order from fields prop
63
+ const regularFields = fields.filter(
64
+ ( f ) =>
65
+ ! togglableFields.includes( f.id ) &&
66
+ f.type !== 'media' &&
67
+ f.enableHiding !== false
68
+ );
69
+
70
+ if ( ! regularFields?.length ) {
71
+ return null;
72
+ }
73
+ const titleField = fields.find( ( f ) => f.id === view.titleField );
74
+ const previewField = fields.find( ( f ) => f.id === view.mediaField );
75
+ const descriptionField = fields.find(
76
+ ( f ) => f.id === view.descriptionField
77
+ );
78
+
79
+ const lockedFields = [
80
+ {
81
+ field: titleField,
82
+ isVisibleFlag: 'showTitle',
83
+ },
84
+ {
85
+ field: previewField,
86
+ isVisibleFlag: 'showMedia',
87
+ },
88
+ {
89
+ field: descriptionField,
90
+ isVisibleFlag: 'showDescription',
91
+ },
92
+ ].filter( ( { field } ) => isDefined( field ) );
93
+ const visibleFieldIds = view.fields ?? [];
94
+ const visibleRegularFieldsCount = regularFields.filter( ( f ) =>
95
+ visibleFieldIds.includes( f.id )
96
+ ).length;
97
+
98
+ let visibleLockedFields = lockedFields.filter(
99
+ ( { field, isVisibleFlag } ) =>
100
+ // @ts-expect-error
101
+ isDefined( field ) && ( view[ isVisibleFlag ] ?? true )
102
+ ) as Array< {
103
+ field: NormalizedField< any >;
104
+ isVisibleFlag: string;
105
+ } >;
106
+
107
+ // If only one field (locked or regular) is visible, prevent it from being hidden
108
+ const totalVisibleFields =
109
+ visibleLockedFields.length + visibleRegularFieldsCount;
110
+ if ( totalVisibleFields === 1 ) {
111
+ if ( visibleLockedFields.length === 1 ) {
112
+ visibleLockedFields = visibleLockedFields.map( ( locked ) => ( {
113
+ ...locked,
114
+ field: { ...locked.field, enableHiding: false },
115
+ } ) );
116
+ }
117
+ }
118
+
119
+ const hiddenLockedFields = lockedFields.filter(
120
+ ( { field, isVisibleFlag } ) =>
121
+ // @ts-expect-error
122
+ isDefined( field ) && ! ( view[ isVisibleFlag ] ?? true )
123
+ ) as Array< {
124
+ field: NormalizedField< any >;
125
+ isVisibleFlag: string;
126
+ } >;
127
+
128
+ return (
129
+ <VStack className="dataviews-field-control" spacing={ 0 }>
130
+ { showLabel && (
131
+ <BaseControl.VisualLabel>
132
+ { __( 'Properties' ) }
133
+ </BaseControl.VisualLabel>
134
+ ) }
135
+ <VStack className="dataviews-view-config__properties" spacing={ 0 }>
136
+ <ItemGroup isBordered isSeparated size="medium">
137
+ { visibleLockedFields.map( ( { field, isVisibleFlag } ) => {
138
+ return (
139
+ <FieldItem
140
+ key={ field.id }
141
+ field={ field }
142
+ isVisible
143
+ onToggleVisibility={ () => {
144
+ onChangeView( {
145
+ ...view,
146
+ [ isVisibleFlag ]: false,
147
+ } );
148
+ } }
149
+ />
150
+ );
151
+ } ) }
152
+
153
+ { hiddenLockedFields.map( ( { field, isVisibleFlag } ) => {
154
+ return (
155
+ <FieldItem
156
+ key={ field.id }
157
+ field={ field }
158
+ isVisible={ false }
159
+ onToggleVisibility={ () => {
160
+ onChangeView( {
161
+ ...view,
162
+ [ isVisibleFlag ]: true,
163
+ } );
164
+ } }
165
+ />
166
+ );
167
+ } ) }
168
+
169
+ { regularFields.map( ( field ) => {
170
+ // Check if this is the last visible field to prevent hiding
171
+ const isVisible = visibleFieldIds.includes( field.id );
172
+ const isLastVisible =
173
+ totalVisibleFields === 1 && isVisible;
174
+ const fieldToRender = isLastVisible
175
+ ? { ...field, enableHiding: false }
176
+ : field;
177
+
178
+ return (
179
+ <FieldItem
180
+ key={ field.id }
181
+ field={ fieldToRender }
182
+ isVisible={ isVisible }
183
+ onToggleVisibility={ () => {
184
+ onChangeView( {
185
+ ...view,
186
+ fields: isVisible
187
+ ? visibleFieldIds.filter(
188
+ ( fieldId ) =>
189
+ fieldId !== field.id
190
+ )
191
+ : [ ...visibleFieldIds, field.id ],
192
+ } );
193
+ } }
194
+ />
195
+ );
196
+ } ) }
197
+ </ItemGroup>
198
+ </VStack>
199
+ </VStack>
200
+ );
201
+ }
@@ -58,44 +58,7 @@
58
58
  }
59
59
  }
60
60
  }
61
- .dataviews-field-control__field {
62
- height: $grid-unit-40;
63
- }
64
-
65
- .dataviews-field-control__actions {
66
- position: absolute;
67
- top: -9999em;
68
- }
69
- .dataviews-field-control__actions.dataviews-field-control__actions {
70
- gap: $grid-unit-05;
71
- }
72
-
73
- .dataviews-field-control__field:hover,
74
- .dataviews-field-control__field:focus-within,
75
- .dataviews-field-control__field.is-interacting {
76
- .dataviews-field-control__actions {
77
- position: unset;
78
- top: unset;
79
- }
80
- }
81
-
82
- .dataviews-field-control__icon {
83
- display: flex;
84
- width: $icon-size;
85
- }
86
-
87
- .dataviews-field-control__label-sub-label-container {
88
- flex-grow: 1;
89
- }
90
-
91
- .dataviews-field-control__label {
92
- display: block;
93
- }
94
61
 
95
- .dataviews-field-control__sub-label {
96
- margin-top: $grid-unit-10;
97
- margin-bottom: 0;
98
- font-size: 11px;
99
- font-style: normal;
100
- color: $gray-700;
62
+ .dataviews-view-config__label {
63
+ text-wrap: nowrap;
101
64
  }
package/src/constants.ts CHANGED
@@ -186,3 +186,4 @@ export const LAYOUT_LIST = 'list';
186
186
 
187
187
  // Picker view layouts.
188
188
  export const LAYOUT_PICKER_GRID = 'pickerGrid';
189
+ export const LAYOUT_PICKER_TABLE = 'pickerTable';
@@ -51,6 +51,7 @@ import type {
51
51
  NormalizedField,
52
52
  } from '../types';
53
53
  import getCustomValidity from './utils/get-custom-validity';
54
+ import { weekStartsOnToNumber } from '../utils/week-starts-on';
54
55
 
55
56
  const { DateCalendar, DateRangeCalendar } = unlock( componentsPrivateApis );
56
57
 
@@ -257,11 +258,24 @@ function CalendarDateControl< Item >( {
257
258
  hideLabelFromVision,
258
259
  validity,
259
260
  }: DataFormControlProps< Item > ) {
260
- const { id, label, setValue, getValue, isValid } = field;
261
+ const {
262
+ id,
263
+ type,
264
+ label,
265
+ setValue,
266
+ getValue,
267
+ isValid,
268
+ format: fieldFormat,
269
+ } = field;
261
270
  const [ selectedPresetId, setSelectedPresetId ] = useState< string | null >(
262
271
  null
263
272
  );
264
273
 
274
+ let weekStartsOn;
275
+ if ( type === 'date' ) {
276
+ weekStartsOn = weekStartsOnToNumber( fieldFormat.weekStartsOn );
277
+ }
278
+
265
279
  const fieldValue = getValue( { item: data } );
266
280
  const value = typeof fieldValue === 'string' ? fieldValue : undefined;
267
281
  const [ calendarMonth, setCalendarMonth ] = useState< Date >( () => {
@@ -320,7 +334,6 @@ function CalendarDateControl< Item >( {
320
334
 
321
335
  const {
322
336
  timezone: { string: timezoneString },
323
- l10n: { startOfWeek },
324
337
  } = getSettings();
325
338
 
326
339
  const displayLabel = isValid?.required
@@ -396,7 +409,7 @@ function CalendarDateControl< Item >( {
396
409
  month={ calendarMonth }
397
410
  onMonthChange={ setCalendarMonth }
398
411
  timeZone={ timezoneString || undefined }
399
- weekStartsOn={ startOfWeek }
412
+ weekStartsOn={ weekStartsOn }
400
413
  />
401
414
  </VStack>
402
415
  </BaseControl>
@@ -411,7 +424,7 @@ function CalendarDateRangeControl< Item >( {
411
424
  hideLabelFromVision,
412
425
  validity,
413
426
  }: DataFormControlProps< Item > ) {
414
- const { id, label, getValue, setValue } = field;
427
+ const { id, type, label, getValue, setValue, format: fieldFormat } = field;
415
428
  let value: DateRange;
416
429
  const fieldValue = getValue( { item: data } );
417
430
  if (
@@ -422,6 +435,11 @@ function CalendarDateRangeControl< Item >( {
422
435
  value = fieldValue as DateRange;
423
436
  }
424
437
 
438
+ let weekStartsOn;
439
+ if ( type === 'date' ) {
440
+ weekStartsOn = weekStartsOnToNumber( fieldFormat.weekStartsOn );
441
+ }
442
+
425
443
  const onChangeCallback = useCallback(
426
444
  ( newValue: DateRange ) => {
427
445
  onChange(
@@ -521,7 +539,7 @@ function CalendarDateRangeControl< Item >( {
521
539
  [ value, updateDateRange ]
522
540
  );
523
541
 
524
- const { timezone, l10n } = getSettings();
542
+ const { timezone } = getSettings();
525
543
 
526
544
  const displayLabel = field.isValid?.required
527
545
  ? `${ label } (${ __( 'Required' ) })`
@@ -609,7 +627,7 @@ function CalendarDateRangeControl< Item >( {
609
627
  month={ calendarMonth }
610
628
  onMonthChange={ setCalendarMonth }
611
629
  timeZone={ timezone.string || undefined }
612
- weekStartsOn={ l10n.startOfWeek }
630
+ weekStartsOn={ weekStartsOn }
613
631
  />
614
632
  </VStack>
615
633
  </BaseControl>
@@ -5,7 +5,7 @@ import {
5
5
  Icon,
6
6
  __experimentalInputControlPrefixWrapper as InputControlPrefixWrapper,
7
7
  } from '@wordpress/components';
8
- import { atSymbol } from '@wordpress/icons';
8
+ import { envelope } from '@wordpress/icons';
9
9
 
10
10
  /**
11
11
  * Internal dependencies
@@ -31,7 +31,7 @@ export default function Email< Item >( {
31
31
  type: 'email',
32
32
  prefix: (
33
33
  <InputControlPrefixWrapper variant="icon">
34
- <Icon icon={ atSymbol } />
34
+ <Icon icon={ envelope } />
35
35
  </InputControlPrefixWrapper>
36
36
  ),
37
37
  } }
@@ -0,0 +1,71 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { useContext, useMemo } from '@wordpress/element';
5
+ import { __ } from '@wordpress/i18n';
6
+
7
+ /**
8
+ * Internal dependencies
9
+ */
10
+ import type {
11
+ NormalizedForm,
12
+ NormalizedDetailsLayout,
13
+ FieldLayoutProps,
14
+ } from '../../types';
15
+ import DataFormContext from '../../components/dataform-context';
16
+ import { DataFormLayout } from '../data-form-layout';
17
+ import { DEFAULT_LAYOUT } from '../normalize-form';
18
+
19
+ export default function FormDetailsField< Item >( {
20
+ data,
21
+ field,
22
+ onChange,
23
+ }: FieldLayoutProps< Item > ) {
24
+ const { fields } = useContext( DataFormContext );
25
+
26
+ const form: NormalizedForm = useMemo(
27
+ () => ( {
28
+ layout: DEFAULT_LAYOUT,
29
+ fields: field.children ?? [],
30
+ } ),
31
+ [ field ]
32
+ );
33
+
34
+ if ( ! field.children ) {
35
+ return null;
36
+ }
37
+
38
+ // Find the summary field definition if specified
39
+ const summaryFieldId =
40
+ ( field.layout as NormalizedDetailsLayout ).summary ?? '';
41
+ const summaryField = summaryFieldId
42
+ ? fields.find( ( fieldDef ) => fieldDef.id === summaryFieldId )
43
+ : undefined;
44
+
45
+ // Render the summary content
46
+ let summaryContent;
47
+ if ( summaryField && summaryField.render ) {
48
+ // Use the field's render function to display the current value
49
+ summaryContent = (
50
+ <summaryField.render item={ data } field={ summaryField } />
51
+ );
52
+ } else {
53
+ // Fall back to the label
54
+ summaryContent = field.label || __( 'More details' );
55
+ }
56
+
57
+ return (
58
+ <details className="dataforms-layouts-details__details">
59
+ <summary className="dataforms-layouts-details__summary">
60
+ { summaryContent }
61
+ </summary>
62
+ <div className="dataforms-layouts-details__content">
63
+ <DataFormLayout
64
+ data={ data }
65
+ form={ form }
66
+ onChange={ onChange }
67
+ />
68
+ </div>
69
+ </details>
70
+ );
71
+ }
@@ -0,0 +1,5 @@
1
+ @use "@wordpress/base-styles/variables" as *;
2
+
3
+ .dataforms-layouts-details__content {
4
+ padding-top: $grid-unit-15;
5
+ }
@@ -14,6 +14,7 @@ import FormRegularField from './regular';
14
14
  import FormPanelField from './panel';
15
15
  import FormCardField from './card';
16
16
  import FormRowField from './row';
17
+ import FormDetailsField from './details';
17
18
 
18
19
  const FORM_FIELD_LAYOUTS = [
19
20
  {
@@ -67,6 +68,10 @@ const FORM_FIELD_LAYOUTS = [
67
68
  </VStack>
68
69
  ),
69
70
  },
71
+ {
72
+ type: 'details',
73
+ component: FormDetailsField,
74
+ },
70
75
  ];
71
76
 
72
77
  export function getFormFieldLayout( type: string ) {
@@ -11,6 +11,7 @@ import type {
11
11
  NormalizedPanelLayout,
12
12
  NormalizedCardLayout,
13
13
  NormalizedRowLayout,
14
+ NormalizedDetailsLayout,
14
15
  NormalizedCardSummaryField,
15
16
  CardSummaryField,
16
17
  } from '../types';
@@ -94,6 +95,11 @@ function normalizeLayout( layout?: Layout ): NormalizedLayout {
94
95
  alignment: layout?.alignment ?? 'center',
95
96
  styles: layout?.styles ?? {},
96
97
  } satisfies NormalizedRowLayout;
98
+ } else if ( layout?.type === 'details' ) {
99
+ normalizedLayout = {
100
+ type: 'details',
101
+ summary: layout?.summary ?? '',
102
+ } satisfies NormalizedDetailsLayout;
97
103
  }
98
104
 
99
105
  return normalizedLayout;
@@ -16,11 +16,13 @@ import ViewTable from './table';
16
16
  import ViewGrid from './grid';
17
17
  import ViewList from './list';
18
18
  import ViewPickerGrid from './picker-grid';
19
+ import ViewPickerTable from './picker-table';
19
20
  import {
20
21
  LAYOUT_GRID,
21
22
  LAYOUT_LIST,
22
23
  LAYOUT_TABLE,
23
24
  LAYOUT_PICKER_GRID,
25
+ LAYOUT_PICKER_TABLE,
24
26
  } from '../constants';
25
27
  import PreviewSizePicker from './utils/preview-size-picker';
26
28
  import DensityPicker from './table/density-picker';
@@ -54,4 +56,12 @@ export const VIEW_LAYOUTS = [
54
56
  viewConfigOptions: PreviewSizePicker,
55
57
  isPicker: true,
56
58
  },
59
+ {
60
+ type: LAYOUT_PICKER_TABLE,
61
+ label: __( 'Table' ),
62
+ component: ViewPickerTable,
63
+ icon: blockTable,
64
+ viewConfigOptions: DensityPicker,
65
+ isPicker: true,
66
+ },
57
67
  ];
@@ -24,6 +24,7 @@ div.dataviews-view-list {
24
24
  width: max-content;
25
25
  flex: 0 0 auto;
26
26
  gap: $grid-unit-05;
27
+ white-space: nowrap;
27
28
 
28
29
  .components-button {
29
30
  position: relative;