@wordpress/dataviews 0.3.0 → 0.4.1

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 +2 -0
  2. package/build/bulk-actions.js +143 -0
  3. package/build/bulk-actions.js.map +1 -0
  4. package/build/dataviews.js +15 -1
  5. package/build/dataviews.js.map +1 -1
  6. package/build/item-actions.js +4 -4
  7. package/build/item-actions.js.map +1 -1
  8. package/build/pagination.js +2 -2
  9. package/build/pagination.js.map +1 -1
  10. package/build/view-actions.js +3 -2
  11. package/build/view-actions.js.map +1 -1
  12. package/build/view-grid.js +11 -8
  13. package/build/view-grid.js.map +1 -1
  14. package/build/view-list.js +13 -1
  15. package/build/view-list.js.map +1 -1
  16. package/build/view-table.js +116 -9
  17. package/build/view-table.js.map +1 -1
  18. package/build-module/bulk-actions.js +136 -0
  19. package/build-module/bulk-actions.js.map +1 -0
  20. package/build-module/dataviews.js +17 -3
  21. package/build-module/dataviews.js.map +1 -1
  22. package/build-module/item-actions.js +4 -4
  23. package/build-module/item-actions.js.map +1 -1
  24. package/build-module/pagination.js +2 -2
  25. package/build-module/pagination.js.map +1 -1
  26. package/build-module/view-actions.js +4 -3
  27. package/build-module/view-actions.js.map +1 -1
  28. package/build-module/view-grid.js +12 -9
  29. package/build-module/view-grid.js.map +1 -1
  30. package/build-module/view-list.js +13 -1
  31. package/build-module/view-list.js.map +1 -1
  32. package/build-module/view-table.js +120 -13
  33. package/build-module/view-table.js.map +1 -1
  34. package/build-style/style-rtl.css +147 -26
  35. package/build-style/style.css +147 -26
  36. package/package.json +11 -11
  37. package/src/bulk-actions.js +187 -0
  38. package/src/dataviews.js +29 -2
  39. package/src/item-actions.js +4 -7
  40. package/src/pagination.js +2 -6
  41. package/src/style.scss +156 -28
  42. package/src/view-actions.js +8 -14
  43. package/src/view-grid.js +14 -12
  44. package/src/view-list.js +20 -1
  45. package/src/view-table.js +161 -15
package/src/style.scss CHANGED
@@ -18,6 +18,10 @@
18
18
  }
19
19
  }
20
20
 
21
+ .dataviews-filters__view-actions.components-h-stack {
22
+ align-items: center;
23
+ }
24
+
21
25
  .dataviews-filters-button {
22
26
  position: relative;
23
27
  }
@@ -55,6 +59,10 @@
55
59
  margin: $grid-unit-40 0 $grid-unit-20;
56
60
  }
57
61
 
62
+ .dataviews-view-table-wrapper {
63
+ overflow-x: auto;
64
+ }
65
+
58
66
  .dataviews-view-table {
59
67
  width: 100%;
60
68
  text-indent: 0;
@@ -77,10 +85,23 @@
77
85
  td,
78
86
  th {
79
87
  padding: $grid-unit-15;
80
- min-width: 160px;
88
+ white-space: nowrap;
89
+
90
+ @include break-huge() {
91
+ min-width: 200px;
92
+ }
93
+
81
94
  &[data-field-id="actions"] {
82
95
  text-align: right;
83
96
  }
97
+
98
+ &.dataviews-view-table__checkbox-column {
99
+ padding-right: 0;
100
+ }
101
+
102
+ .components-checkbox-control__input-container {
103
+ margin: $grid-unit-05;
104
+ }
84
105
  }
85
106
  tr {
86
107
  border-bottom: 1px solid $gray-100;
@@ -109,8 +130,32 @@
109
130
  }
110
131
 
111
132
  &:hover {
112
- td {
113
- background-color: #f8f8f8;
133
+ background-color: #f8f8f8;
134
+ }
135
+
136
+ .components-checkbox-control__input {
137
+ opacity: 0;
138
+
139
+ &:checked,
140
+ &:indeterminate,
141
+ &:focus {
142
+ opacity: 1;
143
+ }
144
+ }
145
+
146
+ &:focus-within,
147
+ &:hover {
148
+ .components-checkbox-control__input {
149
+ opacity: 1;
150
+ }
151
+ }
152
+
153
+ &.is-selected {
154
+ background-color: rgba(var(--wp-admin-theme-color--rgb), 0.04);
155
+ color: $gray-700;
156
+
157
+ &:hover {
158
+ background-color: rgba(var(--wp-admin-theme-color--rgb), 0.08);
114
159
  }
115
160
  }
116
161
  }
@@ -132,7 +177,20 @@
132
177
  padding-left: $grid-unit-05;
133
178
  }
134
179
  }
180
+ tbody {
181
+ td {
182
+ vertical-align: top;
183
+ }
184
+ .dataviews-view-table__cell-content-wrapper {
185
+ min-height: $grid-unit-40;
186
+ display: flex;
187
+ align-items: center;
135
188
 
189
+ > * {
190
+ flex-grow: 1;
191
+ }
192
+ }
193
+ }
136
194
  .dataviews-view-table-header-button {
137
195
  padding: $grid-unit-05 $grid-unit-10;
138
196
  font-size: 11px;
@@ -155,11 +213,54 @@
155
213
  .dataviews-view-table-header {
156
214
  padding-left: $grid-unit-05;
157
215
  }
216
+
217
+ .dataviews-view-table__actions-column {
218
+ width: 1%;
219
+ }
220
+ }
221
+
222
+ .dataviews-view-list__primary-field,
223
+ .dataviews-view-grid__primary-field,
224
+ .dataviews-view-table__primary-field {
225
+ font-size: $default-font-size;
226
+ font-weight: 500;
227
+ color: $gray-900;
228
+ text-overflow: ellipsis;
229
+ white-space: nowrap;
230
+ overflow: hidden;
231
+ display: block;
232
+ width: 100%;
233
+
234
+ a {
235
+ text-decoration: none;
236
+ color: inherit;
237
+ text-overflow: ellipsis;
238
+ white-space: nowrap;
239
+ overflow: hidden;
240
+ display: block;
241
+ width: 100%;
242
+
243
+ &:hover {
244
+ color: $gray-900;
245
+ }
246
+ }
247
+
248
+ button.components-button.is-link {
249
+ text-decoration: none;
250
+ color: inherit;
251
+ font-weight: inherit;
252
+ text-overflow: ellipsis;
253
+ white-space: nowrap;
254
+ overflow: hidden;
255
+ display: block;
256
+ width: 100%;
257
+ }
158
258
  }
159
259
 
160
260
  .dataviews-view-grid {
161
261
  margin-bottom: $grid-unit-30;
162
262
  grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
263
+ grid-template-rows: max-content;
163
264
  padding: 0 $grid-unit-40;
164
265
 
165
266
  @include break-xlarge() {
@@ -171,22 +272,17 @@
171
272
  }
172
273
 
173
274
  .dataviews-view-grid__card {
174
- .dataviews-view-grid__primary-field {
175
- .dataviews-view-grid__title-field {
176
- white-space: nowrap;
177
- overflow: hidden;
178
- text-overflow: ellipsis;
179
- display: block;
180
- font-size: $default-font-size;
181
- width: 100%;
182
- }
275
+ border-radius: $radius-block-ui * 2;
276
+ border: 1px solid $gray-200;
277
+ height: 100%;
278
+ justify-content: flex-start;
183
279
 
184
- .dataviews-view-grid__title-field a,
185
- button.dataviews-view-grid__title-field {
186
- font-weight: 500;
187
- color: $gray-900;
188
- text-decoration: none;
189
- }
280
+ .dataviews-view-grid__title-actions {
281
+ padding: 0 $grid-unit-05;
282
+ }
283
+
284
+ .dataviews-view-grid__primary-field {
285
+ min-height: $grid-unit-50;
190
286
  }
191
287
  }
192
288
 
@@ -194,11 +290,11 @@
194
290
  width: 100%;
195
291
  min-height: 200px;
196
292
  aspect-ratio: 1/1;
197
- box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1);
198
- border-radius: $radius-block-ui * 2;
199
- overflow: hidden;
293
+ border-bottom: 1px solid $gray-200;
294
+ background-color: $gray-100;
295
+ border-radius: 3px 3px 0 0;
200
296
 
201
- > * {
297
+ img {
202
298
  object-fit: cover;
203
299
  width: 100%;
204
300
  height: 100%;
@@ -206,7 +302,7 @@
206
302
  }
207
303
 
208
304
  .dataviews-view-grid__primary-field {
209
- min-height: $grid-unit-30;
305
+ padding: $grid-unit-10;
210
306
  }
211
307
 
212
308
  .dataviews-view-grid__fields {
@@ -214,12 +310,14 @@
214
310
  font-size: 12px;
215
311
  line-height: 16px;
216
312
 
313
+ &:not(:empty) {
314
+ padding: $grid-unit-15;
315
+ padding-top: 0;
316
+ }
317
+
217
318
  .dataviews-view-grid__field {
218
- .dataviews-view-grid__field-header {
219
- color: $gray-700;
220
- }
221
319
  .dataviews-view-grid__field-value {
222
- color: $gray-900;
320
+ color: $gray-700;
223
321
  }
224
322
  }
225
323
  }
@@ -251,6 +349,7 @@
251
349
  &:not(.is-selected):hover {
252
350
  color: var(--wp-admin-theme-color);
253
351
 
352
+ .dataviews-view-list__primary-field,
254
353
  .dataviews-view-list__fields {
255
354
  color: var(--wp-admin-theme-color);
256
355
  }
@@ -263,6 +362,7 @@
263
362
  background-color: var(--wp-admin-theme-color);
264
363
  color: $white;
265
364
 
365
+ .dataviews-view-list__primary-field,
266
366
  .dataviews-view-list__fields,
267
367
  .components-button {
268
368
  color: $white;
@@ -299,11 +399,19 @@
299
399
  }
300
400
 
301
401
  .dataviews-view-list__media-wrapper {
302
- min-width: $grid-unit-40;
402
+ width: $grid-unit-40;
303
403
  height: $grid-unit-40;
304
404
  border-radius: $grid-unit-05;
305
405
  overflow: hidden;
306
406
  position: relative;
407
+ flex-shrink: 0;
408
+ background-color: $gray-100;
409
+
410
+ img {
411
+ width: 100%;
412
+ height: 100%;
413
+ object-fit: cover;
414
+ }
307
415
 
308
416
  &::after {
309
417
  content: "";
@@ -335,6 +443,10 @@
335
443
  &:last-child {
336
444
  margin-right: 0;
337
445
  }
446
+
447
+ &:empty {
448
+ display: none;
449
+ }
338
450
  }
339
451
  }
340
452
 
@@ -373,7 +485,23 @@
373
485
  padding: 0 $grid-unit-40;
374
486
  }
375
487
 
488
+ .dataviews-view-table-selection-checkbox label {
489
+ position: absolute;
490
+ width: 1px;
491
+ height: 1px;
492
+ padding: 0;
493
+ margin: -1px;
494
+ overflow: hidden;
495
+ clip: rect(0, 0, 0, 0);
496
+ white-space: nowrap;
497
+ border: 0;
498
+ }
499
+
376
500
  .dataviews-filters__custom-menu-radio-item-prefix {
377
501
  display: block;
378
502
  width: 24px;
379
503
  }
504
+
505
+ .dataviews-bulk-edit-button.components-button {
506
+ flex-shrink: 0;
507
+ }
@@ -7,12 +7,13 @@ import {
7
7
  } from '@wordpress/components';
8
8
  import { __ } from '@wordpress/i18n';
9
9
  import { memo } from '@wordpress/element';
10
+ import { settings } from '@wordpress/icons';
10
11
 
11
12
  /**
12
13
  * Internal dependencies
13
14
  */
14
15
  import { unlock } from './lock-unlock';
15
- import { VIEW_LAYOUTS, LAYOUT_TABLE, SORTING_DIRECTIONS } from './constants';
16
+ import { VIEW_LAYOUTS, SORTING_DIRECTIONS } from './constants';
16
17
 
17
18
  const {
18
19
  DropdownMenuV2: DropdownMenu,
@@ -260,24 +261,17 @@ const ViewActions = memo( function ViewActions( {
260
261
  trigger={
261
262
  <Button
262
263
  size="compact"
263
- icon={
264
- VIEW_LAYOUTS.find( ( v ) => v.type === view.type )
265
- ?.icon ||
266
- VIEW_LAYOUTS.find( ( v ) => v.type === LAYOUT_TABLE )
267
- .icon
268
- }
264
+ icon={ settings }
269
265
  label={ __( 'View options' ) }
270
266
  />
271
267
  }
272
268
  >
273
269
  <DropdownMenuGroup>
274
- { window?.__experimentalAdminViews && (
275
- <ViewTypeMenu
276
- view={ view }
277
- onChangeView={ onChangeView }
278
- supportedLayouts={ supportedLayouts }
279
- />
280
- ) }
270
+ <ViewTypeMenu
271
+ view={ view }
272
+ onChangeView={ onChangeView }
273
+ supportedLayouts={ supportedLayouts }
274
+ />
281
275
  <SortMenu
282
276
  fields={ fields }
283
277
  view={ view }
package/src/view-grid.js CHANGED
@@ -2,10 +2,10 @@
2
2
  * WordPress dependencies
3
3
  */
4
4
  import {
5
- FlexBlock,
6
5
  __experimentalGrid as Grid,
7
6
  __experimentalHStack as HStack,
8
7
  __experimentalVStack as VStack,
8
+ Tooltip,
9
9
  } from '@wordpress/components';
10
10
  import { useAsyncList } from '@wordpress/compose';
11
11
 
@@ -39,14 +39,14 @@ export default function ViewGrid( {
39
39
  const usedData = deferredRendering ? shownData : data;
40
40
  return (
41
41
  <Grid
42
- gap={ 8 }
42
+ gap={ 6 }
43
43
  columns={ 2 }
44
44
  alignment="top"
45
45
  className="dataviews-view-grid"
46
46
  >
47
47
  { usedData.map( ( item ) => (
48
48
  <VStack
49
- spacing={ 3 }
49
+ spacing={ 0 }
50
50
  key={ getItemId( item ) }
51
51
  className="dataviews-view-grid__card"
52
52
  >
@@ -54,12 +54,12 @@ export default function ViewGrid( {
54
54
  { mediaField?.render( { item } ) }
55
55
  </div>
56
56
  <HStack
57
- className="dataviews-view-grid__primary-field"
58
57
  justify="space-between"
58
+ className="dataviews-view-grid__title-actions"
59
59
  >
60
- <FlexBlock>
60
+ <HStack className="dataviews-view-grid__primary-field">
61
61
  { primaryField?.render( { item } ) }
62
- </FlexBlock>
62
+ </HStack>
63
63
  <ItemActions
64
64
  item={ item }
65
65
  actions={ actions }
@@ -83,12 +83,14 @@ export default function ViewGrid( {
83
83
  key={ field.id }
84
84
  spacing={ 1 }
85
85
  >
86
- <div className="dataviews-view-grid__field-header">
87
- { field.header }
88
- </div>
89
- <div className="dataviews-view-grid__field-value">
90
- { renderedValue }
91
- </div>
86
+ <Tooltip
87
+ text={ field.header }
88
+ placement="left"
89
+ >
90
+ <div className="dataviews-view-grid__field-value">
91
+ { renderedValue }
92
+ </div>
93
+ </Tooltip>
92
94
  </VStack>
93
95
  );
94
96
  } ) }
package/src/view-list.js CHANGED
@@ -20,6 +20,7 @@ export default function ViewList( {
20
20
  view,
21
21
  fields,
22
22
  data,
23
+ isLoading,
23
24
  getItemId,
24
25
  onSelectionChange,
25
26
  onDetailsChange,
@@ -49,6 +50,22 @@ export default function ViewList( {
49
50
  }
50
51
  };
51
52
 
53
+ const hasData = usedData?.length;
54
+ if ( ! hasData ) {
55
+ return (
56
+ <div
57
+ className={ classNames( {
58
+ 'dataviews-loading': isLoading,
59
+ 'dataviews-no-results': ! hasData && ! isLoading,
60
+ } ) }
61
+ >
62
+ { ! hasData && (
63
+ <p>{ isLoading ? __( 'Loading…' ) : __( 'No results' ) }</p>
64
+ ) }
65
+ </div>
66
+ );
67
+ }
68
+
52
69
  return (
53
70
  <ul className="dataviews-view-list">
54
71
  { usedData.map( ( item ) => {
@@ -75,7 +92,9 @@ export default function ViewList( {
75
92
  ) }
76
93
  </div>
77
94
  <VStack spacing={ 1 }>
78
- { primaryField?.render( { item } ) }
95
+ <span className="dataviews-view-list__primary-field">
96
+ { primaryField?.render( { item } ) }
97
+ </span>
79
98
  <div className="dataviews-view-list__fields">
80
99
  { visibleFields.map( ( field ) => {
81
100
  return (
package/src/view-table.js CHANGED
@@ -1,18 +1,19 @@
1
1
  /**
2
2
  * External dependencies
3
3
  */
4
- import classNames from 'classnames';
4
+ import classnames from 'classnames';
5
5
 
6
6
  /**
7
7
  * WordPress dependencies
8
8
  */
9
- import { __ } from '@wordpress/i18n';
9
+ import { __, sprintf } from '@wordpress/i18n';
10
10
  import { useAsyncList } from '@wordpress/compose';
11
11
  import { unseen, funnel } from '@wordpress/icons';
12
12
  import {
13
13
  Button,
14
14
  Icon,
15
15
  privateApis as componentsPrivateApis,
16
+ CheckboxControl,
16
17
  } from '@wordpress/components';
17
18
  import {
18
19
  Children,
@@ -306,6 +307,80 @@ function WithSeparators( { children } ) {
306
307
  ) );
307
308
  }
308
309
 
310
+ function BulkSelectionCheckbox( { selection, onSelectionChange, data } ) {
311
+ const areAllSelected = selection.length === data.length;
312
+ return (
313
+ <CheckboxControl
314
+ className="dataviews-view-table-selection-checkbox"
315
+ __nextHasNoMarginBottom
316
+ checked={ areAllSelected }
317
+ indeterminate={ ! areAllSelected && selection.length }
318
+ onChange={ () => {
319
+ if ( areAllSelected ) {
320
+ onSelectionChange( [] );
321
+ } else {
322
+ onSelectionChange( data );
323
+ }
324
+ } }
325
+ label={ areAllSelected ? __( 'Deselect all' ) : __( 'Select all' ) }
326
+ />
327
+ );
328
+ }
329
+
330
+ function SingleSelectionCheckbox( {
331
+ selection,
332
+ onSelectionChange,
333
+ item,
334
+ data,
335
+ getItemId,
336
+ primaryField,
337
+ } ) {
338
+ const id = getItemId( item );
339
+ const isSelected = selection.includes( id );
340
+ let selectionLabel;
341
+ if ( primaryField?.getValue && item ) {
342
+ // eslint-disable-next-line @wordpress/valid-sprintf
343
+ selectionLabel = sprintf(
344
+ /* translators: %s: item title. */
345
+ isSelected ? __( 'Deselect item: %s' ) : __( 'Select item: %s' ),
346
+ primaryField.getValue( { item } )
347
+ );
348
+ } else {
349
+ selectionLabel = isSelected
350
+ ? __( 'Select a new item' )
351
+ : __( 'Deselect item' );
352
+ }
353
+ return (
354
+ <CheckboxControl
355
+ className="dataviews-view-table-selection-checkbox"
356
+ __nextHasNoMarginBottom
357
+ checked={ isSelected }
358
+ label={ selectionLabel }
359
+ onChange={ () => {
360
+ if ( ! isSelected ) {
361
+ onSelectionChange(
362
+ data.filter( ( _item ) => {
363
+ const itemId = getItemId?.( _item );
364
+ return (
365
+ itemId === id || selection.includes( itemId )
366
+ );
367
+ } )
368
+ );
369
+ } else {
370
+ onSelectionChange(
371
+ data.filter( ( _item ) => {
372
+ const itemId = getItemId?.( _item );
373
+ return (
374
+ itemId !== id && selection.includes( itemId )
375
+ );
376
+ } )
377
+ );
378
+ }
379
+ } }
380
+ />
381
+ );
382
+ }
383
+
309
384
  function ViewTable( {
310
385
  view,
311
386
  onChangeView,
@@ -315,7 +390,10 @@ function ViewTable( {
315
390
  getItemId,
316
391
  isLoading = false,
317
392
  deferredRendering,
393
+ selection,
394
+ onSelectionChange,
318
395
  } ) {
396
+ const hasBulkActions = actions?.some( ( action ) => action.supportsBulk );
319
397
  const headerMenuRefs = useRef( new Map() );
320
398
  const headerMenuToFocusRef = useRef();
321
399
  const [ nextHeaderMenuToFocus, setNextHeaderMenuToFocus ] = useState();
@@ -348,23 +426,42 @@ function ViewTable( {
348
426
  const visibleFields = fields.filter(
349
427
  ( field ) =>
350
428
  ! view.hiddenFields.includes( field.id ) &&
351
- ! [ view.layout.mediaField, view.layout.primaryField ].includes(
352
- field.id
353
- )
429
+ ! [ view.layout.mediaField ].includes( field.id )
354
430
  );
355
431
  const usedData = deferredRendering ? asyncData : data;
356
432
  const hasData = !! usedData?.length;
357
433
  const sortValues = { asc: 'ascending', desc: 'descending' };
358
434
 
435
+ const primaryField = fields.find(
436
+ ( field ) => field.id === view.layout.primaryField
437
+ );
438
+
359
439
  return (
360
- <div>
440
+ <div className="dataviews-view-table-wrapper">
361
441
  <table
362
442
  className="dataviews-view-table"
363
443
  aria-busy={ isLoading }
364
444
  aria-describedby={ tableNoticeId }
365
445
  >
366
446
  <thead>
367
- <tr>
447
+ <tr className="dataviews-view-table__row">
448
+ { hasBulkActions && (
449
+ <th
450
+ className="dataviews-view-table__checkbox-column"
451
+ style={ {
452
+ width: 20,
453
+ minWidth: 20,
454
+ } }
455
+ data-field-id="selection"
456
+ scope="col"
457
+ >
458
+ <BulkSelectionCheckbox
459
+ selection={ selection }
460
+ onSelectionChange={ onSelectionChange }
461
+ data={ data }
462
+ />
463
+ </th>
464
+ ) }
368
465
  { visibleFields.map( ( field, index ) => (
369
466
  <th
370
467
  key={ field.id }
@@ -409,7 +506,10 @@ function ViewTable( {
409
506
  </th>
410
507
  ) ) }
411
508
  { !! actions?.length && (
412
- <th data-field-id="actions">
509
+ <th
510
+ data-field-id="actions"
511
+ className="dataviews-view-table__actions-column"
512
+ >
413
513
  <span className="dataviews-view-table-header">
414
514
  { __( 'Actions' ) }
415
515
  </span>
@@ -419,8 +519,43 @@ function ViewTable( {
419
519
  </thead>
420
520
  <tbody>
421
521
  { hasData &&
422
- usedData.map( ( item ) => (
423
- <tr key={ getItemId( item ) }>
522
+ usedData.map( ( item, index ) => (
523
+ <tr
524
+ key={ getItemId( item ) }
525
+ className={ classnames(
526
+ 'dataviews-view-table__row',
527
+ {
528
+ 'is-selected': selection.includes(
529
+ getItemId( item ) || index
530
+ ),
531
+ }
532
+ ) }
533
+ >
534
+ { hasBulkActions && (
535
+ <td
536
+ className="dataviews-view-table__checkbox-column"
537
+ style={ {
538
+ width: 20,
539
+ minWidth: 20,
540
+ } }
541
+ >
542
+ <div className="dataviews-view-table__cell-content-wrapper">
543
+ <SingleSelectionCheckbox
544
+ id={
545
+ getItemId( item ) || index
546
+ }
547
+ item={ item }
548
+ selection={ selection }
549
+ onSelectionChange={
550
+ onSelectionChange
551
+ }
552
+ getItemId={ getItemId }
553
+ data={ data }
554
+ primaryField={ primaryField }
555
+ />
556
+ </div>
557
+ </td>
558
+ ) }
424
559
  { visibleFields.map( ( field ) => (
425
560
  <td
426
561
  key={ field.id }
@@ -432,13 +567,24 @@ function ViewTable( {
432
567
  field.maxWidth || undefined,
433
568
  } }
434
569
  >
435
- { field.render( {
436
- item,
437
- } ) }
570
+ <div
571
+ className={ classnames(
572
+ 'dataviews-view-table__cell-content-wrapper',
573
+ {
574
+ 'dataviews-view-table__primary-field':
575
+ primaryField?.id ===
576
+ field.id,
577
+ }
578
+ ) }
579
+ >
580
+ { field.render( {
581
+ item,
582
+ } ) }
583
+ </div>
438
584
  </td>
439
585
  ) ) }
440
586
  { !! actions?.length && (
441
- <td>
587
+ <td className="dataviews-view-table__actions-column">
442
588
  <ItemActions
443
589
  item={ item }
444
590
  actions={ actions }
@@ -450,7 +596,7 @@ function ViewTable( {
450
596
  </tbody>
451
597
  </table>
452
598
  <div
453
- className={ classNames( {
599
+ className={ classnames( {
454
600
  'dataviews-loading': isLoading,
455
601
  'dataviews-no-results': ! hasData && ! isLoading,
456
602
  } ) }