@wordpress/dataviews 0.7.0 → 0.9.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 (79) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +49 -18
  3. package/build/constants.js +28 -10
  4. package/build/constants.js.map +1 -1
  5. package/build/dataviews.js +3 -7
  6. package/build/dataviews.js.map +1 -1
  7. package/build/filter-and-sort-data-view.js +147 -0
  8. package/build/filter-and-sort-data-view.js.map +1 -0
  9. package/build/filter-summary.js +33 -12
  10. package/build/filter-summary.js.map +1 -1
  11. package/build/filters.js +11 -16
  12. package/build/filters.js.map +1 -1
  13. package/build/index.js +3 -9
  14. package/build/index.js.map +1 -1
  15. package/build/item-actions.js +20 -39
  16. package/build/item-actions.js.map +1 -1
  17. package/build/normalize-fields.js +25 -0
  18. package/build/normalize-fields.js.map +1 -0
  19. package/build/pagination.js +2 -2
  20. package/build/pagination.js.map +1 -1
  21. package/build/search-widget.js +34 -10
  22. package/build/search-widget.js.map +1 -1
  23. package/build/utils.js +25 -67
  24. package/build/utils.js.map +1 -1
  25. package/build/view-grid.js +25 -12
  26. package/build/view-grid.js.map +1 -1
  27. package/build/view-list.js +122 -58
  28. package/build/view-list.js.map +1 -1
  29. package/build/view-table.js +53 -8
  30. package/build/view-table.js.map +1 -1
  31. package/build-module/constants.js +27 -9
  32. package/build-module/constants.js.map +1 -1
  33. package/build-module/dataviews.js +3 -7
  34. package/build-module/dataviews.js.map +1 -1
  35. package/build-module/filter-and-sort-data-view.js +139 -0
  36. package/build-module/filter-and-sort-data-view.js.map +1 -0
  37. package/build-module/filter-summary.js +34 -13
  38. package/build-module/filter-summary.js.map +1 -1
  39. package/build-module/filters.js +12 -17
  40. package/build-module/filters.js.map +1 -1
  41. package/build-module/index.js +1 -1
  42. package/build-module/index.js.map +1 -1
  43. package/build-module/item-actions.js +20 -39
  44. package/build-module/item-actions.js.map +1 -1
  45. package/build-module/normalize-fields.js +19 -0
  46. package/build-module/normalize-fields.js.map +1 -0
  47. package/build-module/pagination.js +2 -2
  48. package/build-module/pagination.js.map +1 -1
  49. package/build-module/search-widget.js +35 -11
  50. package/build-module/search-widget.js.map +1 -1
  51. package/build-module/utils.js +25 -66
  52. package/build-module/utils.js.map +1 -1
  53. package/build-module/view-grid.js +26 -13
  54. package/build-module/view-grid.js.map +1 -1
  55. package/build-module/view-list.js +124 -60
  56. package/build-module/view-list.js.map +1 -1
  57. package/build-module/view-table.js +55 -10
  58. package/build-module/view-table.js.map +1 -1
  59. package/build-style/style-rtl.css +41 -11
  60. package/build-style/style.css +41 -11
  61. package/package.json +11 -11
  62. package/src/constants.js +35 -9
  63. package/src/dataviews.js +3 -7
  64. package/src/filter-and-sort-data-view.js +154 -0
  65. package/src/filter-summary.js +76 -23
  66. package/src/filters.js +20 -26
  67. package/src/index.js +1 -1
  68. package/src/item-actions.js +19 -55
  69. package/src/normalize-fields.js +17 -0
  70. package/src/pagination.js +2 -2
  71. package/src/search-widget.js +63 -21
  72. package/src/stories/fixtures.js +87 -2
  73. package/src/stories/index.story.js +5 -74
  74. package/src/style.scss +53 -14
  75. package/src/test/filter-and-sort-data-view.js +276 -0
  76. package/src/utils.js +38 -56
  77. package/src/view-grid.js +36 -11
  78. package/src/view-list.js +159 -69
  79. package/src/view-table.js +71 -9
@@ -15,7 +15,7 @@ import {
15
15
  Icon,
16
16
  privateApis as componentsPrivateApis,
17
17
  } from '@wordpress/components';
18
- import { search } from '@wordpress/icons';
18
+ import { search, check } from '@wordpress/icons';
19
19
  import { SVG, Circle } from '@wordpress/primitives';
20
20
 
21
21
  /**
@@ -39,6 +39,36 @@ function normalizeSearchInput( input = '' ) {
39
39
  return removeAccents( input.trim().toLowerCase() );
40
40
  }
41
41
 
42
+ const getCurrentValue = ( filterDefinition, currentFilter ) => {
43
+ if ( filterDefinition.singleSelection ) {
44
+ return currentFilter?.value;
45
+ }
46
+
47
+ if ( Array.isArray( currentFilter?.value ) ) {
48
+ return currentFilter.value;
49
+ }
50
+
51
+ if ( ! Array.isArray( currentFilter?.value ) && !! currentFilter?.value ) {
52
+ return [ currentFilter.value ];
53
+ }
54
+
55
+ return [];
56
+ };
57
+
58
+ const getNewValue = ( filterDefinition, currentFilter, value ) => {
59
+ if ( filterDefinition.singleSelection ) {
60
+ return value;
61
+ }
62
+
63
+ if ( Array.isArray( currentFilter?.value ) ) {
64
+ return currentFilter.value.includes( value )
65
+ ? currentFilter.value.filter( ( v ) => v !== value )
66
+ : [ ...currentFilter.value, value ];
67
+ }
68
+
69
+ return [ value ];
70
+ };
71
+
42
72
  function ListBox( { view, filter, onChangeView } ) {
43
73
  const compositeStore = useCompositeStore( {
44
74
  virtualFocus: true,
@@ -48,10 +78,10 @@ function ListBox( { view, filter, onChangeView } ) {
48
78
  // so the first item is not selected, since the focus is on the operators control.
49
79
  defaultActiveId: filter.operators?.length === 1 ? undefined : null,
50
80
  } );
51
- const selectedFilter = view.filters.find(
52
- ( _filter ) => _filter.field === filter.field
81
+ const currentFilter = view.filters.find(
82
+ ( f ) => f.field === filter.field
53
83
  );
54
- const selectedValues = selectedFilter?.value;
84
+ const currentValue = getCurrentValue( filter, currentFilter );
55
85
  return (
56
86
  <Composite
57
87
  store={ compositeStore }
@@ -83,10 +113,6 @@ function ListBox( { view, filter, onChangeView } ) {
83
113
  />
84
114
  }
85
115
  onClick={ () => {
86
- const currentFilter = view.filters.find(
87
- ( _filter ) =>
88
- _filter.field === filter.field
89
- );
90
116
  const newFilters = currentFilter
91
117
  ? [
92
118
  ...view.filters.map(
@@ -101,7 +127,11 @@ function ListBox( { view, filter, onChangeView } ) {
101
127
  currentFilter.operator ||
102
128
  filter
103
129
  .operators[ 0 ],
104
- value: element.value,
130
+ value: getNewValue(
131
+ filter,
132
+ currentFilter,
133
+ element.value
134
+ ),
105
135
  };
106
136
  }
107
137
  return _filter;
@@ -113,7 +143,11 @@ function ListBox( { view, filter, onChangeView } ) {
113
143
  {
114
144
  field: filter.field,
115
145
  operator: filter.operators[ 0 ],
116
- value: element.value,
146
+ value: getNewValue(
147
+ filter,
148
+ currentFilter,
149
+ element.value
150
+ ),
117
151
  },
118
152
  ];
119
153
  onChangeView( {
@@ -126,9 +160,14 @@ function ListBox( { view, filter, onChangeView } ) {
126
160
  }
127
161
  >
128
162
  <span className="dataviews-search-widget-listitem-check">
129
- { selectedValues === element.value && (
130
- <Icon icon={ radioCheck } />
131
- ) }
163
+ { filter.singleSelection &&
164
+ currentValue === element.value && (
165
+ <Icon icon={ radioCheck } />
166
+ ) }
167
+ { ! filter.singleSelection &&
168
+ currentValue.includes( element.value ) && (
169
+ <Icon icon={ check } />
170
+ ) }
132
171
  </span>
133
172
  <span>
134
173
  { element.label }
@@ -147,10 +186,10 @@ function ListBox( { view, filter, onChangeView } ) {
147
186
  function ComboboxList( { view, filter, onChangeView } ) {
148
187
  const [ searchValue, setSearchValue ] = useState( '' );
149
188
  const deferredSearchValue = useDeferredValue( searchValue );
150
- const selectedFilter = view.filters.find(
189
+ const currentFilter = view.filters.find(
151
190
  ( _filter ) => _filter.field === filter.field
152
191
  );
153
- const selectedValues = selectedFilter?.value;
192
+ const currentValue = getCurrentValue( filter, currentFilter );
154
193
  const matches = useMemo( () => {
155
194
  const normalizedSearch = normalizeSearchInput( deferredSearchValue );
156
195
  return filter.elements.filter( ( item ) =>
@@ -160,10 +199,8 @@ function ComboboxList( { view, filter, onChangeView } ) {
160
199
  return (
161
200
  <Ariakit.ComboboxProvider
162
201
  value={ searchValue }
202
+ selectedValue={ currentValue }
163
203
  setSelectedValue={ ( value ) => {
164
- const currentFilter = view.filters.find(
165
- ( _filter ) => _filter.field === filter.field
166
- );
167
204
  const newFilters = currentFilter
168
205
  ? [
169
206
  ...view.filters.map( ( _filter ) => {
@@ -223,9 +260,14 @@ function ComboboxList( { view, filter, onChangeView } ) {
223
260
  focusOnHover
224
261
  >
225
262
  <span className="dataviews-search-widget-listitem-check">
226
- { selectedValues === element.value && (
227
- <Icon icon={ radioCheck } />
228
- ) }
263
+ { filter.singleSelection &&
264
+ currentValue === element.value && (
265
+ <Icon icon={ radioCheck } />
266
+ ) }
267
+ { ! filter.singleSelection &&
268
+ currentValue.includes( element.value ) && (
269
+ <Icon icon={ check } />
270
+ ) }
229
271
  </span>
230
272
  <span>
231
273
  <Ariakit.ComboboxItemValue
@@ -20,66 +20,88 @@ export const data = [
20
20
  title: 'Apollo',
21
21
  description: 'Apollo description',
22
22
  image: 'https://live.staticflickr.com/5725/21726228300_51333bd62c_b.jpg',
23
+ type: 'Not a planet',
24
+ categories: [ 'Space', 'NASA' ],
23
25
  },
24
26
  {
25
27
  id: 2,
26
28
  title: 'Space',
27
29
  description: 'Space description',
28
30
  image: 'https://live.staticflickr.com/5678/21911065441_92e2d44708_b.jpg',
31
+ type: 'Not a planet',
32
+ categories: [ 'Space' ],
29
33
  },
30
34
  {
31
35
  id: 3,
32
36
  title: 'NASA',
33
37
  description: 'NASA photo',
34
38
  image: 'https://live.staticflickr.com/742/21712365770_8f70a2c91e_b.jpg',
39
+ type: 'Not a planet',
40
+ categories: [ 'NASA' ],
35
41
  },
36
42
  {
37
43
  id: 4,
38
44
  title: 'Neptune',
39
45
  description: 'Neptune description',
40
46
  image: 'https://live.staticflickr.com/5725/21726228300_51333bd62c_b.jpg',
47
+ type: 'Ice giant',
48
+ categories: [ 'Space', 'Planet', 'Solar system' ],
41
49
  },
42
50
  {
43
51
  id: 5,
44
52
  title: 'Mercury',
45
53
  description: 'Mercury description',
46
54
  image: 'https://live.staticflickr.com/5725/21726228300_51333bd62c_b.jpg',
55
+ type: 'Terrestrial',
56
+ categories: [ 'Space', 'Planet', 'Solar system' ],
47
57
  },
48
58
  {
49
59
  id: 6,
50
60
  title: 'Venus',
51
- description: 'Venus description',
61
+ description: 'La planète Vénus',
52
62
  image: 'https://live.staticflickr.com/5725/21726228300_51333bd62c_b.jpg',
63
+ type: 'Terrestrial',
64
+ categories: [ 'Space', 'Planet', 'Solar system' ],
53
65
  },
54
66
  {
55
67
  id: 7,
56
68
  title: 'Earth',
57
69
  description: 'Earth description',
58
70
  image: 'https://live.staticflickr.com/5725/21726228300_51333bd62c_b.jpg',
71
+ type: 'Terrestrial',
72
+ categories: [ 'Space', 'Planet', 'Solar system' ],
59
73
  },
60
74
  {
61
75
  id: 8,
62
76
  title: 'Mars',
63
77
  description: 'Mars description',
64
78
  image: 'https://live.staticflickr.com/5725/21726228300_51333bd62c_b.jpg',
79
+ type: 'Terrestrial',
80
+ categories: [ 'Space', 'Planet', 'Solar system' ],
65
81
  },
66
82
  {
67
83
  id: 9,
68
84
  title: 'Jupiter',
69
85
  description: 'Jupiter description',
70
86
  image: 'https://live.staticflickr.com/5725/21726228300_51333bd62c_b.jpg',
87
+ type: 'Gas giant',
88
+ categories: [ 'Space', 'Planet', 'Solar system' ],
71
89
  },
72
90
  {
73
91
  id: 10,
74
92
  title: 'Saturn',
75
93
  description: 'Saturn description',
76
94
  image: 'https://live.staticflickr.com/5725/21726228300_51333bd62c_b.jpg',
95
+ type: 'Gas giant',
96
+ categories: [ 'Space', 'Planet', 'Solar system' ],
77
97
  },
78
98
  {
79
99
  id: 11,
80
100
  title: 'Uranus',
81
101
  description: 'Uranus description',
82
102
  image: 'https://live.staticflickr.com/5725/21726228300_51333bd62c_b.jpg',
103
+ type: 'Ice giant',
104
+ categories: [ 'Space', 'Ice giant', 'Solar system' ],
83
105
  },
84
106
  ];
85
107
 
@@ -88,7 +110,7 @@ export const DEFAULT_VIEW = {
88
110
  search: '',
89
111
  page: 1,
90
112
  perPage: 10,
91
- hiddenFields: [ 'image' ],
113
+ hiddenFields: [ 'image', 'type' ],
92
114
  layout: {},
93
115
  filters: [],
94
116
  };
@@ -124,3 +146,66 @@ export const actions = [
124
146
  callback() {},
125
147
  },
126
148
  ];
149
+
150
+ export const fields = [
151
+ {
152
+ header: 'Image',
153
+ id: 'image',
154
+ render: ( { item } ) => {
155
+ return (
156
+ <img src={ item.image } alt="" style={ { width: '100%' } } />
157
+ );
158
+ },
159
+ width: 50,
160
+ enableSorting: false,
161
+ },
162
+ {
163
+ header: 'Title',
164
+ id: 'title',
165
+ maxWidth: 400,
166
+ enableHiding: false,
167
+ enableGlobalSearch: true,
168
+ },
169
+ {
170
+ header: 'Type',
171
+ id: 'type',
172
+ maxWidth: 400,
173
+ enableHiding: false,
174
+ type: 'enumeration',
175
+ elements: [
176
+ { value: 'Not a planet', label: 'Not a planet' },
177
+ { value: 'Ice giant', label: 'Ice giant' },
178
+ { value: 'Terrestrial', label: 'Terrestrial' },
179
+ { value: 'Gas giant', label: 'Gas giant' },
180
+ ],
181
+ },
182
+ {
183
+ header: 'Description',
184
+ id: 'description',
185
+ maxWidth: 200,
186
+ enableSorting: false,
187
+ enableGlobalSearch: true,
188
+ },
189
+ {
190
+ header: 'Categories',
191
+ id: 'categories',
192
+ type: 'enumeration',
193
+ elements: [
194
+ { value: 'Space', label: 'Space' },
195
+ { value: 'NASA', label: 'NASA' },
196
+ { value: 'Planet', label: 'Planet' },
197
+ { value: 'Solar system', label: 'Solar system' },
198
+ { value: 'Ice giant', label: 'Ice giant' },
199
+ ],
200
+ filterBy: {
201
+ operators: [ 'isAny', 'isNone', 'isAll', 'isNotAll' ],
202
+ },
203
+ getValue: ( { item } ) => {
204
+ return item.categories;
205
+ },
206
+ render: ( { item } ) => {
207
+ return item.categories.join( ',' );
208
+ },
209
+ enableSorting: false,
210
+ },
211
+ ];
@@ -7,11 +7,12 @@ import { useState, useMemo, useCallback } from '@wordpress/element';
7
7
  * Internal dependencies
8
8
  */
9
9
  import { DataViews } from '../index';
10
- import { DEFAULT_VIEW, actions, data } from './fixtures';
10
+ import { DEFAULT_VIEW, actions, data, fields } from './fixtures';
11
11
  import { LAYOUT_GRID, LAYOUT_TABLE } from '../constants';
12
+ import { filterSortAndPaginate } from '../filter-and-sort-data-view';
12
13
 
13
14
  const meta = {
14
- title: 'DataViews (Experimental)/DataViews',
15
+ title: 'DataViews/DataViews',
15
16
  component: DataViews,
16
17
  };
17
18
  export default meta;
@@ -26,80 +27,10 @@ const defaultConfigPerViewType = {
26
27
  },
27
28
  };
28
29
 
29
- function normalizeSearchInput( input = '' ) {
30
- return input.trim().toLowerCase();
31
- }
32
-
33
- const fields = [
34
- {
35
- header: 'Image',
36
- id: 'image',
37
- render: ( { item } ) => {
38
- return (
39
- <img src={ item.image } alt="" style={ { width: '100%' } } />
40
- );
41
- },
42
- width: 50,
43
- enableSorting: false,
44
- },
45
- {
46
- header: 'Title',
47
- id: 'title',
48
- getValue: ( { item } ) => item.title,
49
- maxWidth: 400,
50
- enableHiding: false,
51
- },
52
- {
53
- header: 'Description',
54
- id: 'description',
55
- getValue: ( { item } ) => item.description,
56
- maxWidth: 200,
57
- enableSorting: false,
58
- },
59
- ];
60
-
61
30
  export const Default = ( props ) => {
62
31
  const [ view, setView ] = useState( DEFAULT_VIEW );
63
- const { shownData, paginationInfo } = useMemo( () => {
64
- let filteredData = [ ...data ];
65
- // Handle global search.
66
- if ( view.search ) {
67
- const normalizedSearch = normalizeSearchInput( view.search );
68
- filteredData = filteredData.filter( ( item ) => {
69
- return [
70
- normalizeSearchInput( item.title ),
71
- normalizeSearchInput( item.description ),
72
- ].some( ( field ) => field.includes( normalizedSearch ) );
73
- } );
74
- }
75
- // Handle sorting.
76
- if ( view.sort ) {
77
- const stringSortingFields = [ 'title' ];
78
- const fieldId = view.sort.field;
79
- if ( stringSortingFields.includes( fieldId ) ) {
80
- const fieldToSort = fields.find( ( field ) => {
81
- return field.id === fieldId;
82
- } );
83
- filteredData.sort( ( a, b ) => {
84
- const valueA = fieldToSort.getValue( { item: a } ) ?? '';
85
- const valueB = fieldToSort.getValue( { item: b } ) ?? '';
86
- return view.sort.direction === 'asc'
87
- ? valueA.localeCompare( valueB )
88
- : valueB.localeCompare( valueA );
89
- } );
90
- }
91
- }
92
- // Handle pagination.
93
- const start = ( view.page - 1 ) * view.perPage;
94
- const totalItems = filteredData?.length || 0;
95
- filteredData = filteredData?.slice( start, start + view.perPage );
96
- return {
97
- shownData: filteredData,
98
- paginationInfo: {
99
- totalItems,
100
- totalPages: Math.ceil( totalItems / view.perPage ),
101
- },
102
- };
32
+ const { data: shownData, paginationInfo } = useMemo( () => {
33
+ return filterSortAndPaginate( data, view, fields );
103
34
  }, [ view ] );
104
35
  const onChangeView = useCallback(
105
36
  ( newView ) => {
package/src/style.scss CHANGED
@@ -1,5 +1,4 @@
1
1
  .dataviews-wrapper {
2
- width: 100%;
3
2
  height: 100%;
4
3
  overflow: auto;
5
4
  box-sizing: border-box;
@@ -7,6 +6,7 @@
7
6
  }
8
7
 
9
8
  .dataviews-filters__view-actions {
9
+ box-sizing: border-box;
10
10
  padding: $grid-unit-15 $grid-unit-40 0;
11
11
  margin-bottom: $grid-unit-15;
12
12
  flex-shrink: 0;
@@ -123,7 +123,7 @@
123
123
  border-bottom: 0;
124
124
  }
125
125
 
126
- &:hover {
126
+ &.is-hovered {
127
127
  background-color: #f8f8f8;
128
128
  }
129
129
 
@@ -137,9 +137,15 @@
137
137
  }
138
138
  }
139
139
 
140
+ .dataviews-item-actions .components-button:not(.dataviews-all-actions-button) {
141
+ opacity: 0;
142
+ }
143
+
140
144
  &:focus-within,
145
+ &.is-hovered,
141
146
  &:hover {
142
- .components-checkbox-control__input {
147
+ .components-checkbox-control__input,
148
+ .dataviews-item-actions .components-button:not(.dataviews-all-actions-button) {
143
149
  opacity: 1;
144
150
  }
145
151
  }
@@ -184,6 +190,12 @@
184
190
  > * {
185
191
  flex-grow: 1;
186
192
  }
193
+
194
+ &.dataviews-view-table__primary-field {
195
+ a {
196
+ flex-grow: 0;
197
+ }
198
+ }
187
199
  }
188
200
  }
189
201
  .dataviews-view-table-header-button {
@@ -238,10 +250,10 @@
238
250
  white-space: nowrap;
239
251
  overflow: hidden;
240
252
  display: block;
241
- width: 100%;
253
+ flex-grow: 0;
242
254
 
243
255
  &:hover {
244
- color: $gray-900;
256
+ color: var(--wp-admin-theme-color);
245
257
  }
246
258
  @include link-reset();
247
259
  }
@@ -321,7 +333,24 @@
321
333
  }
322
334
 
323
335
  .dataviews-view-grid__field {
324
- .dataviews-view-grid__field-value {
336
+ align-items: flex-start;
337
+
338
+ &:not(.is-column) {
339
+ align-items: center;
340
+
341
+ .dataviews-view-grid__field-name {
342
+ width: 35%;
343
+ }
344
+
345
+ .dataviews-view-grid__field-value {
346
+ width: 65%;
347
+ overflow: hidden;
348
+ text-overflow: ellipsis;
349
+ white-space: nowrap;
350
+ }
351
+ }
352
+
353
+ .dataviews-view-grid__field-name {
325
354
  color: $gray-700;
326
355
  }
327
356
  }
@@ -334,6 +363,7 @@
334
363
 
335
364
  li {
336
365
  margin: 0;
366
+ cursor: pointer;
337
367
 
338
368
  .dataviews-view-list__item-wrapper {
339
369
  position: relative;
@@ -349,14 +379,21 @@
349
379
  background: $gray-100;
350
380
  height: 1px;
351
381
  }
352
- }
353
382
 
354
- &:not(.is-selected):hover {
355
- color: var(--wp-admin-theme-color);
383
+ > * {
384
+ width: 100%;
385
+ }
386
+ }
356
387
 
357
- .dataviews-view-list__primary-field,
358
- .dataviews-view-list__fields {
388
+ &:not(.is-selected) {
389
+ &:hover,
390
+ &:focus-within {
359
391
  color: var(--wp-admin-theme-color);
392
+
393
+ .dataviews-view-list__primary-field,
394
+ .dataviews-view-list__fields {
395
+ color: var(--wp-admin-theme-color);
396
+ }
360
397
  }
361
398
  }
362
399
  }
@@ -382,8 +419,9 @@
382
419
  .dataviews-view-list__item {
383
420
  padding: $grid-unit-15 0 $grid-unit-15 $grid-unit-30;
384
421
  width: 100%;
385
- cursor: pointer;
386
- &:focus {
422
+ scroll-margin: $grid-unit-10 0;
423
+
424
+ &:focus-visible {
387
425
  &::before {
388
426
  position: absolute;
389
427
  content: "";
@@ -398,6 +436,7 @@
398
436
  }
399
437
  .dataviews-view-list__primary-field {
400
438
  min-height: $grid-unit-05 * 5;
439
+ overflow: hidden;
401
440
  }
402
441
  }
403
442
 
@@ -443,7 +482,7 @@
443
482
  line-height: $grid-unit-20;
444
483
 
445
484
  .dataviews-view-list__field {
446
- &:empty {
485
+ &:has(.dataviews-view-list__field-value:empty) {
447
486
  display: none;
448
487
  }
449
488
  }