@streamscloud/embeddable 3.3.0 → 3.4.1

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.
@@ -0,0 +1,69 @@
1
+ <script lang="ts">import { Icon } from '../../ui/icon';
2
+ import { MediaVolumeManager } from '../../ui/media-playback';
3
+ import IconShoppingBag from '@fluentui/svg-icons/icons/shopping_bag_28_regular.svg?raw';
4
+ import IconSpeaker2 from '@fluentui/svg-icons/icons/speaker_2_28_regular.svg?raw';
5
+ import IconSpeakerMute from '@fluentui/svg-icons/icons/speaker_mute_28_regular.svg?raw';
6
+ let { model, on } = $props();
7
+ const onAttachmentsClicked = () => {
8
+ var _a;
9
+ (_a = on === null || on === void 0 ? void 0 : on.attachmentsClicked) === null || _a === void 0 ? void 0 : _a.call(on);
10
+ };
11
+ const onMuteClicked = () => {
12
+ MediaVolumeManager.isMuted = !MediaVolumeManager.isMuted;
13
+ };
14
+ </script>
15
+
16
+ <div class="short-video-social-interactions" class:short-video-social-interactions--single-action={!(model.products.length || model.ad)}>
17
+ {#if model.products.length || model.ad}
18
+ <button type="button" class="short-video-social-interactions__action" onclick={onAttachmentsClicked}>
19
+ <Icon src={IconShoppingBag} />
20
+ </button>
21
+ {/if}
22
+
23
+ <button type="button" class="short-video-social-interactions__action" onclick={onMuteClicked}>
24
+ {#if MediaVolumeManager.isMuted}
25
+ <Icon src={IconSpeakerMute} />
26
+ {:else}
27
+ <Icon src={IconSpeaker2} />
28
+ {/if}
29
+ </button>
30
+ </div>
31
+
32
+ <style>@keyframes fadeIn {
33
+ 0% {
34
+ opacity: 1;
35
+ }
36
+ 50% {
37
+ opacity: 0.4;
38
+ }
39
+ 100% {
40
+ opacity: 1;
41
+ }
42
+ }
43
+ .short-video-social-interactions {
44
+ cursor: pointer;
45
+ display: flex;
46
+ flex-direction: column;
47
+ justify-content: center;
48
+ gap: 1.125rem;
49
+ border-radius: 1.25rem;
50
+ border: 0.0625rem solid #1c1c1e;
51
+ background: rgba(0, 0, 0, 0.6);
52
+ padding: 1rem 0.625rem;
53
+ }
54
+ .short-video-social-interactions--single-action {
55
+ width: var(--stream-player--button--size);
56
+ min-width: var(--stream-player--button--size);
57
+ max-width: var(--stream-player--button--size);
58
+ height: var(--stream-player--button--size);
59
+ min-height: var(--stream-player--button--size);
60
+ max-height: var(--stream-player--button--size);
61
+ border-radius: 50%;
62
+ }
63
+ .short-video-social-interactions__action {
64
+ --icon--size: var(--stream-player--icon--size);
65
+ --icon--color: #ffffff;
66
+ display: flex;
67
+ justify-content: center;
68
+ align-items: center;
69
+ }</style>
@@ -0,0 +1,10 @@
1
+ import type { ShortVideoViewerModel } from '../..';
2
+ type Props = {
3
+ model: ShortVideoViewerModel;
4
+ on?: {
5
+ attachmentsClicked?: () => void;
6
+ };
7
+ };
8
+ declare const Cmp: import("svelte").Component<Props, {}, "">;
9
+ type Cmp = ReturnType<typeof Cmp>;
10
+ export default Cmp;
@@ -1,6 +1,7 @@
1
1
  export { default as ShortVideoViewer } from './cmp.short-video-viewer.svelte';
2
2
  export { default as ShortVideoAdViewer } from './cmp.ad.svelte';
3
3
  export { default as ShortVideoProductViewer } from './cmp.product.svelte';
4
+ export { default as ShortVideoSocialInteractions } from './cmp.social-interactions.svelte';
4
5
  export { default as ShortVideoViewerAttachments } from './cmp.attachments.svelte';
5
6
  export { default as ShortVideoViewerAttachmentsInline } from './cmp.attachments-inline.svelte';
6
7
  export { default as ShortVideoDetails } from './cmp.short-video-details.svelte';
@@ -1,6 +1,7 @@
1
1
  export { default as ShortVideoViewer } from './cmp.short-video-viewer.svelte';
2
2
  export { default as ShortVideoAdViewer } from './cmp.ad.svelte';
3
3
  export { default as ShortVideoProductViewer } from './cmp.product.svelte';
4
+ export { default as ShortVideoSocialInteractions } from './cmp.social-interactions.svelte';
4
5
  export { default as ShortVideoViewerAttachments } from './cmp.attachments.svelte';
5
6
  export { default as ShortVideoViewerAttachmentsInline } from './cmp.attachments-inline.svelte';
6
7
  export { default as ShortVideoDetails } from './cmp.short-video-details.svelte';
@@ -40,6 +40,7 @@ let isActive = true;
40
40
  let activityTimeout = null;
41
41
  let trackingInterval = null;
42
42
  let maxPageIndexViewed = 0;
43
+ let background = $state(null);
43
44
  const uiManager = new StreamPlayerUiManager();
44
45
  const resetInactivityTimer = () => {
45
46
  if (!isActive) {
@@ -138,6 +139,7 @@ const contentMounted = (node) => {
138
139
  };
139
140
  const onPageActivated = (id) => {
140
141
  const page = buffer === null || buffer === void 0 ? void 0 : buffer.loaded.find((x) => x.id === id);
142
+ background = (page === null || page === void 0 ? void 0 : page.cover) || null;
141
143
  if (page) {
142
144
  AppEventsTracker.trackStreamPageView(id, streamId);
143
145
  const currentIndex = buffer === null || buffer === void 0 ? void 0 : buffer.loaded.findIndex((p) => p.id === id);
@@ -169,7 +171,7 @@ const onProgress = (pageId, videoId, progress) => {
169
171
 
170
172
  <svelte:document onkeydown={(e) => handleEsc(e, onPlayerClose)} />
171
173
 
172
- <div class="stream-player-container">
174
+ <div class="stream-player-container" style="--background-image: url({background})">
173
175
  {#if loading}
174
176
  <Loading positionAbsoluteCenter={true} timeout={600} />
175
177
  {/if}
@@ -258,13 +260,18 @@ const onProgress = (pageId, videoId, progress) => {
258
260
  container-type: inline-size;
259
261
  display: flex;
260
262
  position: relative;
261
- background: #000000;
263
+ background-color: rgba(0, 0, 0, 0.75);
264
+ background-image: var(--background-image);
265
+ background-size: cover;
266
+ background-blend-mode: multiply;
262
267
  }
263
268
 
264
269
  .stream-player {
265
270
  display: flex;
266
271
  flex: 1;
267
272
  padding: 0.625rem 0;
273
+ backdrop-filter: blur(30px);
274
+ position: relative;
268
275
  /* Set 'container-type: inline-size;' to reference container*/
269
276
  }
270
277
  @container (width < 576px) {
@@ -1,22 +1,14 @@
1
1
  <script lang="ts">var _a, _b;
2
- import { ShortVideoDetails, ShortVideoViewerAttachmentsInline, ShortVideoViewerAttachments } from '../../short-videos/short-video-viewer';
2
+ import { ShortVideoViewerAttachmentsInline, ShortVideoViewerAttachments } from '../../short-videos/short-video-viewer';
3
+ import { ShortVideoSocialInteractions } from '../../short-videos/short-video-viewer/index.js';
3
4
  import { StreamElementType } from '../layout/enums';
4
5
  import { mapToShortVideoViewerModel } from '../layout/models';
5
6
  import { Icon } from '../../ui/icon';
6
- import { MediaVolumeManager } from '../../ui/media-playback';
7
- import { default as ActionButton } from './action-button.svelte';
8
7
  import { StreamPlayerLocalization } from './stream-player-localization';
9
- import IconChevronDown from '@fluentui/svg-icons/icons/chevron_down_20_regular.svg?raw';
10
- import IconChevronUp from '@fluentui/svg-icons/icons/chevron_up_20_regular.svg?raw';
11
- import IconDismiss from '@fluentui/svg-icons/icons/dismiss_20_regular.svg?raw';
12
- import IconFullScreenMaximize from '@fluentui/svg-icons/icons/full_screen_maximize_20_regular.svg?raw';
13
- import IconPanelRightGallery from '@fluentui/svg-icons/icons/panel_right_gallery_20_regular.svg?raw';
14
- import IconSpeaker2 from '@fluentui/svg-icons/icons/speaker_2_20_regular.svg?raw';
15
- import IconSpeakerMute from '@fluentui/svg-icons/icons/speaker_mute_20_regular.svg?raw';
8
+ import IconChevronDown from '@fluentui/svg-icons/icons/chevron_down_28_regular.svg?raw';
9
+ import IconChevronUp from '@fluentui/svg-icons/icons/chevron_up_28_regular.svg?raw';
10
+ import IconDismiss from '@fluentui/svg-icons/icons/dismiss_28_regular.svg?raw';
16
11
  let { buffer, uiManager, localization, on } = $props();
17
- const toggleMuted = () => {
18
- MediaVolumeManager.isMuted = !MediaVolumeManager.isMuted;
19
- };
20
12
  const shortVideo = $derived(((_a = buffer.current) === null || _a === void 0 ? void 0 : _a.type) === 'short-video' && ((_b = buffer.current) === null || _b === void 0 ? void 0 : _b.shortVideo) ? mapToShortVideoViewerModel(buffer.current.shortVideo) : null);
21
13
  const singleWebViewPage = $derived.by(() => {
22
14
  var _a;
@@ -48,15 +40,21 @@ const singleWebViewPage = $derived.by(() => {
48
40
  }
49
41
  return allRenderableElements.length === 1 && allRenderableElements[0].type === StreamElementType.WebView;
50
42
  });
43
+ const changeShowShortVideoAttachments = () => {
44
+ uiManager.showShortVideoAttachments = !uiManager.showShortVideoAttachments;
45
+ };
51
46
  </script>
52
47
 
53
48
  <div class="stream-player-controls">
54
49
  <div class="stream-player-controls__left">
55
50
  {#if shortVideo && uiManager.shortVideoDetailsCollapsed && !uiManager.showShortVideoOverlay}
56
51
  <div class="stream-player-controls__short-video-overlay">
57
- <div class="stream-player-controls__short-video-attachments-inline">
58
- <ShortVideoViewerAttachmentsInline model={shortVideo} />
59
- </div>
52
+ {#if uiManager.showShortVideoAttachments}
53
+ <div class="stream-player-controls__short-video-attachments-inline">
54
+ <ShortVideoViewerAttachmentsInline model={shortVideo} />
55
+ </div>
56
+ {/if}
57
+ <ShortVideoSocialInteractions model={shortVideo} on={{ attachmentsClicked: changeShowShortVideoAttachments }} />
60
58
  </div>
61
59
  {/if}
62
60
  <div class="stream-player-controls__navigation-buttons" class:stream-player-controls__navigation-buttons--single-web-view-page={singleWebViewPage}>
@@ -69,7 +67,7 @@ const singleWebViewPage = $derived.by(() => {
69
67
  </div>
70
68
  </div>
71
69
  <div class="stream-player-controls__right">
72
- {#if shortVideo && shortVideo.products}
70
+ {#if shortVideo && shortVideo.products && uiManager.showShortVideoAttachments}
73
71
  <div class="stream-player-controls__short-video-attachments">
74
72
  <ShortVideoViewerAttachments
75
73
  shortVideo={shortVideo}
@@ -79,40 +77,10 @@ const singleWebViewPage = $derived.by(() => {
79
77
  }} />
80
78
  </div>
81
79
  {/if}
82
- <div class="stream-player-controls__controls">
83
- {#if shortVideo}
84
- <ActionButton on={{ click: toggleMuted }}>
85
- {#if MediaVolumeManager.isMuted}
86
- <Icon src={IconSpeakerMute} />
87
- {:else}
88
- <Icon src={IconSpeaker2} />
89
- {/if}
90
- </ActionButton>
91
- {/if}
92
- {#if !uiManager.overviewCollapsed}
93
- <ActionButton on={{ click: () => (uiManager.overviewCollapsed = true) }}>
94
- <Icon src={IconFullScreenMaximize} />
95
- </ActionButton>
96
- {/if}
97
- </div>
98
80
  </div>
99
81
  </div>
100
82
 
101
- {#if shortVideo && (!uiManager.isMobileView || uiManager.overviewCollapsed)}
102
- <ShortVideoDetails
103
- shortVideo={shortVideo}
104
- collapsed={uiManager.shortVideoDetailsCollapsed}
105
- localization={localization.shortVideoDetailsLocalization}
106
- on={{
107
- productClick: on.productClick
108
- }} />
109
- <div class="toggle-collapsed-button">
110
- <ActionButton on={{ click: () => (uiManager.shortVideoDetailsCollapsed = !uiManager.shortVideoDetailsCollapsed) }}>
111
- <Icon src={IconPanelRightGallery} />
112
- </ActionButton>
113
- </div>
114
- {/if}
115
- <button type="button" class="close-button navigation-button" onclick={on.closePlayer}>
83
+ <button type="button" class="close-button" onclick={on.closePlayer} class:close-button--left={uiManager.overviewCollapsed}>
116
84
  <Icon src={IconDismiss} />
117
85
  </button>
118
86
 
@@ -129,16 +97,30 @@ const singleWebViewPage = $derived.by(() => {
129
97
  }
130
98
  .close-button {
131
99
  position: absolute;
132
- top: var(--stream-player--controls--offset-vertical);
133
- right: var(--stream-player--controls--offset-horizontal);
100
+ top: 0.9375rem;
101
+ left: 15.1875rem;
134
102
  z-index: 1;
103
+ width: var(--stream-player--button--size);
104
+ min-width: var(--stream-player--button--size);
105
+ max-width: var(--stream-player--button--size);
106
+ height: var(--stream-player--button--size);
107
+ min-height: var(--stream-player--button--size);
108
+ max-height: var(--stream-player--button--size);
109
+ background-color: rgba(0, 0, 0, 0.6);
110
+ border: 0.0625rem solid #1c1c1e;
111
+ border-radius: 50%;
112
+ text-align: center;
113
+ --icon--color: #ffffff;
114
+ /* Set 'container-type: inline-size;' to reference container*/
135
115
  }
136
-
137
- .toggle-collapsed-button {
138
- position: absolute;
139
- bottom: var(--stream-player--controls--offset-vertical);
140
- right: var(--stream-player--controls--offset-horizontal);
141
- z-index: 1;
116
+ .close-button--left {
117
+ left: 0.625rem;
118
+ }
119
+ @container (width < 576px) {
120
+ .close-button {
121
+ left: unset;
122
+ right: 0.625rem;
123
+ }
142
124
  }
143
125
 
144
126
  .stream-player-controls {
@@ -156,8 +138,9 @@ const singleWebViewPage = $derived.by(() => {
156
138
  .stream-player-controls__left {
157
139
  display: flex;
158
140
  flex-direction: column;
159
- gap: 2.5rem;
141
+ gap: 2.3125rem;
160
142
  justify-content: flex-end;
143
+ align-items: center;
161
144
  }
162
145
  .stream-player-controls__right {
163
146
  flex: 1;
@@ -165,7 +148,6 @@ const singleWebViewPage = $derived.by(() => {
165
148
  justify-content: space-between;
166
149
  align-items: flex-end;
167
150
  flex-direction: column;
168
- padding-top: 3.75rem;
169
151
  /* Set 'container-type: inline-size;' to reference container*/
170
152
  }
171
153
  @container (width < 9.375rem) {
@@ -181,16 +163,12 @@ const singleWebViewPage = $derived.by(() => {
181
163
  flex-direction: column;
182
164
  align-items: flex-start;
183
165
  justify-content: flex-end;
184
- --short-video-viewer--interactions--icon--size: var(--stream-player--navigation-button--size);
185
- --short-video-viewer--interactions--background--color: #1c1c1c;
186
- --short-video-viewer--interactions--counter--color: #f3f4f6;
187
- --short-video-viewer--interactions--icon--font-color: #f3f4f6;
188
166
  }
189
167
  .stream-player-controls__short-video-attachments-inline {
190
168
  display: none;
191
169
  /* Set 'container-type: inline-size;' to reference container*/
192
170
  }
193
- @container (width < calc(21.875rem + 3.75rem)) {
171
+ @container (width < calc(11rem + 3.75rem)) {
194
172
  .stream-player-controls__short-video-attachments-inline {
195
173
  display: contents;
196
174
  }
@@ -201,8 +179,8 @@ const singleWebViewPage = $derived.by(() => {
201
179
  overflow-y: auto;
202
180
  scrollbar-color: transparent transparent;
203
181
  scrollbar-width: thin;
204
- width: 21.875rem;
205
- max-width: 21.875rem;
182
+ width: 11rem;
183
+ max-width: 11rem;
206
184
  /* Set 'container-type: inline-size;' to reference container*/
207
185
  }
208
186
  .stream-player-controls__short-video-attachments::-webkit-scrollbar {
@@ -227,7 +205,7 @@ const singleWebViewPage = $derived.by(() => {
227
205
  .stream-player-controls__short-video-attachments:hover::-webkit-scrollbar-thumb {
228
206
  background: var(--custom-scrollbar-color, #7d7d7d);
229
207
  }
230
- @container (width < calc(21.875rem + 3.75rem)) {
208
+ @container (width < calc(11rem + 3.75rem)) {
231
209
  .stream-player-controls__short-video-attachments {
232
210
  display: none;
233
211
  }
@@ -236,7 +214,6 @@ const singleWebViewPage = $derived.by(() => {
236
214
  display: flex;
237
215
  flex-direction: column;
238
216
  gap: 1rem;
239
- margin-bottom: 0.625rem;
240
217
  z-index: 1;
241
218
  /* Set 'container-type: inline-size;' to reference container*/
242
219
  }
@@ -245,38 +222,20 @@ const singleWebViewPage = $derived.by(() => {
245
222
  visibility: hidden;
246
223
  }
247
224
  }
248
- .stream-player-controls__navigation-buttons--single-web-view-page {
249
- /* Set 'container-type: inline-size;' to reference container*/
250
- }
251
- @container (width < 6.25rem) {
252
- .stream-player-controls__navigation-buttons--single-web-view-page {
253
- visibility: visible;
254
- position: absolute;
255
- bottom: var(--stream-player--controls--offset-vertical);
256
- right: var(--stream-player--controls--offset-horizontal);
257
- z-index: 1;
258
- }
259
- }
260
- .stream-player-controls__controls {
261
- display: flex;
262
- margin-top: auto;
263
- gap: 1rem;
264
- align-self: flex-start;
265
- }
266
225
 
267
226
  .navigation-button {
268
- width: var(--stream-player--navigation-button--size);
269
- min-width: var(--stream-player--navigation-button--size);
270
- max-width: var(--stream-player--navigation-button--size);
271
- height: var(--stream-player--navigation-button--size);
272
- min-height: var(--stream-player--navigation-button--size);
273
- max-height: var(--stream-player--navigation-button--size);
274
- background-color: #000000;
275
- border: 1px solid #1c1c1c;
227
+ width: var(--stream-player--button--size);
228
+ min-width: var(--stream-player--button--size);
229
+ max-width: var(--stream-player--button--size);
230
+ height: var(--stream-player--button--size);
231
+ min-height: var(--stream-player--button--size);
232
+ max-height: var(--stream-player--button--size);
233
+ background-color: rgba(0, 0, 0, 0.6);
234
+ border: 0.0625rem solid #1c1c1e;
276
235
  border-radius: 50%;
277
236
  text-align: center;
278
237
  --icon--color: #ffffff;
279
- --icon--stroke-width: 0.6;
238
+ --icon--size: var(--stream-player--icon--size);
280
239
  }
281
240
  .navigation-button:disabled {
282
241
  opacity: 0.5;
@@ -5,7 +5,6 @@ import { InfiniteScrolling } from '../../ui/infinite-scrolling';
5
5
  import { LineClamp } from '../../ui/line-clamp';
6
6
  import { ProportionalContainer } from '../../ui/proportional-container';
7
7
  import { TimeAgo } from '../../ui/time-ago';
8
- import { default as ActionButton } from './action-button.svelte';
9
8
  import { StreamPlayerLocalization } from './stream-player-localization';
10
9
  import IconPanelLeftText from '@fluentui/svg-icons/icons/panel_left_text_20_regular.svg?raw';
11
10
  let { model, buffer, activePageId, on, uiManager, localization } = $props();
@@ -67,11 +66,13 @@ let { model, buffer, activePageId, on, uiManager, localization } = $props();
67
66
  </div>
68
67
  {/if}
69
68
 
70
- <div class="toggle-collapsed-button">
71
- <ActionButton on={{ click: () => (uiManager.overviewCollapsed = !uiManager.overviewCollapsed) }}>
72
- <Icon src={IconPanelLeftText} />
73
- </ActionButton>
74
- </div>
69
+ <button
70
+ class="toggle-collapsed-button"
71
+ class:toggle-collapsed-button--left={uiManager.overviewCollapsed}
72
+ type="button"
73
+ onclick={() => (uiManager.overviewCollapsed = !uiManager.overviewCollapsed)}>
74
+ <Icon src={IconPanelLeftText} />
75
+ </button>
75
76
 
76
77
  <style>@keyframes fadeIn {
77
78
  0% {
@@ -114,9 +115,21 @@ let { model, buffer, activePageId, on, uiManager, localization } = $props();
114
115
 
115
116
  .toggle-collapsed-button {
116
117
  position: absolute;
117
- bottom: var(--stream-player--controls--offset-vertical);
118
- left: var(--stream-player--controls--offset-horizontal);
118
+ bottom: 0.625rem;
119
+ left: 12rem;
119
120
  z-index: 1;
121
+ --icon--color: #ffffff;
122
+ --icon--size: 1.25rem;
123
+ /* Set 'container-type: inline-size;' to reference container*/
124
+ }
125
+ .toggle-collapsed-button--left {
126
+ left: 0.625rem;
127
+ }
128
+ @container (width < 576px) {
129
+ .toggle-collapsed-button {
130
+ left: unset;
131
+ right: 0.625rem;
132
+ }
120
133
  }
121
134
 
122
135
  .stream-overview-info {
@@ -124,21 +137,19 @@ let { model, buffer, activePageId, on, uiManager, localization } = $props();
124
137
  }
125
138
  .stream-overview-info__title {
126
139
  font-size: 1.125rem;
127
- line-height: 1.2;
128
- font-weight: 900;
140
+ line-height: 1.55;
141
+ font-weight: 600;
129
142
  color: #ffffff;
130
143
  }
131
144
  .stream-overview-info__subtitle {
132
- font-size: 0.9375rem;
133
- line-height: 1.6;
134
- font-weight: 500;
135
- letter-spacing: 0.75px;
145
+ font-size: 0.875rem;
136
146
  color: #ffffff;
137
147
  }
138
148
  .stream-overview-info__pages {
139
149
  font-size: 0.625rem;
140
150
  line-height: 1;
141
- font-weight: 500;
151
+ font-weight: 400;
152
+ letter-spacing: -0.0125rem;
142
153
  color: #999999;
143
154
  }
144
155
 
@@ -179,7 +190,7 @@ let { model, buffer, activePageId, on, uiManager, localization } = $props();
179
190
  display: flex;
180
191
  flex-direction: column;
181
192
  align-items: center;
182
- gap: 2.5rem;
193
+ gap: 1rem;
183
194
  /* Set 'container-type: inline-size;' to reference container*/
184
195
  }
185
196
  @container (width < 576px) {
@@ -217,9 +228,9 @@ let { model, buffer, activePageId, on, uiManager, localization } = $props();
217
228
  height: 2rem;
218
229
  min-height: 2rem;
219
230
  max-height: 2rem;
220
- --image--rounded--inner--border-color: #111827;
221
- --image--rounded--outer--border-color: #f3f4f6;
222
- --image--rounded--outer--border-width: 0.0625rem;
231
+ --image--rounded--inner--border-width: 0;
232
+ --image--rounded--outer--border-color: #f2f2f3;
233
+ --image--rounded--outer--border-width: 0.04325rem;
223
234
  }
224
235
  .stream-overview-owner__body {
225
236
  display: flex;
@@ -229,11 +240,10 @@ let { model, buffer, activePageId, on, uiManager, localization } = $props();
229
240
  }
230
241
  .stream-overview-owner__name {
231
242
  font-size: 0.75rem;
232
- line-height: 1.2;
233
243
  font-weight: 500;
244
+ letter-spacing: -0.015625rem;
234
245
  }
235
246
  .stream-overview-owner__meta {
236
247
  font-size: 0.625rem;
237
- line-height: 1.2;
238
- font-weight: 500;
248
+ letter-spacing: -0.0125rem;
239
249
  }</style>
@@ -1,13 +1,14 @@
1
1
  export declare class StreamPlayerUiManager {
2
2
  overviewCollapsed: boolean;
3
3
  shortVideoDetailsCollapsed: boolean;
4
+ showShortVideoAttachments: boolean;
4
5
  globalCssVariables: string;
5
6
  isMobileView: boolean;
6
7
  showShortVideoOverlay: boolean;
7
- private readonly actionButtonSize;
8
- private readonly navigationButtonSize;
8
+ private readonly buttonSize;
9
9
  private readonly controlsOffsetHorizontal;
10
10
  private readonly controlsOffsetVertical;
11
+ private readonly iconSize;
11
12
  private viewTotalWidth;
12
13
  private mainViewColumnWidth;
13
14
  updateDimensions: (dimensions: {
@@ -1,22 +1,23 @@
1
1
  export class StreamPlayerUiManager {
2
2
  overviewCollapsed = $state(false);
3
3
  shortVideoDetailsCollapsed = $state(true);
4
+ showShortVideoAttachments = $state(true);
4
5
  globalCssVariables = $derived.by(() => {
5
6
  const values = [
6
- `--stream-player--action-button--size: ${this.actionButtonSize}px`,
7
- `--stream-player--navigation-button--size: ${this.navigationButtonSize}px`,
7
+ `--stream-player--button--size: ${this.buttonSize}px`,
8
8
  `--stream-player--controls--offset-horizontal: ${this.controlsOffsetHorizontal}px`,
9
9
  `--stream-player--controls--offset-vertical: ${this.controlsOffsetVertical}px`,
10
- `--stream-player--sidebar--available-space: ${(this.viewTotalWidth - this.mainViewColumnWidth) / 2}px`
10
+ `--stream-player--sidebar--available-space: ${(this.viewTotalWidth - this.mainViewColumnWidth) / 2}px`,
11
+ `--stream-player--icon--size: ${this.iconSize}px`
11
12
  ];
12
13
  return values.join(';');
13
14
  });
14
15
  isMobileView = $derived.by(() => this.viewTotalWidth <= 576);
15
16
  showShortVideoOverlay = $derived.by(() => (this.viewTotalWidth - this.mainViewColumnWidth) / 2 <= 70);
16
- actionButtonSize = 30;
17
- navigationButtonSize = 40;
18
- controlsOffsetHorizontal = 15;
19
- controlsOffsetVertical = 10;
17
+ buttonSize = 48;
18
+ controlsOffsetHorizontal = 28;
19
+ controlsOffsetVertical = 28;
20
+ iconSize = 23;
20
21
  viewTotalWidth = $state(0);
21
22
  mainViewColumnWidth = $state(0);
22
23
  updateDimensions = (dimensions) => {
@@ -1,11 +1,11 @@
1
1
  <script lang="ts">import { Utils } from '../../core/utils';
2
2
  import { isScrollingPrevented } from './prevent-slider-scroll';
3
- import { onDestroy, onMount } from 'svelte';
4
- let { buffer, children, on } = $props();
3
+ import { onDestroy, onMount, untrack } from 'svelte';
4
+ let { buffer, on, children } = $props();
5
5
  let slidesRef;
6
6
  let sliderHeight = $state(0);
7
7
  let swipeTransition = $state(0);
8
- let cssAnimationDuration = $state(buffer.animationDuration);
8
+ let cssAnimationDuration = $state(buffer.animationDuration * 0.55);
9
9
  let resizeObserver;
10
10
  let activeIndex = $state.raw(buffer.currentIndex);
11
11
  const actualTransition = $derived(-sliderHeight * activeIndex);
@@ -17,14 +17,41 @@ const onKeyPress = (e) => {
17
17
  buffer.loadNext();
18
18
  }
19
19
  };
20
- // Notify the parent component that the active item is about to change.
21
- let active = null;
22
20
  $effect(() => {
23
21
  if (buffer.currentIndex >= 0 && activeIndex >= 0 && Math.abs(activeIndex - buffer.currentIndex) === 1) {
24
22
  slidesRef.classList.toggle('animate', true);
25
23
  }
24
+ else if (buffer.currentIndex >= 0 && (Math.abs(activeIndex - buffer.currentIndex) !== 0 || !active)) {
25
+ untrack(() => notifyOnItemChanged());
26
+ }
27
+ });
28
+ // Notify the parent component that the active item is about to change.
29
+ let active = null;
30
+ $effect(() => {
31
+ if (buffer.currentIndex >= 0 && activeIndex >= 0 && activeIndex !== buffer.currentIndex && on) {
32
+ untrack(() => {
33
+ var _a, _b, _c;
34
+ if (active && ((_a = buffer.current) === null || _a === void 0 ? void 0 : _a.id) !== active.id) {
35
+ (_b = on === null || on === void 0 ? void 0 : on.itemPreDeactivated) === null || _b === void 0 ? void 0 : _b.call(on, { itemId: active.id, loadingNext: buffer.currentIndex > activeIndex });
36
+ }
37
+ const nextItem = buffer.loaded[buffer.currentIndex];
38
+ if (nextItem) {
39
+ (_c = on === null || on === void 0 ? void 0 : on.itemPreActivated) === null || _c === void 0 ? void 0 : _c.call(on, nextItem);
40
+ }
41
+ });
42
+ }
26
43
  activeIndex = buffer.currentIndex;
27
44
  });
45
+ const notifyOnItemChanged = () => {
46
+ var _a, _b, _c;
47
+ if (active && ((_a = buffer.current) === null || _a === void 0 ? void 0 : _a.id) !== active.id) {
48
+ (_b = on === null || on === void 0 ? void 0 : on.itemDeactivated) === null || _b === void 0 ? void 0 : _b.call(on, active.id);
49
+ }
50
+ active = buffer.current;
51
+ if (active) {
52
+ (_c = on === null || on === void 0 ? void 0 : on.itemActivated) === null || _c === void 0 ? void 0 : _c.call(on, active.id);
53
+ }
54
+ };
28
55
  onMount(() => {
29
56
  let touchStartY = 0;
30
57
  let touchMoveY = 0;
@@ -37,6 +64,7 @@ onMount(() => {
37
64
  touchStartTime = Date.now();
38
65
  });
39
66
  slidesRef.addEventListener('touchmove', (e) => {
67
+ e.preventDefault();
40
68
  const newPosition = e.changedTouches[0].screenY;
41
69
  const diff = newPosition - touchStartY;
42
70
  if ((diff > 0 && buffer.canLoadPrevious) || (diff < 0 && buffer.canLoadNext)) {
@@ -81,7 +109,7 @@ onMount(() => {
81
109
  if (e.deltaY < 0 && buffer.canLoadPrevious) {
82
110
  buffer.loadPrevious();
83
111
  }
84
- }, buffer.animationDuration));
112
+ }, buffer.animationDuration + 250));
85
113
  slidesRef.addEventListener('transitionend', (e) => {
86
114
  if (e.target !== slidesRef) {
87
115
  return;
@@ -95,16 +123,6 @@ onMount(() => {
95
123
  });
96
124
  resizeObserver.observe(slidesRef);
97
125
  });
98
- const notifyOnItemChanged = () => {
99
- var _a, _b, _c;
100
- if (active && ((_a = buffer.current) === null || _a === void 0 ? void 0 : _a.id) !== active.id) {
101
- (_b = on === null || on === void 0 ? void 0 : on.itemDeactivated) === null || _b === void 0 ? void 0 : _b.call(on, active.id);
102
- }
103
- active = buffer.current;
104
- if (active) {
105
- (_c = on === null || on === void 0 ? void 0 : on.itemActivated) === null || _c === void 0 ? void 0 : _c.call(on, active.id);
106
- }
107
- };
108
126
  onDestroy(() => {
109
127
  if (resizeObserver) {
110
128
  resizeObserver.disconnect();
@@ -6,8 +6,13 @@ declare class __sveltets_Render<T extends {
6
6
  props(): {
7
7
  buffer: IPlayerBuffer<T>;
8
8
  on?: {
9
- itemDeactivated?: ((e: string) => void) | undefined;
9
+ itemPreActivated?: ((e: T) => void) | undefined;
10
+ itemPreDeactivated?: ((e: {
11
+ itemId: string;
12
+ loadingNext: boolean;
13
+ }) => void) | undefined;
10
14
  itemActivated?: ((e: string) => void) | undefined;
15
+ itemDeactivated?: ((e: string) => void) | undefined;
11
16
  } | undefined;
12
17
  children: Snippet<[{
13
18
  item: T;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@streamscloud/embeddable",
3
- "version": "3.3.0",
3
+ "version": "3.4.1",
4
4
  "author": "StreamsCloud",
5
5
  "repository": "https://github.com/StreamsCloud/streamscloud-frontend-packages.git",
6
6
  "type": "module",
@@ -1,38 +0,0 @@
1
- <script lang="ts">let { children, on } = $props();
2
- export {};
3
- </script>
4
-
5
- <button type="button" class="action-button" onclick={() => on.click()}>
6
- {@render children()}
7
- </button>
8
-
9
- <style>@keyframes fadeIn {
10
- 0% {
11
- opacity: 1;
12
- }
13
- 50% {
14
- opacity: 0.4;
15
- }
16
- 100% {
17
- opacity: 1;
18
- }
19
- }
20
- .action-button {
21
- --_stream-player--action-button--size: var(--stream-player--action-button--size);
22
- --_stream-player--action-button--background: var(--action-button-background, #1c1c1c);
23
- width: var(--_stream-player--action-button--size);
24
- min-width: var(--_stream-player--action-button--size);
25
- max-width: var(--_stream-player--action-button--size);
26
- height: var(--_stream-player--action-button--size);
27
- min-height: var(--_stream-player--action-button--size);
28
- max-height: var(--_stream-player--action-button--size);
29
- display: flex;
30
- justify-content: center;
31
- align-items: center;
32
- line-height: 0;
33
- background: var(--_stream-player--action-button--background);
34
- border-radius: 50%;
35
- --icon--size: 1.25rem;
36
- z-index: 1;
37
- color: #ffffff;
38
- }</style>
@@ -1,10 +0,0 @@
1
- import type { Snippet } from 'svelte';
2
- type Props = {
3
- on: {
4
- click: () => void;
5
- };
6
- children: Snippet;
7
- };
8
- declare const ActionButton: import("svelte").Component<Props, {}, "">;
9
- type ActionButton = ReturnType<typeof ActionButton>;
10
- export default ActionButton;