@playpilot/tpi 8.23.0-beta.3 → 8.23.0-beta.5
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 +10 -10
- package/dist/link-injections.js +1 -1
- package/dist/mount.js +7 -7
- package/package.json +2 -2
- package/src/lib/data/translations.ts +10 -0
- package/src/routes/components/Description.svelte +12 -4
- package/src/routes/components/Modals/ModalCloseOverlay.svelte +1 -2
- package/src/routes/components/Modals/RailModal.svelte +3 -2
- package/src/routes/components/Modals/TitlesReelModal.svelte +7 -2
- package/src/routes/components/Playlinks/PlaylinksCompact.svelte +23 -6
- package/src/routes/components/Rails/ParticipantsRail.svelte +4 -3
- package/src/tests/routes/components/Description.test.js +9 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@playpilot/tpi",
|
|
3
|
-
"version": "8.23.0-beta.
|
|
3
|
+
"version": "8.23.0-beta.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"dev": "vite dev",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"svelte": "5.55.7",
|
|
39
39
|
"svelte-check": "^4.6.0",
|
|
40
40
|
"svelte-preprocess": "^6.0.5",
|
|
41
|
-
"svelte-tiny-slider": "^2.8.
|
|
41
|
+
"svelte-tiny-slider": "^2.8.1",
|
|
42
42
|
"typescript": "^6.0.3",
|
|
43
43
|
"typescript-eslint": "^8.62.0",
|
|
44
44
|
"vite": "^5.4.21",
|
|
@@ -146,6 +146,11 @@ export const translations = {
|
|
|
146
146
|
[Language.Swedish]: 'Visa mer',
|
|
147
147
|
[Language.Danish]: 'Vis mere',
|
|
148
148
|
},
|
|
149
|
+
'Show Less': {
|
|
150
|
+
[Language.English]: 'Show less',
|
|
151
|
+
[Language.Swedish]: 'Visa mindre',
|
|
152
|
+
[Language.Danish]: 'Vis mindre',
|
|
153
|
+
},
|
|
149
154
|
'Cast': {
|
|
150
155
|
[Language.English]: 'Cast',
|
|
151
156
|
[Language.Swedish]: 'Rollista',
|
|
@@ -333,6 +338,11 @@ export const translations = {
|
|
|
333
338
|
[Language.Swedish]: 'Snart på Bio',
|
|
334
339
|
[Language.Danish]: 'Kommende film',
|
|
335
340
|
},
|
|
341
|
+
'Explore All Movies And Shows': {
|
|
342
|
+
[Language.English]: 'Explore all movies and TV-shows',
|
|
343
|
+
[Language.Swedish]: 'Utforska alla filmer och TV-serier',
|
|
344
|
+
[Language.Danish]: 'Udforsk alle film og tv-serier',
|
|
345
|
+
},
|
|
336
346
|
|
|
337
347
|
// Genres
|
|
338
348
|
'All': {
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { t } from '$lib/localization'
|
|
3
|
+
|
|
2
4
|
interface Props {
|
|
3
5
|
text: string
|
|
4
6
|
blurb?: string
|
|
@@ -12,8 +14,8 @@
|
|
|
12
14
|
|
|
13
15
|
const limitedText = $derived(text.slice(0, limit))
|
|
14
16
|
|
|
15
|
-
function
|
|
16
|
-
expanded =
|
|
17
|
+
function toggle(): void {
|
|
18
|
+
expanded = !expanded
|
|
17
19
|
onclick()
|
|
18
20
|
}
|
|
19
21
|
</script>
|
|
@@ -23,7 +25,7 @@
|
|
|
23
25
|
{expanded ? text : limitedText}{#if !expanded && text.length > limit}...{/if}
|
|
24
26
|
|
|
25
27
|
{#if !expanded && (text.length > limit || blurb)}
|
|
26
|
-
<button class="
|
|
28
|
+
<button class="toggle" onclick={toggle}>{t('Show More')}</button>
|
|
27
29
|
{/if}
|
|
28
30
|
</span>
|
|
29
31
|
|
|
@@ -32,10 +34,16 @@
|
|
|
32
34
|
{/if}
|
|
33
35
|
</div>
|
|
34
36
|
|
|
37
|
+
{#if expanded}
|
|
38
|
+
<button class="toggle" onclick={toggle}>{t('Show Less')}</button>
|
|
39
|
+
{/if}
|
|
40
|
+
|
|
35
41
|
<style lang="scss">
|
|
36
42
|
.description:first-child {
|
|
37
43
|
margin: margin(-1) 0 margin(1);
|
|
38
44
|
max-width: theme(description-max-width, 100%);
|
|
45
|
+
max-height: theme(description-max-height, 100vh);
|
|
46
|
+
overflow: auto;
|
|
39
47
|
}
|
|
40
48
|
|
|
41
49
|
.paragraph {
|
|
@@ -44,7 +52,7 @@
|
|
|
44
52
|
font-family: theme(description-font-family, font-family);
|
|
45
53
|
}
|
|
46
54
|
|
|
47
|
-
.
|
|
55
|
+
.toggle {
|
|
48
56
|
display: inline;
|
|
49
57
|
appearance: none;
|
|
50
58
|
padding: 0;
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { onMount, type Snippet } from 'svelte'
|
|
3
3
|
import TinySlider from 'svelte-tiny-slider'
|
|
4
4
|
import { fade } from 'svelte/transition'
|
|
5
|
+
import { t } from '$lib/localization'
|
|
5
6
|
import Modal from './Modal.svelte'
|
|
6
7
|
import IconArrow from '../Icons/IconArrow.svelte'
|
|
7
8
|
import ModalCloseOverlay from './ModalCloseOverlay.svelte'
|
|
@@ -74,7 +75,7 @@
|
|
|
74
75
|
</div>
|
|
75
76
|
|
|
76
77
|
<div class="close">
|
|
77
|
-
<ModalCloseOverlay {onclose} label={window.location.href.includes('route=modal') ? '
|
|
78
|
+
<ModalCloseOverlay {onclose} label={window.location.href.includes('route=modal') ? t('Explore All Movies And Shows') : ''} />
|
|
78
79
|
</div>
|
|
79
80
|
{/snippet}
|
|
80
81
|
</Modal>
|
|
@@ -209,6 +210,6 @@
|
|
|
209
210
|
}
|
|
210
211
|
|
|
211
212
|
.close {
|
|
212
|
-
--modal-close-overlay-left: calc((100vw - $size) / 2)
|
|
213
|
+
--modal-close-overlay-left: calc((100vw - #{$size}) / 2);
|
|
213
214
|
}
|
|
214
215
|
</style>
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
import PlaylinksCompact from '../Playlinks/PlaylinksCompact.svelte'
|
|
12
12
|
import PlaylinksDisclaimer from '../Playlinks/PlaylinksDisclaimer.svelte'
|
|
13
13
|
import ModalCloseOverlay from './ModalCloseOverlay.svelte'
|
|
14
|
+
import ParticipantsRail from '../Rails/ParticipantsRail.svelte'
|
|
14
15
|
|
|
15
16
|
interface Props {
|
|
16
17
|
titles: TitleData[],
|
|
@@ -65,6 +66,8 @@
|
|
|
65
66
|
<div class="details">
|
|
66
67
|
<Description text={title.description!} blurb={title.blurb} limit={80} />
|
|
67
68
|
|
|
69
|
+
<ParticipantsRail {title} heading="" />
|
|
70
|
+
|
|
68
71
|
<div class="playlinks-heading" use:heading={3}>{t('Where To Stream Online')}</div>
|
|
69
72
|
|
|
70
73
|
<PlaylinksCompact playlinks={title.providers} size={24} />
|
|
@@ -83,7 +86,7 @@
|
|
|
83
86
|
</TinySlider>
|
|
84
87
|
</div>
|
|
85
88
|
|
|
86
|
-
<ModalCloseOverlay label=
|
|
89
|
+
<ModalCloseOverlay label={t('Explore All Movies And Shows')} />
|
|
87
90
|
{/snippet}
|
|
88
91
|
</Modal>
|
|
89
92
|
</div>
|
|
@@ -97,6 +100,7 @@
|
|
|
97
100
|
--playpilot-detail-background-border-radius: 0;
|
|
98
101
|
--playpilot-detail-background-width: 400%;
|
|
99
102
|
--playpilot-detail-backdrop: rgba(0, 0, 0, 0.85);
|
|
103
|
+
--playpilot-description-max-height: 40dvh;
|
|
100
104
|
|
|
101
105
|
:global(*) {
|
|
102
106
|
box-sizing: border-box;
|
|
@@ -127,6 +131,7 @@
|
|
|
127
131
|
}
|
|
128
132
|
|
|
129
133
|
.content {
|
|
134
|
+
--rail-margin: #{margin(2)};
|
|
130
135
|
position: relative;
|
|
131
136
|
display: flex;
|
|
132
137
|
flex-direction: column;
|
|
@@ -166,7 +171,7 @@
|
|
|
166
171
|
}
|
|
167
172
|
|
|
168
173
|
.playlinks-heading {
|
|
169
|
-
margin: margin(0.5)
|
|
174
|
+
margin: margin(1) 0 margin(0.5);
|
|
170
175
|
color: theme(reel-playlinks-title-color, text-color-alt);
|
|
171
176
|
font-family: theme(reel-playlinks-title-font-family, inherit);
|
|
172
177
|
font-weight: theme(reel-playlinks-title-font-weight, lighter);
|
|
@@ -10,11 +10,18 @@
|
|
|
10
10
|
|
|
11
11
|
const { playlinks, size = 30 }: Props = $props()
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
let limit = $state(3)
|
|
14
|
+
|
|
15
|
+
const mergedPlaylinks = mergePlaylinks(playlinks)
|
|
16
|
+
const limitedPlaylinks = $derived(mergedPlaylinks.slice(0, limit))
|
|
14
17
|
|
|
15
18
|
function onPlaylinkClick(event: MouseEvent): void {
|
|
16
19
|
event.stopPropagation()
|
|
17
20
|
}
|
|
21
|
+
|
|
22
|
+
function expand(): void {
|
|
23
|
+
limit = mergedPlaylinks.length
|
|
24
|
+
}
|
|
18
25
|
</script>
|
|
19
26
|
|
|
20
27
|
<div class="playlinks">
|
|
@@ -22,13 +29,13 @@
|
|
|
22
29
|
<PlaylinkIcon {playlink} onclick={onPlaylinkClick} {size} />
|
|
23
30
|
{/each}
|
|
24
31
|
|
|
25
|
-
{#if
|
|
26
|
-
<
|
|
27
|
-
+{
|
|
28
|
-
</
|
|
32
|
+
{#if mergedPlaylinks.length > limit}
|
|
33
|
+
<button class="button more" onclick={expand}>
|
|
34
|
+
+{mergedPlaylinks.length - limit}
|
|
35
|
+
</button>
|
|
29
36
|
{/if}
|
|
30
37
|
|
|
31
|
-
{#if !
|
|
38
|
+
{#if !mergedPlaylinks.length}
|
|
32
39
|
<div class="empty" data-testid="playlinks-empty">
|
|
33
40
|
Unavailable to stream
|
|
34
41
|
</div>
|
|
@@ -44,15 +51,25 @@
|
|
|
44
51
|
}
|
|
45
52
|
|
|
46
53
|
.more {
|
|
54
|
+
appearance: none;
|
|
47
55
|
display: flex;
|
|
48
56
|
align-items: center;
|
|
49
57
|
padding: 0 margin(0.125);
|
|
58
|
+
background: transparent;
|
|
59
|
+
border: 0;
|
|
50
60
|
color: theme(list-item-more-text-color, text-color-alt);
|
|
51
61
|
font-size: theme(detail-font-size-small, font-size-small);
|
|
62
|
+
font-family: inherit;
|
|
52
63
|
line-height: normal;
|
|
64
|
+
|
|
65
|
+
&:hover {
|
|
66
|
+
cursor: pointer;
|
|
67
|
+
color: theme(text-color);
|
|
68
|
+
}
|
|
53
69
|
}
|
|
54
70
|
|
|
55
71
|
.empty {
|
|
72
|
+
appearance: none;
|
|
56
73
|
margin-top: margin(0.25);
|
|
57
74
|
opacity: 0.65;
|
|
58
75
|
font-style: italic;
|
|
@@ -12,9 +12,10 @@
|
|
|
12
12
|
|
|
13
13
|
interface Props {
|
|
14
14
|
title: TitleData
|
|
15
|
+
heading?: string
|
|
15
16
|
}
|
|
16
17
|
|
|
17
|
-
const { title }: Props = $props()
|
|
18
|
+
const { title, heading = t('Cast') }: Props = $props()
|
|
18
19
|
|
|
19
20
|
/**
|
|
20
21
|
* Order participants by how often their name appears in an the page text. This only takes into account
|
|
@@ -48,14 +49,14 @@
|
|
|
48
49
|
</script>
|
|
49
50
|
|
|
50
51
|
{#await fetchParticipantsForTitle(title)}
|
|
51
|
-
<Rail heading
|
|
52
|
+
<Rail {heading}>
|
|
52
53
|
{#each { length: 5 }}
|
|
53
54
|
<div class="participant"></div>
|
|
54
55
|
{/each}
|
|
55
56
|
</Rail>
|
|
56
57
|
{:then participants}
|
|
57
58
|
{#if participants?.length}
|
|
58
|
-
<Rail heading
|
|
59
|
+
<Rail {heading}>
|
|
59
60
|
{#each orderParticipantsByPageTextOccurrence(participants).slice(0, 15) as participant}
|
|
60
61
|
<button class="participant" data-testid="participant" onclick={event => onclick(event, participant)}>
|
|
61
62
|
<span class="truncate">{participant.name}</span>
|
|
@@ -23,15 +23,20 @@ describe('Description.svelte', () => {
|
|
|
23
23
|
expect(queryByRole('button')).not.toBeTruthy()
|
|
24
24
|
})
|
|
25
25
|
|
|
26
|
-
it('Should expand description and
|
|
27
|
-
const { getByText,
|
|
26
|
+
it('Should expand description and collapse again after clicking Show more and Show less', async () => {
|
|
27
|
+
const { getByText, queryByText } = render(Description, { text: 'Some test description', limit: 5 })
|
|
28
28
|
|
|
29
29
|
expect(getByText('Some ...')).toBeTruthy()
|
|
30
30
|
|
|
31
|
-
await fireEvent.click(/** @type {Node} **/(
|
|
31
|
+
await fireEvent.click(/** @type {Node} **/(getByText('Show more')))
|
|
32
32
|
|
|
33
33
|
expect(getByText('Some test description')).toBeTruthy()
|
|
34
|
-
expect(
|
|
34
|
+
expect(queryByText('Show more')).not.toBeTruthy()
|
|
35
|
+
|
|
36
|
+
await fireEvent.click(/** @type {Node} **/(getByText('Show less')))
|
|
37
|
+
|
|
38
|
+
expect(queryByText('Some test description')).not.toBeTruthy()
|
|
39
|
+
expect(queryByText('Show less')).not.toBeTruthy()
|
|
35
40
|
})
|
|
36
41
|
|
|
37
42
|
it('Should include blurb after expanding if given', async () => {
|