@wordpress/dataviews 10.1.1 → 10.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 (45) hide show
  1. package/CHANGELOG.md +5 -1
  2. package/README.md +1 -0
  3. package/build/components/dataviews-bulk-actions/index.js +19 -2
  4. package/build/components/dataviews-bulk-actions/index.js.map +2 -2
  5. package/build/dataform-controls/password.js +3 -4
  6. package/build/dataform-controls/password.js.map +3 -3
  7. package/build/dataform-layouts/card/index.js +28 -10
  8. package/build/dataform-layouts/card/index.js.map +3 -3
  9. package/build/dataform-layouts/normalize-form-fields.js +4 -2
  10. package/build/dataform-layouts/normalize-form-fields.js.map +2 -2
  11. package/build/types/dataform.js.map +1 -1
  12. package/build-module/components/dataviews-bulk-actions/index.js +19 -2
  13. package/build-module/components/dataviews-bulk-actions/index.js.map +2 -2
  14. package/build-module/dataform-controls/password.js +7 -5
  15. package/build-module/dataform-controls/password.js.map +2 -2
  16. package/build-module/dataform-layouts/card/index.js +34 -11
  17. package/build-module/dataform-layouts/card/index.js.map +2 -2
  18. package/build-module/dataform-layouts/normalize-form-fields.js +4 -2
  19. package/build-module/dataform-layouts/normalize-form-fields.js.map +2 -2
  20. package/build-style/style-rtl.css +12 -12
  21. package/build-style/style.css +12 -12
  22. package/build-types/components/dataviews-bulk-actions/index.d.ts.map +1 -1
  23. package/build-types/dataform-controls/password.d.ts.map +1 -1
  24. package/build-types/dataform-layouts/card/index.d.ts +3 -3
  25. package/build-types/dataform-layouts/card/index.d.ts.map +1 -1
  26. package/build-types/dataform-layouts/normalize-form-fields.d.ts.map +1 -1
  27. package/build-types/stories/dataform.story.d.ts +9 -1
  28. package/build-types/stories/dataform.story.d.ts.map +1 -1
  29. package/build-types/types/dataform.d.ts +4 -0
  30. package/build-types/types/dataform.d.ts.map +1 -1
  31. package/build-wp/index.js +140 -101
  32. package/package.json +15 -15
  33. package/src/components/dataviews/style.scss +1 -1
  34. package/src/components/dataviews-bulk-actions/index.tsx +20 -1
  35. package/src/components/dataviews-bulk-actions/style.scss +1 -1
  36. package/src/components/dataviews-filters/style.scss +1 -1
  37. package/src/components/dataviews-pagination/style.scss +2 -2
  38. package/src/dataform-controls/password.tsx +16 -12
  39. package/src/dataform-layouts/card/index.tsx +45 -13
  40. package/src/dataform-layouts/normalize-form-fields.ts +5 -0
  41. package/src/dataviews-layouts/table/style.scss +2 -2
  42. package/src/stories/dataform.story.tsx +19 -3
  43. package/src/test/normalize-form-fields.ts +7 -0
  44. package/src/types/dataform.ts +6 -0
  45. package/tsconfig.tsbuildinfo +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wordpress/dataviews",
3
- "version": "10.1.1",
3
+ "version": "10.2.0",
4
4
  "description": "DataViews is a component that provides an API to render datasets using different types of layouts (table, grid, list, etc.).",
5
5
  "author": "The WordPress Contributors",
6
6
  "license": "GPL-2.0-or-later",
@@ -44,19 +44,19 @@
44
44
  "sideEffects": false,
45
45
  "dependencies": {
46
46
  "@ariakit/react": "^0.4.15",
47
- "@wordpress/base-styles": "^6.9.1",
48
- "@wordpress/components": "^30.6.1",
49
- "@wordpress/compose": "^7.33.1",
50
- "@wordpress/data": "^10.33.1",
51
- "@wordpress/date": "^5.33.1",
52
- "@wordpress/element": "^6.33.1",
53
- "@wordpress/i18n": "^6.6.1",
54
- "@wordpress/icons": "^11.0.1",
55
- "@wordpress/keycodes": "^4.33.1",
56
- "@wordpress/primitives": "^4.33.1",
57
- "@wordpress/private-apis": "^1.33.1",
58
- "@wordpress/url": "^4.33.1",
59
- "@wordpress/warning": "^3.33.1",
47
+ "@wordpress/base-styles": "^6.10.0",
48
+ "@wordpress/components": "^30.7.0",
49
+ "@wordpress/compose": "^7.34.0",
50
+ "@wordpress/data": "^10.34.0",
51
+ "@wordpress/date": "^5.34.0",
52
+ "@wordpress/element": "^6.34.0",
53
+ "@wordpress/i18n": "^6.7.0",
54
+ "@wordpress/icons": "^11.1.0",
55
+ "@wordpress/keycodes": "^4.34.0",
56
+ "@wordpress/primitives": "^4.34.0",
57
+ "@wordpress/private-apis": "^1.34.0",
58
+ "@wordpress/url": "^4.34.0",
59
+ "@wordpress/warning": "^3.34.0",
60
60
  "clsx": "^2.1.1",
61
61
  "colord": "^2.7.0",
62
62
  "date-fns": "^4.1.0",
@@ -74,5 +74,5 @@
74
74
  "scripts": {
75
75
  "build:wp": "node build"
76
76
  },
77
- "gitHead": "5f84bafdec1bed05247c1080c12f6a237951b862"
77
+ "gitHead": "ceebff807958d2e8fc755b5a20473939c78b4d1d"
78
78
  }
@@ -61,7 +61,7 @@
61
61
 
62
62
  .dataviews-title-field {
63
63
  font-size: $default-font-size;
64
- font-weight: 500;
64
+ font-weight: $font-weight-medium;
65
65
  color: $gray-800;
66
66
  text-overflow: ellipsis;
67
67
  white-space: nowrap;
@@ -15,6 +15,7 @@ import { __, sprintf, _n } from '@wordpress/i18n';
15
15
  import { useMemo, useState, useRef, useContext } from '@wordpress/element';
16
16
  import { useRegistry } from '@wordpress/data';
17
17
  import { closeSmall } from '@wordpress/icons';
18
+ import { useViewportMatch } from '@wordpress/compose';
18
19
 
19
20
  /**
20
21
  * Internal dependencies
@@ -165,6 +166,22 @@ function ActionTrigger< Item >( {
165
166
  }: ActionTriggerProps< Item > ) {
166
167
  const label =
167
168
  typeof action.label === 'string' ? action.label : action.label( items );
169
+ const isMobile = useViewportMatch( 'medium', '<' );
170
+
171
+ if ( isMobile ) {
172
+ return (
173
+ <Button
174
+ disabled={ isBusy }
175
+ accessibleWhenDisabled
176
+ label={ label }
177
+ icon={ action.icon }
178
+ size="compact"
179
+ onClick={ onClick }
180
+ isBusy={ isBusy }
181
+ />
182
+ );
183
+ }
184
+
168
185
  return (
169
186
  <Button
170
187
  disabled={ isBusy }
@@ -308,6 +325,7 @@ function FooterContent< Item >( {
308
325
  null
309
326
  );
310
327
  const footerContentRef = useRef< JSX.Element | null >( null );
328
+ const isMobile = useViewportMatch( 'medium', '<' );
311
329
 
312
330
  const bulkActions = useMemo(
313
331
  () => actions.filter( ( action ) => action.supportsBulk ),
@@ -334,13 +352,14 @@ function FooterContent< Item >( {
334
352
  actions.filter( ( action ) => {
335
353
  return (
336
354
  action.supportsBulk &&
355
+ ( ! isMobile || action.icon ) &&
337
356
  selectedItems.some(
338
357
  ( item ) =>
339
358
  ! action.isEligible || action.isEligible( item )
340
359
  )
341
360
  );
342
361
  } ),
343
- [ actions, selectedItems ]
362
+ [ actions, selectedItems, isMobile ]
344
363
  );
345
364
  if ( ! actionInProgress ) {
346
365
  if ( footerContentRef.current ) {
@@ -4,7 +4,7 @@
4
4
 
5
5
  .dataviews-bulk-actions-footer__item-count {
6
6
  color: $gray-900;
7
- font-weight: 500;
7
+ font-weight: $font-weight-medium;
8
8
  font-size: 11px;
9
9
  text-transform: uppercase;
10
10
  }
@@ -119,7 +119,7 @@
119
119
  }
120
120
 
121
121
  .dataviews-filters-__summary-filter-text-name {
122
- font-weight: 500;
122
+ font-weight: $font-weight-medium;
123
123
  }
124
124
  }
125
125
 
@@ -3,13 +3,13 @@
3
3
 
4
4
  .dataviews-pagination__page-select {
5
5
  font-size: 11px;
6
- font-weight: 500;
6
+ font-weight: $font-weight-medium;
7
7
  text-transform: uppercase;
8
8
 
9
9
  @include break-small() {
10
10
  .components-select-control__input {
11
11
  font-size: 11px !important;
12
- font-weight: 500;
12
+ font-weight: $font-weight-medium;
13
13
  }
14
14
  }
15
15
  }
@@ -1,7 +1,10 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
- import { Button } from '@wordpress/components';
4
+ import {
5
+ __experimentalInputControlSuffixWrapper as InputControlSuffixWrapper,
6
+ Button,
7
+ } from '@wordpress/components';
5
8
  import { useCallback, useState } from '@wordpress/element';
6
9
  import { __ } from '@wordpress/i18n';
7
10
  import { seen, unseen } from '@wordpress/icons';
@@ -34,17 +37,18 @@ export default function Password< Item >( {
34
37
  validity,
35
38
  type: isVisible ? 'text' : 'password',
36
39
  suffix: (
37
- <Button
38
- icon={ isVisible ? unseen : seen }
39
- onClick={ toggleVisibility }
40
- size="small"
41
- variant="tertiary"
42
- aria-label={
43
- isVisible
44
- ? __( 'Hide password' )
45
- : __( 'Show password' )
46
- }
47
- />
40
+ <InputControlSuffixWrapper variant="control">
41
+ <Button
42
+ icon={ isVisible ? unseen : seen }
43
+ onClick={ toggleVisibility }
44
+ size="small"
45
+ label={
46
+ isVisible
47
+ ? __( 'Hide password' )
48
+ : __( 'Show password' )
49
+ }
50
+ />
51
+ </InputControlSuffixWrapper>
48
52
  ),
49
53
  } }
50
54
  />
@@ -1,7 +1,12 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
- import { Button, Card, CardBody, CardHeader } from '@wordpress/components';
4
+ import {
5
+ Button,
6
+ Card,
7
+ CardBody,
8
+ CardHeader as OriginalCardHeader,
9
+ } from '@wordpress/components';
5
10
  import { useCallback, useContext, useMemo, useState } from '@wordpress/element';
6
11
  import { chevronDown, chevronUp } from '@wordpress/icons';
7
12
 
@@ -23,8 +28,30 @@ import { isCombinedField } from '../is-combined-field';
23
28
  import { DEFAULT_LAYOUT, normalizeLayout } from '../normalize-form-fields';
24
29
  import { getSummaryFields } from '../get-summary-fields';
25
30
 
26
- export function useCollapsibleCard( initialIsOpen: boolean = true ) {
27
- const [ isOpen, setIsOpen ] = useState( initialIsOpen );
31
+ const NonCollapsibleCardHeader = ( {
32
+ children,
33
+ ...props
34
+ }: {
35
+ children: React.ReactNode;
36
+ } ) => (
37
+ <OriginalCardHeader { ...props }>
38
+ <div
39
+ style={ {
40
+ height: '40px', // This is to match the chevron's __next40pxDefaultSize
41
+ width: '100%',
42
+ display: 'flex',
43
+ justifyContent: 'space-between',
44
+ alignItems: 'center',
45
+ } }
46
+ >
47
+ { children }
48
+ </div>
49
+ </OriginalCardHeader>
50
+ );
51
+
52
+ export function useCardHeader( layout: NormalizedCardLayout ) {
53
+ const { isOpened, isCollapsible } = layout;
54
+ const [ isOpen, setIsOpen ] = useState( isOpened );
28
55
 
29
56
  const toggle = useCallback( () => {
30
57
  setIsOpen( ( prev ) => ! prev );
@@ -38,7 +65,7 @@ export function useCollapsibleCard( initialIsOpen: boolean = true ) {
38
65
  children: React.ReactNode;
39
66
  [ key: string ]: any;
40
67
  } ) => (
41
- <CardHeader
68
+ <OriginalCardHeader
42
69
  { ...props }
43
70
  onClick={ toggle }
44
71
  style={ {
@@ -63,12 +90,17 @@ export function useCollapsibleCard( initialIsOpen: boolean = true ) {
63
90
  aria-expanded={ isOpen }
64
91
  aria-label={ isOpen ? 'Collapse' : 'Expand' }
65
92
  />
66
- </CardHeader>
93
+ </OriginalCardHeader>
67
94
  ),
68
95
  [ toggle, isOpen ]
69
96
  );
70
97
 
71
- return { isOpen, CollapsibleCardHeader };
98
+ const effectiveIsOpen = isCollapsible ? isOpen : true;
99
+ const CardHeaderComponent = isCollapsible
100
+ ? CollapsibleCardHeader
101
+ : NonCollapsibleCardHeader;
102
+
103
+ return { isOpen: effectiveIsOpen, CardHeader: CardHeaderComponent };
72
104
  }
73
105
 
74
106
  function isSummaryFieldVisible< Item >(
@@ -144,9 +176,7 @@ export default function FormCardField< Item >( {
144
176
  [ field ]
145
177
  );
146
178
 
147
- const { isOpen, CollapsibleCardHeader } = useCollapsibleCard(
148
- layout.isOpened
149
- );
179
+ const { isOpen, CardHeader } = useCardHeader( layout );
150
180
 
151
181
  const summaryFields = getSummaryFields< Item >( layout.summary, fields );
152
182
 
@@ -156,10 +186,11 @@ export default function FormCardField< Item >( {
156
186
 
157
187
  if ( isCombinedField( field ) ) {
158
188
  const withHeader = !! field.label && layout.withHeader;
189
+
159
190
  return (
160
191
  <Card className="dataforms-layouts-card__field">
161
192
  { withHeader && (
162
- <CollapsibleCardHeader className="dataforms-layouts-card__field-header">
193
+ <CardHeader className="dataforms-layouts-card__field-header">
163
194
  <span className="dataforms-layouts-card__field-header-label">
164
195
  { field.label }
165
196
  </span>
@@ -177,7 +208,7 @@ export default function FormCardField< Item >( {
177
208
  ) }
178
209
  </div>
179
210
  ) }
180
- </CollapsibleCardHeader>
211
+ </CardHeader>
181
212
  ) }
182
213
  { ( isOpen || ! withHeader ) && (
183
214
  // If it doesn't have a header, keep it open.
@@ -213,10 +244,11 @@ export default function FormCardField< Item >( {
213
244
  return null;
214
245
  }
215
246
  const withHeader = !! fieldDefinition.label && layout.withHeader;
247
+
216
248
  return (
217
249
  <Card className="dataforms-layouts-card__field">
218
250
  { withHeader && (
219
- <CollapsibleCardHeader className="dataforms-layouts-card__field-header">
251
+ <CardHeader className="dataforms-layouts-card__field-header">
220
252
  <span className="dataforms-layouts-card__field-header-label">
221
253
  { fieldDefinition.label }
222
254
  </span>
@@ -231,7 +263,7 @@ export default function FormCardField< Item >( {
231
263
  ) ) }
232
264
  </div>
233
265
  ) }
234
- </CollapsibleCardHeader>
266
+ </CardHeader>
235
267
  ) }
236
268
  { ( isOpen || ! withHeader ) && (
237
269
  // If it doesn't have a header, keep it open.
@@ -72,6 +72,7 @@ export function normalizeLayout( layout?: Layout ): NormalizedLayout {
72
72
  withHeader: false,
73
73
  isOpened: true,
74
74
  summary: [],
75
+ isCollapsible: false,
75
76
  } satisfies NormalizedCardLayout;
76
77
  } else {
77
78
  const summary = layout.summary ?? [];
@@ -84,6 +85,10 @@ export function normalizeLayout( layout?: Layout ): NormalizedLayout {
84
85
  ? layout.isOpened
85
86
  : true,
86
87
  summary: normalizeCardSummaryField( summary ),
88
+ isCollapsible:
89
+ layout.isCollapsible === undefined
90
+ ? true
91
+ : layout.isCollapsible,
87
92
  } satisfies NormalizedCardLayout;
88
93
  }
89
94
  } else if ( layout?.type === 'row' ) {
@@ -157,7 +157,7 @@
157
157
  padding-left: $grid-unit-15;
158
158
  font-size: 11px;
159
159
  text-transform: uppercase;
160
- font-weight: 500;
160
+ font-weight: $font-weight-medium;
161
161
 
162
162
  &:has(.dataviews-view-table-header-button):not(:first-child) {
163
163
  padding-left: $grid-unit-05;
@@ -190,7 +190,7 @@
190
190
  padding: $grid-unit-05 $grid-unit-10;
191
191
  font-size: 11px;
192
192
  text-transform: uppercase;
193
- font-weight: 500;
193
+ font-weight: $font-weight-medium;
194
194
 
195
195
  &:not(:hover) {
196
196
  color: $gray-900;
@@ -1252,7 +1252,13 @@ const VisibilityComponent = () => {
1252
1252
  );
1253
1253
  };
1254
1254
 
1255
- const LayoutCardComponent = ( { withHeader }: { withHeader: boolean } ) => {
1255
+ const LayoutCardComponent = ( {
1256
+ withHeader,
1257
+ isCollapsible,
1258
+ }: {
1259
+ withHeader: boolean;
1260
+ isCollapsible: boolean;
1261
+ } ) => {
1256
1262
  type Customer = {
1257
1263
  name: string;
1258
1264
  email: string;
@@ -1383,7 +1389,11 @@ const LayoutCardComponent = ( { withHeader }: { withHeader: boolean } ) => {
1383
1389
  fields: [
1384
1390
  {
1385
1391
  id: 'customerCard',
1386
- layout: { type: 'card', summary: 'plan-summary' },
1392
+ layout: {
1393
+ type: 'card',
1394
+ summary: 'plan-summary',
1395
+ isCollapsible,
1396
+ },
1387
1397
  label: 'Customer',
1388
1398
  description:
1389
1399
  'Enter your contact details, plan type, and addresses to complete your customer information.',
@@ -1448,12 +1458,13 @@ const LayoutCardComponent = ( { withHeader }: { withHeader: boolean } ) => {
1448
1458
  type: 'card',
1449
1459
  isOpened: false,
1450
1460
  summary: [ { id: 'dueDate', visibility: 'always' } ],
1461
+ isCollapsible,
1451
1462
  },
1452
1463
  children: [ 'vat', 'commission' ],
1453
1464
  },
1454
1465
  ],
1455
1466
  } ),
1456
- [ withHeader ]
1467
+ [ withHeader, isCollapsible ]
1457
1468
  );
1458
1469
 
1459
1470
  return (
@@ -1860,9 +1871,14 @@ export const LayoutCard = {
1860
1871
  control: { type: 'boolean' },
1861
1872
  description: 'Whether the card has a header.',
1862
1873
  },
1874
+ isCollapsible: {
1875
+ control: { type: 'boolean' },
1876
+ description: 'Whether the card can be collapsed/expanded.',
1877
+ },
1863
1878
  },
1864
1879
  args: {
1865
1880
  withHeader: true,
1881
+ isCollapsible: true,
1866
1882
  },
1867
1883
  };
1868
1884
 
@@ -161,6 +161,7 @@ describe( 'normalizeFormFields', () => {
161
161
  withHeader: true,
162
162
  isOpened: true,
163
163
  summary: [],
164
+ isCollapsible: true,
164
165
  },
165
166
  },
166
167
  ] );
@@ -187,6 +188,7 @@ describe( 'normalizeFormFields', () => {
187
188
  withHeader: false,
188
189
  isOpened: true,
189
190
  summary: [],
191
+ isCollapsible: false,
190
192
  },
191
193
  },
192
194
  ] );
@@ -211,6 +213,7 @@ describe( 'normalizeFormFields', () => {
211
213
  withHeader: true,
212
214
  isOpened: false,
213
215
  summary: [ { id: 'field1', visibility: 'always' } ],
216
+ isCollapsible: true,
214
217
  },
215
218
  },
216
219
  ] );
@@ -226,6 +229,7 @@ describe( 'normalizeFormFields', () => {
226
229
  'field2',
227
230
  { id: 'field1', visibility: 'always' },
228
231
  ],
232
+ isCollapsible: true,
229
233
  },
230
234
  fields: [ 'field1' ],
231
235
  };
@@ -241,6 +245,7 @@ describe( 'normalizeFormFields', () => {
241
245
  { id: 'field2', visibility: 'when-collapsed' },
242
246
  { id: 'field1', visibility: 'always' },
243
247
  ],
248
+ isCollapsible: true,
244
249
  },
245
250
  },
246
251
  ] );
@@ -300,6 +305,7 @@ describe( 'normalizeFormFields', () => {
300
305
  withHeader: false,
301
306
  isOpened: true,
302
307
  summary: [],
308
+ isCollapsible: false,
303
309
  },
304
310
  },
305
311
  {
@@ -309,6 +315,7 @@ describe( 'normalizeFormFields', () => {
309
315
  withHeader: true,
310
316
  isOpened: false,
311
317
  summary: [],
318
+ isCollapsible: true,
312
319
  },
313
320
  },
314
321
  ] );
@@ -56,12 +56,15 @@ export type CardLayout =
56
56
  // isOpened cannot be false if withHeader is false as well.
57
57
  // Otherwise, the card would not be visible.
58
58
  isOpened?: true;
59
+ // isCollapsible cannot be true if withHeader is false as well.
60
+ isCollapsible?: false;
59
61
  }
60
62
  | {
61
63
  type: 'card';
62
64
  withHeader?: true | undefined;
63
65
  isOpened?: boolean;
64
66
  summary?: CardSummaryField;
67
+ isCollapsible?: boolean | undefined;
65
68
  };
66
69
  export type NormalizedCardLayout =
67
70
  | {
@@ -72,12 +75,15 @@ export type NormalizedCardLayout =
72
75
  isOpened: true;
73
76
  // Summary is an empty array
74
77
  summary: [];
78
+ // If no header, the card should not be collapsible.
79
+ isCollapsible: false;
75
80
  }
76
81
  | {
77
82
  type: 'card';
78
83
  withHeader: true;
79
84
  isOpened: boolean;
80
85
  summary: NormalizedCardSummaryField;
86
+ isCollapsible: boolean;
81
87
  };
82
88
 
83
89
  export type RowLayout = {