@playpilot/tpi 8.35.0-beta.1 → 8.35.0-beta.2
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/dist/editorial.mount.js +9 -9
- package/dist/link-injections.js +1 -1
- package/dist/mount.js +6 -6
- package/package.json +1 -1
- package/src/lib/data/translations.ts +40 -0
- package/src/lib/fakeData.ts +6 -0
- package/src/lib/types/filter.d.ts +5 -2
- package/src/lib/types/participant.d.ts +1 -1
- package/src/routes/components/Explore/Filter/Filter.svelte +10 -4
- package/src/routes/components/Explore/Filter/FilterSorting.svelte +5 -4
- package/src/routes/components/Explore/Routes/ExploreResults.svelte +12 -7
- package/src/routes/components/GridTitle.svelte +11 -4
- package/src/routes/components/Modals/Modal.svelte +1 -1
- package/src/routes/components/Modals/ParticipantModal.svelte +1 -5
- package/src/routes/components/Participants/Participant.svelte +75 -135
- package/src/tests/routes/components/Participants/Participant.test.js +52 -14
package/package.json
CHANGED
|
@@ -151,6 +151,16 @@ export const translations = {
|
|
|
151
151
|
[Language.Swedish]: 'Visa mindre',
|
|
152
152
|
[Language.Danish]: 'Vis mindre',
|
|
153
153
|
},
|
|
154
|
+
'Read More': {
|
|
155
|
+
[Language.English]: 'Read more',
|
|
156
|
+
[Language.Swedish]: 'Läs mer',
|
|
157
|
+
[Language.Danish]: 'Læs mere',
|
|
158
|
+
},
|
|
159
|
+
'Read Less': {
|
|
160
|
+
[Language.English]: 'Read less',
|
|
161
|
+
[Language.Swedish]: 'Läs mindre',
|
|
162
|
+
[Language.Danish]: 'Læs mindre',
|
|
163
|
+
},
|
|
154
164
|
'Cast': {
|
|
155
165
|
[Language.English]: 'Cast',
|
|
156
166
|
[Language.Swedish]: 'Rollista',
|
|
@@ -358,6 +368,36 @@ export const translations = {
|
|
|
358
368
|
[Language.Swedish]: 'Utforska alla filmer och tv-serier',
|
|
359
369
|
[Language.Danish]: 'Udforsk alle film og tv-serier',
|
|
360
370
|
},
|
|
371
|
+
'Job: all': {
|
|
372
|
+
[Language.English]: 'All',
|
|
373
|
+
[Language.Swedish]: 'Alla',
|
|
374
|
+
[Language.Danish]: 'Alle',
|
|
375
|
+
},
|
|
376
|
+
'Job: actor': {
|
|
377
|
+
[Language.English]: 'Actor',
|
|
378
|
+
[Language.Swedish]: 'Skådespelare',
|
|
379
|
+
[Language.Danish]: 'Skuespiller',
|
|
380
|
+
},
|
|
381
|
+
'Job: producer': {
|
|
382
|
+
[Language.English]: 'Producer',
|
|
383
|
+
[Language.Swedish]: 'Producent',
|
|
384
|
+
[Language.Danish]: 'Producer',
|
|
385
|
+
},
|
|
386
|
+
'Job: executive-producer': {
|
|
387
|
+
[Language.English]: 'Executive Producer',
|
|
388
|
+
[Language.Swedish]: 'Verkställande producent',
|
|
389
|
+
[Language.Danish]: 'Administrerende producer',
|
|
390
|
+
},
|
|
391
|
+
'Job: writer': {
|
|
392
|
+
[Language.English]: 'Writer',
|
|
393
|
+
[Language.Swedish]: 'Manusförfattare',
|
|
394
|
+
[Language.Danish]: 'Manuskriptforfatter',
|
|
395
|
+
},
|
|
396
|
+
'Job: director': {
|
|
397
|
+
[Language.English]: 'Director',
|
|
398
|
+
[Language.Swedish]: 'Regissör',
|
|
399
|
+
[Language.Danish]: 'Instruktør',
|
|
400
|
+
},
|
|
361
401
|
|
|
362
402
|
// Genres
|
|
363
403
|
'All': {
|
package/src/lib/fakeData.ts
CHANGED
|
@@ -54,6 +54,7 @@ export const participants: ParticipantData[] = [
|
|
|
54
54
|
image_uuid: null,
|
|
55
55
|
gender: 'Male',
|
|
56
56
|
character: 'Will Rodman (archive footage) (uncredited)',
|
|
57
|
+
description: 'Some description',
|
|
57
58
|
},
|
|
58
59
|
{
|
|
59
60
|
sid: 'pr8bZm',
|
|
@@ -65,6 +66,7 @@ export const participants: ParticipantData[] = [
|
|
|
65
66
|
image_uuid: null,
|
|
66
67
|
gender: 'Male',
|
|
67
68
|
character: 'Old Man',
|
|
69
|
+
description: 'Some description',
|
|
68
70
|
},
|
|
69
71
|
{
|
|
70
72
|
sid: 'pr45Dp',
|
|
@@ -76,6 +78,7 @@ export const participants: ParticipantData[] = [
|
|
|
76
78
|
image_uuid: null,
|
|
77
79
|
gender: 'Male',
|
|
78
80
|
character: 'Self (archive footage) (uncredited)',
|
|
81
|
+
description: 'Some description',
|
|
79
82
|
},
|
|
80
83
|
{
|
|
81
84
|
sid: 'pr6DnN',
|
|
@@ -87,6 +90,7 @@ export const participants: ParticipantData[] = [
|
|
|
87
90
|
image_uuid: null,
|
|
88
91
|
gender: 'Male',
|
|
89
92
|
character: 'Dreyfus',
|
|
93
|
+
description: 'Some description',
|
|
90
94
|
},
|
|
91
95
|
{
|
|
92
96
|
sid: 'pr7GK8',
|
|
@@ -98,6 +102,7 @@ export const participants: ParticipantData[] = [
|
|
|
98
102
|
image_uuid: null,
|
|
99
103
|
gender: 'Male',
|
|
100
104
|
character: 'Cannon-Gunner',
|
|
105
|
+
description: 'Some description',
|
|
101
106
|
},
|
|
102
107
|
{
|
|
103
108
|
sid: 'pr88KG',
|
|
@@ -109,6 +114,7 @@ export const participants: ParticipantData[] = [
|
|
|
109
114
|
image_uuid: null,
|
|
110
115
|
gender: 'Female',
|
|
111
116
|
character: 'Cornelia',
|
|
117
|
+
description: 'Some description',
|
|
112
118
|
},
|
|
113
119
|
]
|
|
114
120
|
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
import type { Sorting } from '$lib/enums/Sorting'
|
|
2
|
+
|
|
1
3
|
export type ExploreFilterType = 'array' | 'range' | 'string'
|
|
2
|
-
export type ExploreFilterItem = { type: ExploreFilterType
|
|
4
|
+
export type ExploreFilterItem = { type: ExploreFilterType; value: unknown }
|
|
3
5
|
export type ExploreFilter = Record<string, ExploreFilterItem>
|
|
4
|
-
export type ExploreFilterItemArrayValue = { label: string
|
|
6
|
+
export type ExploreFilterItemArrayValue = { label: string; value: string }
|
|
7
|
+
export type ExploreTitleSorting = { label: string; value: (typeof Sorting)[keyof typeof Sorting] }
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export type ParticipantData = {
|
|
2
2
|
sid: string
|
|
3
3
|
name: string
|
|
4
|
+
description: string
|
|
4
5
|
birth_date: string
|
|
5
6
|
death_date: string | null
|
|
6
7
|
jobs: Job[]
|
|
@@ -16,7 +17,6 @@ export type ParticipantData = {
|
|
|
16
17
|
}
|
|
17
18
|
gender: string
|
|
18
19
|
character?: string | null
|
|
19
|
-
bio?: string | null
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
export type Job = 'actor' | 'writer' | 'director'
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import type { ExploreFilter } from '$lib/types/filter'
|
|
2
|
+
import type { ExploreFilter, ExploreTitleSorting } from '$lib/types/filter'
|
|
3
3
|
import genres from '$lib/data/genres.json'
|
|
4
4
|
import { fetchProviders } from '$lib/api/providers'
|
|
5
5
|
import { t } from '$lib/localization'
|
|
@@ -16,7 +16,9 @@
|
|
|
16
16
|
interface Props {
|
|
17
17
|
filter: ExploreFilter
|
|
18
18
|
limit?: boolean
|
|
19
|
+
hideActive?: boolean
|
|
19
20
|
showSorting?: boolean
|
|
21
|
+
sortings?: null | ExploreTitleSorting[]
|
|
20
22
|
searchQuery?: string
|
|
21
23
|
onchange?: () => void
|
|
22
24
|
onempty?: () => void
|
|
@@ -25,7 +27,9 @@
|
|
|
25
27
|
const {
|
|
26
28
|
filter,
|
|
27
29
|
limit = true,
|
|
30
|
+
hideActive = false,
|
|
28
31
|
showSorting = true,
|
|
32
|
+
sortings = null,
|
|
29
33
|
searchQuery = '',
|
|
30
34
|
onchange = () => null,
|
|
31
35
|
onempty = () => null,
|
|
@@ -65,7 +69,7 @@
|
|
|
65
69
|
data: [{ label: t('Movies'), value: 'movie' }, { label: t('Shows'), value: 'series' }, { label: t('Kids'), value: 'kids' }, { label: t('Documentary'), value: 'documentary' }],
|
|
66
70
|
}]
|
|
67
71
|
|
|
68
|
-
let limited = $
|
|
72
|
+
let limited = $derived(limit)
|
|
69
73
|
let wasPreviouslyActive = false
|
|
70
74
|
|
|
71
75
|
$effect(() => {
|
|
@@ -104,13 +108,15 @@
|
|
|
104
108
|
|
|
105
109
|
{#if showSorting}
|
|
106
110
|
<div class="sorting" transition:fly={{ x: 5, duration: 100 }}>
|
|
107
|
-
<FilterSorting {filter} {onchange} />
|
|
111
|
+
<FilterSorting {filter} {onchange} {sortings} />
|
|
108
112
|
</div>
|
|
109
113
|
{/if}
|
|
110
114
|
</div>
|
|
111
115
|
</div>
|
|
112
116
|
|
|
113
|
-
|
|
117
|
+
{#if !hideActive}
|
|
118
|
+
<ActiveFilterItems {filter} {items} />
|
|
119
|
+
{/if}
|
|
114
120
|
|
|
115
121
|
<style lang="scss">
|
|
116
122
|
.filter {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import Button from '../../Button.svelte'
|
|
3
3
|
import IconArrow from '../../Icons/IconArrow.svelte'
|
|
4
|
-
import type { ExploreFilter } from '$lib/types/filter'
|
|
4
|
+
import type { ExploreFilter, ExploreTitleSorting } from '$lib/types/filter'
|
|
5
5
|
import { t } from '$lib/localization'
|
|
6
6
|
import Dropdown from './Dropdown.svelte'
|
|
7
7
|
import { Sorting } from '$lib/enums/Sorting'
|
|
@@ -9,17 +9,18 @@
|
|
|
9
9
|
interface Props {
|
|
10
10
|
filter: ExploreFilter
|
|
11
11
|
onchange?: () => void
|
|
12
|
+
sortings?: null | ExploreTitleSorting[]
|
|
12
13
|
}
|
|
13
14
|
|
|
14
|
-
const { filter, onchange = () => null }: Props = $props()
|
|
15
|
+
const { filter, onchange = () => null, sortings = null }: Props = $props()
|
|
15
16
|
|
|
16
17
|
const param = 'ordering'
|
|
17
18
|
|
|
18
|
-
const options = [
|
|
19
|
+
const options = $derived(sortings || [
|
|
19
20
|
{ label: 'Popularity', value: Sorting.Popular },
|
|
20
21
|
{ label: 'New', value: Sorting.New },
|
|
21
22
|
{ label: 'Top Rated', value: Sorting.Best },
|
|
22
|
-
]
|
|
23
|
+
])
|
|
23
24
|
|
|
24
25
|
const label = $derived(options.find(({ value }) => value === filter[param]?.value)?.label || 'Sort By')
|
|
25
26
|
|
|
@@ -21,9 +21,11 @@
|
|
|
21
21
|
searchQuery?: string,
|
|
22
22
|
filter?: ExploreFilter
|
|
23
23
|
forceGrid?: boolean
|
|
24
|
+
hidePlaylinks?: boolean
|
|
25
|
+
onTitleClick?: null | ((event: MouseEvent, titles: TitleData[], index: number) => void)
|
|
24
26
|
}
|
|
25
27
|
|
|
26
|
-
const { searchQuery = '', filter = {}, forceGrid = false }: Props = $props()
|
|
28
|
+
const { searchQuery = '', filter = {}, forceGrid = false, hidePlaylinks = false, onTitleClick = null }: Props = $props()
|
|
27
29
|
|
|
28
30
|
// svelte-ignore non_reactive_update
|
|
29
31
|
let page = 1
|
|
@@ -53,9 +55,7 @@
|
|
|
53
55
|
if (filter) setFilter()
|
|
54
56
|
})
|
|
55
57
|
|
|
56
|
-
onDestroy(
|
|
57
|
-
emptyFilter()
|
|
58
|
-
})
|
|
58
|
+
onDestroy(emptyFilter)
|
|
59
59
|
|
|
60
60
|
async function getTitlesForFilter(): Promise<APIPaginatedResult<TitleData>> {
|
|
61
61
|
latestRequestId += 1
|
|
@@ -132,7 +132,12 @@
|
|
|
132
132
|
track(TrackingEvent.ExploreShowMore, null, { page })
|
|
133
133
|
}
|
|
134
134
|
|
|
135
|
-
function openTitle(event: MouseEvent, title: TitleData): void {
|
|
135
|
+
function openTitle(event: MouseEvent, title: TitleData, index: number): void {
|
|
136
|
+
if (onTitleClick) {
|
|
137
|
+
onTitleClick(event, titles, index)
|
|
138
|
+
return
|
|
139
|
+
}
|
|
140
|
+
|
|
136
141
|
openModal({ event, data: title })
|
|
137
142
|
track(TrackingEvent.ExploreTitleClick, title)
|
|
138
143
|
}
|
|
@@ -147,9 +152,9 @@
|
|
|
147
152
|
</script>
|
|
148
153
|
|
|
149
154
|
<div class="titles" class:grid role="main" style:--grid-columns={gridColumns} bind:clientWidth={width} data-testid="explore-results">
|
|
150
|
-
{#each titles as title}
|
|
155
|
+
{#each titles as title, index}
|
|
151
156
|
{#key title.sid}
|
|
152
|
-
<TitleComponent {title} onclick={(event: MouseEvent) => openTitle(event, title)} />
|
|
157
|
+
<TitleComponent {title} {hidePlaylinks} onclick={(event: MouseEvent) => openTitle(event, title, index)} />
|
|
153
158
|
{/key}
|
|
154
159
|
{/each}
|
|
155
160
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { TitleData } from '$lib/types/title'
|
|
3
|
+
import { getContext } from 'svelte'
|
|
3
4
|
import IconIMDb from './Icons/IconIMDb.svelte'
|
|
4
5
|
import PlaylinksCompact from './Playlinks/PlaylinksCompact.svelte'
|
|
5
6
|
import TitlePoster from './TitlePoster.svelte'
|
|
@@ -7,9 +8,10 @@
|
|
|
7
8
|
interface Props {
|
|
8
9
|
title: TitleData
|
|
9
10
|
onclick?: (event: MouseEvent) => void
|
|
11
|
+
hidePlaylinks?: boolean
|
|
10
12
|
}
|
|
11
13
|
|
|
12
|
-
const { title, onclick = () => null }: Props = $props()
|
|
14
|
+
const { title, onclick = () => null, hidePlaylinks = false }: Props = $props()
|
|
13
15
|
</script>
|
|
14
16
|
|
|
15
17
|
<button class="title" {onclick} data-testid="title">
|
|
@@ -33,9 +35,11 @@
|
|
|
33
35
|
</div>
|
|
34
36
|
|
|
35
37
|
<div class="content">
|
|
36
|
-
<div class="heading">{title.title}</div>
|
|
38
|
+
<div class="heading" class:margin={!hidePlaylinks}>{title.title}</div>
|
|
37
39
|
|
|
38
|
-
|
|
40
|
+
{#if !hidePlaylinks}
|
|
41
|
+
<PlaylinksCompact playlinks={title.providers} size={20} />
|
|
42
|
+
{/if}
|
|
39
43
|
</div>
|
|
40
44
|
</button>
|
|
41
45
|
|
|
@@ -81,7 +85,6 @@
|
|
|
81
85
|
}
|
|
82
86
|
|
|
83
87
|
.heading {
|
|
84
|
-
margin-bottom: margin(0.5);
|
|
85
88
|
overflow: hidden;
|
|
86
89
|
text-overflow: ellipsis;
|
|
87
90
|
white-space: nowrap;
|
|
@@ -96,6 +99,10 @@
|
|
|
96
99
|
color: theme(grid-item-title-hover-text-color, text-color);
|
|
97
100
|
text-decoration: theme(grid-item-title-hover-text-decoration, none);
|
|
98
101
|
}
|
|
102
|
+
|
|
103
|
+
&.margin {
|
|
104
|
+
margin-bottom: margin(0.5);
|
|
105
|
+
}
|
|
99
106
|
}
|
|
100
107
|
|
|
101
108
|
.meta {
|
|
@@ -14,8 +14,6 @@
|
|
|
14
14
|
|
|
15
15
|
const { participant, initialScrollPosition = 0, ...restProps }: Props = $props()
|
|
16
16
|
|
|
17
|
-
let windowWidth = $state(0)
|
|
18
|
-
|
|
19
17
|
track(TrackingEvent.ParticipantModalView, null, { participant: participant.name })
|
|
20
18
|
|
|
21
19
|
onMount(() => {
|
|
@@ -25,8 +23,6 @@
|
|
|
25
23
|
})
|
|
26
24
|
</script>
|
|
27
25
|
|
|
28
|
-
<
|
|
29
|
-
|
|
30
|
-
<Modal {initialScrollPosition} {...restProps} closeButtonStyle="flat" tall>
|
|
26
|
+
<Modal {initialScrollPosition} {...restProps} closeButtonStyle="flat" tall wide blur>
|
|
31
27
|
<Participant {participant} />
|
|
32
28
|
</Modal>
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import { onMount } from 'svelte'
|
|
3
2
|
import { heading } from '$lib/actions/heading'
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import type { ParticipantData } from '$lib/types/participant'
|
|
3
|
+
import type { Job, ParticipantData } from '$lib/types/participant'
|
|
4
|
+
import type { ExploreFilter, ExploreTitleSorting } from '$lib/types/filter'
|
|
7
5
|
import type { TitleData } from '$lib/types/title'
|
|
8
6
|
import { Sorting } from '$lib/enums/Sorting'
|
|
9
7
|
import { t } from '$lib/localization'
|
|
@@ -11,66 +9,40 @@
|
|
|
11
9
|
import { trackViaPixel } from '@playpilot/retargeting-tracking'
|
|
12
10
|
import { MetaEvent } from '$lib/enums/TrackingEvent'
|
|
13
11
|
import ParticipantImage from './ParticipantImage.svelte'
|
|
14
|
-
import
|
|
15
|
-
import
|
|
12
|
+
import ExploreResults from '../Explore/Routes/ExploreResults.svelte'
|
|
13
|
+
import Filter from '../Explore/Filter/Filter.svelte'
|
|
16
14
|
import Button from '../Button.svelte'
|
|
15
|
+
import { openModal } from '$lib/modal'
|
|
17
16
|
|
|
18
17
|
interface Props {
|
|
19
18
|
participant: ParticipantData
|
|
20
19
|
small?: boolean
|
|
21
20
|
}
|
|
22
21
|
|
|
23
|
-
type TitleSorting = { label: string; value: (typeof Sorting)[keyof typeof Sorting] }
|
|
24
|
-
|
|
25
22
|
const { participant, small = false }: Props = $props()
|
|
26
23
|
|
|
27
|
-
const { name,
|
|
24
|
+
const { name, description } = $derived(participant)
|
|
28
25
|
|
|
29
|
-
const
|
|
26
|
+
const filter: ExploreFilter = $state({})
|
|
27
|
+
const sortings: ExploreTitleSorting[] = [
|
|
30
28
|
{ label: 'Popularity', value: Sorting.Popular },
|
|
31
29
|
{ label: 'Top Rated', value: Sorting.Best },
|
|
32
30
|
{ label: 'Year', value: Sorting.Chronological },
|
|
33
31
|
]
|
|
34
32
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
let titles: TitleData[] = $state([])
|
|
38
|
-
let page = $state(1)
|
|
39
|
-
let hasMorePages = $state(true)
|
|
40
|
-
let loading = $state(true)
|
|
41
|
-
let currentSorting = $state(sortings[0])
|
|
33
|
+
let currentJob: 'all' | Job = $state('all')
|
|
34
|
+
let descriptionExpanded: boolean = $state(false)
|
|
42
35
|
|
|
43
|
-
|
|
36
|
+
const filterWithParticipant: ExploreFilter = $derived({
|
|
37
|
+
...filter,
|
|
38
|
+
participant_sid: { type: 'string', value: participant.sid },
|
|
39
|
+
participant_job: { type: 'string', value: currentJob === 'all' ? null : currentJob }
|
|
40
|
+
})
|
|
44
41
|
|
|
45
42
|
if (isRetargetingAllowed()) trackViaPixel(MetaEvent.ParticipantView, { participant: participant.name })
|
|
46
43
|
|
|
47
|
-
function
|
|
48
|
-
|
|
49
|
-
return date.toLocaleDateString(undefined, { year: 'numeric', month: 'long', day: 'numeric' })
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
async function loadMore(): Promise<void> {
|
|
53
|
-
loading = true
|
|
54
|
-
|
|
55
|
-
try {
|
|
56
|
-
const results = await fetchTitlesForParticipant(participant, { page, sorting: currentSorting.value })
|
|
57
|
-
|
|
58
|
-
titles = [...titles, ...results]
|
|
59
|
-
hasMorePages = results?.length >= pageSize
|
|
60
|
-
} catch {
|
|
61
|
-
hasMorePages = false
|
|
62
|
-
} finally {
|
|
63
|
-
loading = false
|
|
64
|
-
page += 1
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
function setSorting(sorting: TitleSorting): void {
|
|
69
|
-
currentSorting = sorting
|
|
70
|
-
titles = []
|
|
71
|
-
page = 1
|
|
72
|
-
|
|
73
|
-
loadMore()
|
|
44
|
+
function onTitleClick(event: MouseEvent, titles: TitleData[], index: number): void {
|
|
45
|
+
openModal({ event, type: 'titles-rail', data: titles, props: { initialIndex: index } })
|
|
74
46
|
}
|
|
75
47
|
</script>
|
|
76
48
|
|
|
@@ -80,60 +52,46 @@
|
|
|
80
52
|
<div>
|
|
81
53
|
<div class="heading" use:heading={2} id="heading">{name}</div>
|
|
82
54
|
|
|
83
|
-
{#if
|
|
84
|
-
<p class="
|
|
85
|
-
{
|
|
55
|
+
{#if description}
|
|
56
|
+
<p class="description" class:expanded={descriptionExpanded}>
|
|
57
|
+
{description}
|
|
86
58
|
</p>
|
|
59
|
+
|
|
60
|
+
<div class="read-more">
|
|
61
|
+
<Button variant="link" onclick={() => descriptionExpanded = !descriptionExpanded}>
|
|
62
|
+
{descriptionExpanded ? t('Read Less') : t('Read More')}
|
|
63
|
+
</Button>
|
|
64
|
+
</div>
|
|
87
65
|
{/if}
|
|
88
66
|
</div>
|
|
89
67
|
</div>
|
|
90
68
|
|
|
91
|
-
<div class="content">
|
|
92
|
-
{#if !small
|
|
69
|
+
<div class="content" class:small>
|
|
70
|
+
{#if !small}
|
|
93
71
|
<div class="list-header">
|
|
94
72
|
<div class="heading subheading" use:heading={3} id="credits">{t('Credits')}</div>
|
|
73
|
+
</div>
|
|
95
74
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
{/snippet}
|
|
103
|
-
|
|
104
|
-
{#snippet content()}
|
|
105
|
-
<div class="sortings">
|
|
106
|
-
{#each sortings as sorting}
|
|
107
|
-
<Button variant="link" onclick={() => setSorting(sorting)}>{t(sorting.label)}</Button>
|
|
108
|
-
{/each}
|
|
109
|
-
</div>
|
|
110
|
-
{/snippet}
|
|
111
|
-
</Dropdown>
|
|
112
|
-
</div>
|
|
75
|
+
<div class="jobs">
|
|
76
|
+
{#each ['all', ...participant.jobs] as job}
|
|
77
|
+
<Button variant="border" size="large" active={currentJob === job} onclick={() => currentJob = job as 'all' | Job}>
|
|
78
|
+
{t('Job: ' + job)}
|
|
79
|
+
</Button>
|
|
80
|
+
{/each}
|
|
113
81
|
</div>
|
|
114
|
-
{/if}
|
|
115
82
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
<ListTitle {title} compact={small} onclick={(event) => openModal({ event, data: title })} />
|
|
119
|
-
{/each}
|
|
83
|
+
<Filter {filter} {sortings} hideActive />
|
|
84
|
+
{/if}
|
|
120
85
|
|
|
121
|
-
|
|
122
|
-
{#each { length: 6 }}
|
|
123
|
-
<div class="skeleton" data-testid="skeleton"></div>
|
|
124
|
-
{/each}
|
|
125
|
-
{:else if hasMorePages}
|
|
126
|
-
<button class="more" onclick={loadMore}>{t('Show More')}</button>
|
|
127
|
-
{/if}
|
|
128
|
-
</div>
|
|
86
|
+
<ExploreResults forceGrid hidePlaylinks filter={filterWithParticipant} {onTitleClick} />
|
|
129
87
|
</div>
|
|
130
88
|
|
|
131
89
|
<style lang="scss">
|
|
132
90
|
.header {
|
|
133
|
-
--participant-image-size: #{margin(
|
|
91
|
+
--participant-image-size: #{margin(5)};
|
|
134
92
|
display: grid;
|
|
135
|
-
grid-template-columns: calc(var(--participant-image-size))
|
|
136
|
-
align-items:
|
|
93
|
+
grid-template-columns: var(--participant-image-size) calc(100% - var(--participant-image-size) - margin(1));
|
|
94
|
+
align-items: start;
|
|
137
95
|
gap: margin(1);
|
|
138
96
|
padding: margin(3) margin(1) margin(2);
|
|
139
97
|
font-family: theme(detail-font-family, font-family);
|
|
@@ -144,11 +102,13 @@
|
|
|
144
102
|
|
|
145
103
|
@include desktop {
|
|
146
104
|
--participant-image-size: #{margin(8)};
|
|
105
|
+
padding: margin(3) margin(2) margin(2);
|
|
147
106
|
}
|
|
148
107
|
|
|
149
108
|
&.small {
|
|
150
109
|
--participant-image-size: #{margin(6)};
|
|
151
|
-
padding: margin(1);
|
|
110
|
+
padding: margin(1) margin(1) 0;
|
|
111
|
+
align-items: center;
|
|
152
112
|
}
|
|
153
113
|
}
|
|
154
114
|
|
|
@@ -161,19 +121,14 @@
|
|
|
161
121
|
font-style: theme(detail-title-font-style, normal);
|
|
162
122
|
|
|
163
123
|
&.subheading {
|
|
164
|
-
margin: 0;
|
|
165
124
|
font-size: theme(detail-title-small-font-size, margin(1.25));
|
|
166
125
|
}
|
|
167
126
|
|
|
168
127
|
.small & {
|
|
169
|
-
font-size:
|
|
128
|
+
font-size: 1.25em;
|
|
170
129
|
}
|
|
171
130
|
}
|
|
172
131
|
|
|
173
|
-
.dates {
|
|
174
|
-
margin: margin(0.5) 0 0;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
132
|
.content {
|
|
178
133
|
padding: 0 margin(1) margin(1);
|
|
179
134
|
color: theme(detail-text-color, text-color);
|
|
@@ -183,16 +138,38 @@
|
|
|
183
138
|
line-height: normal;
|
|
184
139
|
font-style: normal;
|
|
185
140
|
|
|
141
|
+
@include desktop {
|
|
142
|
+
padding: 0 margin(2) margin(2);
|
|
143
|
+
|
|
144
|
+
&.small {
|
|
145
|
+
padding: 0 margin(1) margin(1);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
186
149
|
::view-transition-old(content),
|
|
187
150
|
::view-transition-new(content) {
|
|
188
151
|
height: 100%;
|
|
189
152
|
}
|
|
190
153
|
}
|
|
191
154
|
|
|
192
|
-
.
|
|
193
|
-
display:
|
|
194
|
-
|
|
195
|
-
|
|
155
|
+
.description {
|
|
156
|
+
display: -webkit-box;
|
|
157
|
+
-webkit-box-orient: vertical;
|
|
158
|
+
margin: margin(0.5) 0 0;
|
|
159
|
+
overflow: hidden;
|
|
160
|
+
-webkit-line-clamp: 3;
|
|
161
|
+
line-clamp: 3;
|
|
162
|
+
color: theme(text-color-alt);
|
|
163
|
+
|
|
164
|
+
&.expanded {
|
|
165
|
+
display: block;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.read-more {
|
|
170
|
+
:global(.button) {
|
|
171
|
+
font-weight: bold;
|
|
172
|
+
}
|
|
196
173
|
}
|
|
197
174
|
|
|
198
175
|
.list-header {
|
|
@@ -202,47 +179,10 @@
|
|
|
202
179
|
margin-bottom: margin(0.5);
|
|
203
180
|
}
|
|
204
181
|
|
|
205
|
-
.
|
|
206
|
-
min-height: margin(7.25);
|
|
207
|
-
border-radius: theme(playlink-border-radius, border-radius);
|
|
208
|
-
background: theme(detail-background-light, lighter);
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
.more {
|
|
212
|
-
cursor: pointer;
|
|
213
|
-
appearance: none;
|
|
214
|
-
padding: margin(0.5) margin(1);
|
|
215
|
-
border: 0;
|
|
216
|
-
border-radius: theme(participants-load-more-border-radius, border-radius);
|
|
217
|
-
background: theme(participants-load-more-background, content);
|
|
218
|
-
color: inherit;
|
|
219
|
-
font-size: inherit;
|
|
220
|
-
font-family: inherit;
|
|
221
|
-
|
|
222
|
-
&:hover {
|
|
223
|
-
filter: brightness(1.2);
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
.sort {
|
|
182
|
+
.jobs {
|
|
228
183
|
display: flex;
|
|
229
|
-
|
|
230
|
-
gap: margin(0.
|
|
231
|
-
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
.sortings {
|
|
235
|
-
:global(.button) {
|
|
236
|
-
display: block;
|
|
237
|
-
width: 100%;
|
|
238
|
-
padding: margin(0.5) margin(1);
|
|
239
|
-
text-align: left;
|
|
240
|
-
white-space: nowrap;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
:global(.button:hover) {
|
|
244
|
-
background: theme(content-light);
|
|
245
|
-
border-radius: 0;
|
|
246
|
-
}
|
|
184
|
+
flex-wrap: wrap;
|
|
185
|
+
gap: margin(0.5);
|
|
186
|
+
margin-bottom: margin(0.5);
|
|
247
187
|
}
|
|
248
188
|
</style>
|