@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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@playpilot/tpi",
3
- "version": "8.23.0-beta.3",
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.0",
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 expand(): void {
16
- expanded = true
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="show-more" onclick={() => expand()}>Show more</button>
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
- .show-more {
55
+ .toggle {
48
56
  display: inline;
49
57
  appearance: none;
50
58
  padding: 0;
@@ -45,12 +45,11 @@
45
45
  transform: scale(1.025);
46
46
 
47
47
  :global(button) {
48
- text-decoration-thickness: 2px;
48
+ text-decoration: underline;
49
49
  }
50
50
  }
51
51
 
52
52
  :global(button) {
53
- text-decoration: underline;
54
53
  color: white;
55
54
  }
56
55
  }
@@ -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') ? 'Streaming guide' : ''} />
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="Streaming guide" />
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) 0;
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
- const limitedPlaylinks = $derived(mergePlaylinks(playlinks).slice(0, 3))
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 playlinks.length > limitedPlaylinks.length}
26
- <span class="more">
27
- +{playlinks.length - limitedPlaylinks.length}
28
- </span>
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 !playlinks.length}
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={t('Cast')}>
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={t('Cast')}>
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 remove show more button after clicking', async () => {
27
- const { getByText, queryByRole } = render(Description, { text: 'Some test description', limit: 5 })
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} **/(queryByRole('button')))
31
+ await fireEvent.click(/** @type {Node} **/(getByText('Show more')))
32
32
 
33
33
  expect(getByText('Some test description')).toBeTruthy()
34
- expect(queryByRole('button')).not.toBeTruthy()
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 () => {