@asd20/ui-next 2.0.28 → 2.1.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.
- package/CHANGELOG.md +9 -0
- package/package.json +1 -1
- package/src/components/atoms/Asd20RichBodyContent/index.vue +9 -0
- package/src/components/organisms/Asd20FileList/index.vue +306 -10
- package/src/components/organisms/Asd20List/index.vue +37 -10
- package/src/components/organisms/Asd20WidgetList/index.vue +37 -10
- package/src/components/templates/Asd20FileListPageTemplate/index.vue +4 -0
- package/src/design/_typography.scss +7 -0
- package/src/helpers/richBodyListColumns.js +48 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
# [2.1.0](https://github.com/academydistrict20/asd20-ui-next/compare/ui-next-v2.0.29...ui-next-v2.1.0) (2026-04-06)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* revise file list template and componets to add search ([661b500](https://github.com/academydistrict20/asd20-ui-next/commit/661b500259a263285b37adf497156417fe983430))
|
|
9
|
+
|
|
10
|
+
## [2.0.29](https://github.com/academydistrict20/asd20-ui-next/compare/ui-next-v2.0.28...ui-next-v2.0.29) (2026-04-06)
|
|
11
|
+
|
|
3
12
|
## [2.0.28](https://github.com/academydistrict20/asd20-ui-next/compare/ui-next-v2.0.27...ui-next-v2.0.28) (2026-04-03)
|
|
4
13
|
|
|
5
14
|
|
package/package.json
CHANGED
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
import Asd20BodyAccordion from '../../molecules/Asd20BodyAccordion'
|
|
40
40
|
import Asd20TableauEmbed from '../../molecules/Asd20TableauEmbed'
|
|
41
41
|
import { navigateInternalHref } from '../../../helpers/linkPolicy'
|
|
42
|
+
import { applyRichListColumnExceptions } from '../../../helpers/richBodyListColumns'
|
|
42
43
|
|
|
43
44
|
const BODY_BLOCK_PLACEHOLDER_PATTERN =
|
|
44
45
|
/<div\b(?=[^>]*\bdata-cc-block=(['"])([^'"]+)\1)(?=[^>]*\bdata-block-id=(['"])([^'"]+)\3)[^>]*><\/div>/gi
|
|
@@ -146,9 +147,17 @@ export default {
|
|
|
146
147
|
|
|
147
148
|
mounted() {
|
|
148
149
|
this.hasMounted = true
|
|
150
|
+
this.applyListColumnExceptions()
|
|
151
|
+
},
|
|
152
|
+
|
|
153
|
+
updated() {
|
|
154
|
+
this.applyListColumnExceptions()
|
|
149
155
|
},
|
|
150
156
|
|
|
151
157
|
methods: {
|
|
158
|
+
applyListColumnExceptions() {
|
|
159
|
+
applyRichListColumnExceptions(this.$el)
|
|
160
|
+
},
|
|
152
161
|
onContentClick(event) {
|
|
153
162
|
const anchor = event.target?.closest?.('a')
|
|
154
163
|
|
|
@@ -10,6 +10,20 @@
|
|
|
10
10
|
:icon="icon"
|
|
11
11
|
:column-width="640"
|
|
12
12
|
>
|
|
13
|
+
<template #header>
|
|
14
|
+
<div
|
|
15
|
+
v-if="searchable"
|
|
16
|
+
class="asd20-file-list__toolbar"
|
|
17
|
+
>
|
|
18
|
+
<asd20-search-field
|
|
19
|
+
v-model="searchQuery"
|
|
20
|
+
class="asd20-file-list__search"
|
|
21
|
+
:placeholder="searchPlaceholder"
|
|
22
|
+
:extra="resultSummary"
|
|
23
|
+
:id-tag="searchIdTag"
|
|
24
|
+
/>
|
|
25
|
+
</div>
|
|
26
|
+
</template>
|
|
13
27
|
<div
|
|
14
28
|
v-for="category in categorizedFileItems"
|
|
15
29
|
:key="category.name"
|
|
@@ -22,6 +36,36 @@
|
|
|
22
36
|
v-bind="item"
|
|
23
37
|
/>
|
|
24
38
|
</div>
|
|
39
|
+
<div
|
|
40
|
+
v-if="!categorizedFileItems.length"
|
|
41
|
+
class="asd20-file-list__empty"
|
|
42
|
+
>
|
|
43
|
+
{{ emptyStateMessage }}
|
|
44
|
+
</div>
|
|
45
|
+
<template #footer>
|
|
46
|
+
<div
|
|
47
|
+
v-if="shouldShowFooter"
|
|
48
|
+
class="asd20-file-list__footer"
|
|
49
|
+
>
|
|
50
|
+
<div class="asd20-file-list__footer-summary">
|
|
51
|
+
{{ footerSummary }}
|
|
52
|
+
</div>
|
|
53
|
+
<div class="asd20-file-list__footer-actions">
|
|
54
|
+
<asd20-button
|
|
55
|
+
v-if="canShowMore"
|
|
56
|
+
:label="showMoreLabel"
|
|
57
|
+
text-only
|
|
58
|
+
@click="showMore"
|
|
59
|
+
/>
|
|
60
|
+
<asd20-button
|
|
61
|
+
v-if="canShowAll"
|
|
62
|
+
label="Show all"
|
|
63
|
+
text-only
|
|
64
|
+
@click="showAll"
|
|
65
|
+
/>
|
|
66
|
+
</div>
|
|
67
|
+
</div>
|
|
68
|
+
</template>
|
|
25
69
|
</asd20-list>
|
|
26
70
|
</template>
|
|
27
71
|
|
|
@@ -30,10 +74,25 @@ import Asd20List from '../../../components/organisms/Asd20WidgetList'
|
|
|
30
74
|
import mapFilesToListItems from '../../../helpers/mapFilesToListItems'
|
|
31
75
|
import Asd20ListItem from '../../../components/molecules/Asd20ListItem'
|
|
32
76
|
import Asd20ListCategory from '../../../components/molecules/Asd20ListCategory'
|
|
77
|
+
import Asd20SearchField from '../../../components/molecules/Asd20SearchField'
|
|
78
|
+
|
|
79
|
+
function normalizeSearchText(value = '') {
|
|
80
|
+
return String(value || '')
|
|
81
|
+
.toLowerCase()
|
|
82
|
+
.replace(/\.[a-z0-9]+$/i, '')
|
|
83
|
+
.replace(/[^a-z0-9]+/g, ' ')
|
|
84
|
+
.trim()
|
|
85
|
+
}
|
|
86
|
+
|
|
33
87
|
export default {
|
|
34
88
|
name: 'Asd20FileList',
|
|
35
89
|
|
|
36
|
-
components: {
|
|
90
|
+
components: {
|
|
91
|
+
Asd20List,
|
|
92
|
+
Asd20ListItem,
|
|
93
|
+
Asd20ListCategory,
|
|
94
|
+
Asd20SearchField,
|
|
95
|
+
},
|
|
37
96
|
|
|
38
97
|
props: {
|
|
39
98
|
files: { type: Array, default: () => [] },
|
|
@@ -46,10 +105,16 @@ export default {
|
|
|
46
105
|
groupByTag: { type: Boolean, default: false },
|
|
47
106
|
groupByDate: { type: Boolean, default: false },
|
|
48
107
|
maxHeight: { type: String, default: '320px' },
|
|
108
|
+
searchable: { type: Boolean, default: false },
|
|
109
|
+
searchPlaceholder: { type: String, default: 'Search files' },
|
|
110
|
+
initialVisibleCount: { type: Number, default: 0 },
|
|
111
|
+
visibleCountStep: { type: Number, default: 50 },
|
|
49
112
|
},
|
|
50
113
|
|
|
51
114
|
data: () => ({
|
|
52
115
|
loadedFiles: [],
|
|
116
|
+
searchQuery: '',
|
|
117
|
+
visibleCount: 0,
|
|
53
118
|
}),
|
|
54
119
|
|
|
55
120
|
computed: {
|
|
@@ -57,6 +122,125 @@ export default {
|
|
|
57
122
|
return (this.files || []).concat(this.loadedFiles)
|
|
58
123
|
},
|
|
59
124
|
|
|
125
|
+
normalizedSearchQuery() {
|
|
126
|
+
return normalizeSearchText(this.searchQuery)
|
|
127
|
+
},
|
|
128
|
+
|
|
129
|
+
searchTerms() {
|
|
130
|
+
return this.normalizedSearchQuery
|
|
131
|
+
? this.normalizedSearchQuery.split(/\s+/).filter(Boolean)
|
|
132
|
+
: []
|
|
133
|
+
},
|
|
134
|
+
|
|
135
|
+
filteredFiles() {
|
|
136
|
+
if (!this.searchTerms.length) return this.computedFiles
|
|
137
|
+
|
|
138
|
+
return this.computedFiles.filter(file => this.matchesSearch(file))
|
|
139
|
+
},
|
|
140
|
+
|
|
141
|
+
totalFilesCount() {
|
|
142
|
+
return this.computedFiles.length
|
|
143
|
+
},
|
|
144
|
+
|
|
145
|
+
filteredFilesCount() {
|
|
146
|
+
return this.filteredFiles.length
|
|
147
|
+
},
|
|
148
|
+
|
|
149
|
+
hasActiveSearch() {
|
|
150
|
+
return this.searchTerms.length > 0
|
|
151
|
+
},
|
|
152
|
+
|
|
153
|
+
effectiveVisibleCount() {
|
|
154
|
+
if (!this.initialVisibleCount) return this.filteredFilesCount
|
|
155
|
+
if (!this.visibleCount) return this.initialVisibleCount
|
|
156
|
+
|
|
157
|
+
return this.visibleCount
|
|
158
|
+
},
|
|
159
|
+
|
|
160
|
+
visibleFiles() {
|
|
161
|
+
if (!this.initialVisibleCount) return this.filteredFiles
|
|
162
|
+
|
|
163
|
+
return this.filteredFiles.slice(0, this.effectiveVisibleCount)
|
|
164
|
+
},
|
|
165
|
+
|
|
166
|
+
canShowMore() {
|
|
167
|
+
return (
|
|
168
|
+
!!this.initialVisibleCount &&
|
|
169
|
+
this.visibleFiles.length < this.filteredFilesCount
|
|
170
|
+
)
|
|
171
|
+
},
|
|
172
|
+
|
|
173
|
+
canShowAll() {
|
|
174
|
+
return this.canShowMore && this.filteredFilesCount > this.nextVisibleCount
|
|
175
|
+
},
|
|
176
|
+
|
|
177
|
+
nextVisibleCount() {
|
|
178
|
+
return Math.min(
|
|
179
|
+
this.filteredFilesCount,
|
|
180
|
+
this.effectiveVisibleCount + this.resolvedVisibleCountStep
|
|
181
|
+
)
|
|
182
|
+
},
|
|
183
|
+
|
|
184
|
+
resolvedVisibleCountStep() {
|
|
185
|
+
return this.visibleCountStep > 0
|
|
186
|
+
? this.visibleCountStep
|
|
187
|
+
: this.initialVisibleCount || 50
|
|
188
|
+
},
|
|
189
|
+
|
|
190
|
+
resultSummary() {
|
|
191
|
+
if (!this.searchable) return ''
|
|
192
|
+
if (!this.totalFilesCount) return '0 files'
|
|
193
|
+
if (this.hasActiveSearch) {
|
|
194
|
+
return `${this.filteredFilesCount} of ${this.totalFilesCount}`
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return `${this.totalFilesCount} files`
|
|
198
|
+
},
|
|
199
|
+
|
|
200
|
+
footerSummary() {
|
|
201
|
+
if (!this.totalFilesCount) return ''
|
|
202
|
+
|
|
203
|
+
if (this.canShowMore) {
|
|
204
|
+
return `Showing ${this.visibleFiles.length} of ${this.filteredFilesCount} files`
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
if (this.hasActiveSearch) {
|
|
208
|
+
return `${this.filteredFilesCount} matching files`
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
return `Showing all ${this.filteredFilesCount} files`
|
|
212
|
+
},
|
|
213
|
+
|
|
214
|
+
hasLargeResultSet() {
|
|
215
|
+
return (
|
|
216
|
+
!!this.initialVisibleCount &&
|
|
217
|
+
this.filteredFilesCount > this.initialVisibleCount
|
|
218
|
+
)
|
|
219
|
+
},
|
|
220
|
+
|
|
221
|
+
shouldShowFooter() {
|
|
222
|
+
return (
|
|
223
|
+
this.totalFilesCount > 0 &&
|
|
224
|
+
(this.canShowMore || this.hasActiveSearch || this.hasLargeResultSet)
|
|
225
|
+
)
|
|
226
|
+
},
|
|
227
|
+
|
|
228
|
+
showMoreLabel() {
|
|
229
|
+
const increment = this.nextVisibleCount - this.visibleFiles.length
|
|
230
|
+
return `Show ${increment} more`
|
|
231
|
+
},
|
|
232
|
+
|
|
233
|
+
searchIdTag() {
|
|
234
|
+
return normalizeSearchText(this.title).replace(/\s+/g, '-')
|
|
235
|
+
},
|
|
236
|
+
|
|
237
|
+
emptyStateMessage() {
|
|
238
|
+
if (!this.totalFilesCount) return 'No files available.'
|
|
239
|
+
if (this.hasActiveSearch) return 'No files match your search.'
|
|
240
|
+
|
|
241
|
+
return 'No files available.'
|
|
242
|
+
},
|
|
243
|
+
|
|
60
244
|
categorizedFileItems() {
|
|
61
245
|
if (this.groupByDate) {
|
|
62
246
|
return this.fileItemsGroupedByDate
|
|
@@ -71,7 +255,7 @@ export default {
|
|
|
71
255
|
},
|
|
72
256
|
|
|
73
257
|
fileItemsGroupedByCategory() {
|
|
74
|
-
return this.
|
|
258
|
+
return this.visibleFiles
|
|
75
259
|
.reduce((a, c) => {
|
|
76
260
|
let categories =
|
|
77
261
|
c.categories && c.categories.length > 0
|
|
@@ -87,7 +271,7 @@ export default {
|
|
|
87
271
|
return {
|
|
88
272
|
name: c,
|
|
89
273
|
items: mapFilesToListItems(
|
|
90
|
-
this.
|
|
274
|
+
this.visibleFiles
|
|
91
275
|
.map(f => ({
|
|
92
276
|
...f,
|
|
93
277
|
categories:
|
|
@@ -112,7 +296,7 @@ export default {
|
|
|
112
296
|
},
|
|
113
297
|
|
|
114
298
|
fileItemsGroupedByCategoryDescending() {
|
|
115
|
-
return this.
|
|
299
|
+
return this.visibleFiles
|
|
116
300
|
.reduce((a, c) => {
|
|
117
301
|
let categories =
|
|
118
302
|
c.categories && c.categories.length > 0
|
|
@@ -128,7 +312,7 @@ export default {
|
|
|
128
312
|
return {
|
|
129
313
|
name: c,
|
|
130
314
|
items: mapFilesToListItems(
|
|
131
|
-
this.
|
|
315
|
+
this.visibleFiles
|
|
132
316
|
.map(f => ({
|
|
133
317
|
...f,
|
|
134
318
|
categories:
|
|
@@ -153,7 +337,7 @@ export default {
|
|
|
153
337
|
},
|
|
154
338
|
|
|
155
339
|
fileItemsGroupedByTag() {
|
|
156
|
-
return this.
|
|
340
|
+
return this.visibleFiles
|
|
157
341
|
.reduce((a, t) => {
|
|
158
342
|
let tags = t.tags && t.tags.length > 0 ? t.tags : ['Untagged']
|
|
159
343
|
for (const tag of tags) {
|
|
@@ -166,7 +350,7 @@ export default {
|
|
|
166
350
|
return {
|
|
167
351
|
name: t,
|
|
168
352
|
items: mapFilesToListItems(
|
|
169
|
-
this.
|
|
353
|
+
this.visibleFiles
|
|
170
354
|
.map(f => ({
|
|
171
355
|
...f,
|
|
172
356
|
tags: f.tags && f.tags.length > 0 ? f.tags : ['Untagged'],
|
|
@@ -188,7 +372,7 @@ export default {
|
|
|
188
372
|
},
|
|
189
373
|
|
|
190
374
|
fileItemsGroupedByDate() {
|
|
191
|
-
return this.
|
|
375
|
+
return this.visibleFiles
|
|
192
376
|
.reduce((a, c) => {
|
|
193
377
|
let date = new Date(c.lastModifiedDateTime).toLocaleDateString()
|
|
194
378
|
if (a.indexOf(date) === -1) a.push(date)
|
|
@@ -199,7 +383,7 @@ export default {
|
|
|
199
383
|
name: d,
|
|
200
384
|
unix: new Date(d).valueOf(),
|
|
201
385
|
items: mapFilesToListItems(
|
|
202
|
-
this.
|
|
386
|
+
this.visibleFiles.filter(
|
|
203
387
|
f => new Date(f.lastModifiedDateTime).toLocaleDateString() === d
|
|
204
388
|
)
|
|
205
389
|
)
|
|
@@ -221,7 +405,7 @@ export default {
|
|
|
221
405
|
fileItemsGroupedByOwner() {
|
|
222
406
|
return [
|
|
223
407
|
{
|
|
224
|
-
items: mapFilesToListItems(this.
|
|
408
|
+
items: mapFilesToListItems(this.visibleFiles).map(t => ({
|
|
225
409
|
...t,
|
|
226
410
|
bordered: false,
|
|
227
411
|
alignTop: false,
|
|
@@ -236,6 +420,7 @@ export default {
|
|
|
236
420
|
watch: {
|
|
237
421
|
files: {
|
|
238
422
|
handler() {
|
|
423
|
+
this.resetVisibleCount()
|
|
239
424
|
this.$nextTick(() => {
|
|
240
425
|
// console.log('Change in Files detected:', this.files)
|
|
241
426
|
this.checkForOverflow() // Ensure overflow check happens after file changes
|
|
@@ -245,13 +430,48 @@ export default {
|
|
|
245
430
|
deep: true,
|
|
246
431
|
immediate: true,
|
|
247
432
|
},
|
|
433
|
+
searchQuery() {
|
|
434
|
+
this.resetVisibleCount()
|
|
435
|
+
},
|
|
248
436
|
},
|
|
249
437
|
|
|
250
438
|
mounted() {
|
|
439
|
+
this.resetVisibleCount()
|
|
251
440
|
if (this.url) this.loadFiles()
|
|
252
441
|
},
|
|
253
442
|
|
|
254
443
|
methods: {
|
|
444
|
+
resetVisibleCount() {
|
|
445
|
+
this.visibleCount = this.initialVisibleCount > 0
|
|
446
|
+
? this.initialVisibleCount
|
|
447
|
+
: 0
|
|
448
|
+
},
|
|
449
|
+
showMore() {
|
|
450
|
+
this.visibleCount = this.nextVisibleCount
|
|
451
|
+
},
|
|
452
|
+
showAll() {
|
|
453
|
+
this.visibleCount = this.filteredFilesCount
|
|
454
|
+
},
|
|
455
|
+
getFileSearchTokens(file = {}) {
|
|
456
|
+
return [
|
|
457
|
+
file.name,
|
|
458
|
+
file.filename,
|
|
459
|
+
file.description,
|
|
460
|
+
file.slug,
|
|
461
|
+
file.createdBy,
|
|
462
|
+
file.lastModifiedBy,
|
|
463
|
+
...(Array.isArray(file.categories) ? file.categories : []),
|
|
464
|
+
...(Array.isArray(file.owners) ? file.owners : []),
|
|
465
|
+
...(Array.isArray(file.tags) ? file.tags : []),
|
|
466
|
+
]
|
|
467
|
+
.map(normalizeSearchText)
|
|
468
|
+
.filter(Boolean)
|
|
469
|
+
.join(' ')
|
|
470
|
+
},
|
|
471
|
+
matchesSearch(file) {
|
|
472
|
+
const haystack = this.getFileSearchTokens(file)
|
|
473
|
+
return this.searchTerms.every(term => haystack.includes(term))
|
|
474
|
+
},
|
|
255
475
|
// Expose the checkForOverflow method from the asd20viewport component
|
|
256
476
|
// Expose the handleResize method from the asd20list component
|
|
257
477
|
checkForOverflow() {
|
|
@@ -280,6 +500,33 @@ export default {
|
|
|
280
500
|
<style lang="scss" scoped>
|
|
281
501
|
@use '../../../design/component-stack' as *;
|
|
282
502
|
|
|
503
|
+
.asd20-file-list__toolbar {
|
|
504
|
+
display: flex;
|
|
505
|
+
align-items: center;
|
|
506
|
+
gap: space(0.25);
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
.asd20-file-list__search {
|
|
510
|
+
min-width: min(20rem, 100%);
|
|
511
|
+
margin-left: auto;
|
|
512
|
+
|
|
513
|
+
:deep(.asd20-icon) {
|
|
514
|
+
margin-left: space(0.5);
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
:deep(input) {
|
|
518
|
+
border: 2px solid var(--color__accent);
|
|
519
|
+
border-radius: var(--website-shape__radius-s);
|
|
520
|
+
font-family: var(--website-typography__font-family-headlines);
|
|
521
|
+
font-size: 1rem;
|
|
522
|
+
min-height: 40px;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
:deep(.asd20-search-field__extra) {
|
|
526
|
+
padding: 0 space(0.5) 0 space(0.75);
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
|
|
283
530
|
.asd20-file-list__category-group {
|
|
284
531
|
display: contents;
|
|
285
532
|
}
|
|
@@ -289,4 +536,53 @@ export default {
|
|
|
289
536
|
margin-top: space(0.5);
|
|
290
537
|
}
|
|
291
538
|
}
|
|
539
|
+
|
|
540
|
+
.asd20-file-list__empty {
|
|
541
|
+
width: 100%;
|
|
542
|
+
padding: space(0.75) 0;
|
|
543
|
+
color: var(--color__primary);
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
.asd20-file-list__footer {
|
|
547
|
+
display: flex;
|
|
548
|
+
flex-wrap: wrap;
|
|
549
|
+
align-items: center;
|
|
550
|
+
justify-content: space-between;
|
|
551
|
+
gap: space(0.5);
|
|
552
|
+
padding-top: space(0.75);
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
.asd20-file-list__footer-summary {
|
|
556
|
+
color: var(--color__primary);
|
|
557
|
+
font-size: 0.875rem;
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
.asd20-file-list__footer-actions {
|
|
561
|
+
display: flex;
|
|
562
|
+
flex-wrap: wrap;
|
|
563
|
+
gap: space(0.5);
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
@media (max-width: 767px) {
|
|
567
|
+
.asd20-file-list__toolbar {
|
|
568
|
+
display: block;
|
|
569
|
+
flex-wrap: wrap;
|
|
570
|
+
width: 100%;
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
.asd20-file-list__search {
|
|
574
|
+
min-width: 100%;
|
|
575
|
+
margin-left: 0;
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
@media (min-width: 1024px) {
|
|
580
|
+
.asd20-file-list__search {
|
|
581
|
+
margin: space(0.5) space(0.5);
|
|
582
|
+
|
|
583
|
+
:deep(.asd20-icon) {
|
|
584
|
+
margin-left: 0;
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
}
|
|
292
588
|
</style>
|
|
@@ -8,16 +8,21 @@
|
|
|
8
8
|
v-if="$slots.header || headline"
|
|
9
9
|
class="asd20-list__header"
|
|
10
10
|
>
|
|
11
|
-
<
|
|
12
|
-
v-if="icon"
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
11
|
+
<div
|
|
12
|
+
v-if="icon || headline"
|
|
13
|
+
class="asd20-list__headline-group"
|
|
14
|
+
>
|
|
15
|
+
<asd20-icon
|
|
16
|
+
v-if="icon"
|
|
17
|
+
:name="icon"
|
|
18
|
+
:size="iconSize"
|
|
19
|
+
/>
|
|
20
|
+
<component
|
|
21
|
+
:is="headlineTag"
|
|
22
|
+
class="asd20-list__headline"
|
|
23
|
+
v-html="headline"
|
|
24
|
+
></component>
|
|
25
|
+
</div>
|
|
21
26
|
<slot name="header" />
|
|
22
27
|
</div>
|
|
23
28
|
<asd20-viewport
|
|
@@ -123,7 +128,17 @@ export default {
|
|
|
123
128
|
display: flex;
|
|
124
129
|
flex-direction: row;
|
|
125
130
|
align-items: center;
|
|
131
|
+
justify-content: space-between;
|
|
126
132
|
margin-bottom: space(0.5);
|
|
133
|
+
gap: space(0.5);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.asd20-list__headline-group {
|
|
137
|
+
display: flex;
|
|
138
|
+
flex-direction: row;
|
|
139
|
+
align-items: center;
|
|
140
|
+
min-width: 0;
|
|
141
|
+
|
|
127
142
|
.asd20-icon {
|
|
128
143
|
margin-right: space(0.5);
|
|
129
144
|
--line-color: var(--website-icon__line-color);
|
|
@@ -154,6 +169,18 @@ export default {
|
|
|
154
169
|
}
|
|
155
170
|
}
|
|
156
171
|
|
|
172
|
+
@media (max-width: 767px) {
|
|
173
|
+
.asd20-list__header {
|
|
174
|
+
flex-direction: column;
|
|
175
|
+
justify-content: flex-start;
|
|
176
|
+
align-items: stretch;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.asd20-list__headline-group {
|
|
180
|
+
width: 100%;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
157
184
|
/* @media (min-width: 767px) {*/
|
|
158
185
|
/* .asd20-list--multi-column {*/
|
|
159
186
|
/* &::v-deep .asd20-list-item {*/
|
|
@@ -8,16 +8,21 @@
|
|
|
8
8
|
v-if="$slots.header || headline"
|
|
9
9
|
class="asd20-list__header"
|
|
10
10
|
>
|
|
11
|
-
<
|
|
12
|
-
v-if="icon"
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
11
|
+
<div
|
|
12
|
+
v-if="icon || headline"
|
|
13
|
+
class="asd20-list__headline-group"
|
|
14
|
+
>
|
|
15
|
+
<asd20-icon
|
|
16
|
+
v-if="icon"
|
|
17
|
+
:name="icon"
|
|
18
|
+
:size="iconSize"
|
|
19
|
+
/>
|
|
20
|
+
<component
|
|
21
|
+
:is="headlineTag"
|
|
22
|
+
class="asd20-list__headline"
|
|
23
|
+
v-html="headline"
|
|
24
|
+
></component>
|
|
25
|
+
</div>
|
|
21
26
|
<slot name="header" />
|
|
22
27
|
</div>
|
|
23
28
|
<asd20-viewport
|
|
@@ -128,7 +133,17 @@ export default {
|
|
|
128
133
|
display: flex;
|
|
129
134
|
flex-direction: row;
|
|
130
135
|
align-items: center;
|
|
136
|
+
justify-content: space-between;
|
|
131
137
|
margin-bottom: space(0.5);
|
|
138
|
+
gap: space(0.5);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.asd20-list__headline-group {
|
|
142
|
+
display: flex;
|
|
143
|
+
flex-direction: row;
|
|
144
|
+
align-items: center;
|
|
145
|
+
min-width: 0;
|
|
146
|
+
|
|
132
147
|
.asd20-icon {
|
|
133
148
|
margin-right: space(0.5);
|
|
134
149
|
--line-color: var(--website-icon__line-color);
|
|
@@ -159,6 +174,18 @@ export default {
|
|
|
159
174
|
}
|
|
160
175
|
}
|
|
161
176
|
|
|
177
|
+
@media (max-width: 767px) {
|
|
178
|
+
.asd20-list__header {
|
|
179
|
+
flex-direction: column;
|
|
180
|
+
justify-content: flex-start;
|
|
181
|
+
align-items: stretch;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
.asd20-list__headline-group {
|
|
185
|
+
width: 100%;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
162
189
|
/* @media (min-width: 767px) {*/
|
|
163
190
|
/* .asd20-list--multi-column {*/
|
|
164
191
|
/* &::v-deep .asd20-list-item {*/
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export const SINGLE_COLUMN_RICH_LIST_CLASS = 'asd20-rich-list--single-column'
|
|
2
|
+
export const MULTI_COLUMN_LIST_ITEM_THRESHOLD = 20
|
|
3
|
+
export const SIGNIFICANT_LIST_ITEM_TEXT_THRESHOLD = 120
|
|
4
|
+
|
|
5
|
+
const COMPLEX_DIRECT_CHILD_SELECTOR =
|
|
6
|
+
'ul, ol, dl, blockquote, pre, table, figure, h1, h2, h3, h4, h5, h6'
|
|
7
|
+
|
|
8
|
+
function isDomElement(value) {
|
|
9
|
+
return typeof Element !== 'undefined' && value instanceof Element
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function normalizeTextContent(value) {
|
|
13
|
+
return value.replace(/\s+/g, ' ').trim()
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function isSignificantRichListItem(listItem) {
|
|
17
|
+
if (!isDomElement(listItem)) return false
|
|
18
|
+
|
|
19
|
+
if (listItem.querySelector(COMPLEX_DIRECT_CHILD_SELECTOR)) return true
|
|
20
|
+
if (listItem.children.length > 1) return true
|
|
21
|
+
if (listItem.querySelectorAll('br').length >= 2) return true
|
|
22
|
+
|
|
23
|
+
const textContent = normalizeTextContent(listItem.textContent || '')
|
|
24
|
+
return textContent.length >= SIGNIFICANT_LIST_ITEM_TEXT_THRESHOLD
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function shouldPreventRichListColumns(listElement) {
|
|
28
|
+
if (!isDomElement(listElement)) return false
|
|
29
|
+
|
|
30
|
+
const listItems = Array.from(listElement.children).filter(
|
|
31
|
+
child => child.tagName === 'LI'
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
if (listItems.length < MULTI_COLUMN_LIST_ITEM_THRESHOLD) return false
|
|
35
|
+
|
|
36
|
+
return listItems.some(isSignificantRichListItem)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function applyRichListColumnExceptions(rootElement) {
|
|
40
|
+
if (!isDomElement(rootElement)) return
|
|
41
|
+
|
|
42
|
+
rootElement.querySelectorAll('ul, ol').forEach(list => {
|
|
43
|
+
list.classList.toggle(
|
|
44
|
+
SINGLE_COLUMN_RICH_LIST_CLASS,
|
|
45
|
+
shouldPreventRichListColumns(list)
|
|
46
|
+
)
|
|
47
|
+
})
|
|
48
|
+
}
|