@streamscloud/embeddable 7.0.0-1758321646285 → 7.0.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.
@@ -146,6 +146,7 @@ const toggleOverview = () => __awaiter(void 0, void 0, void 0, function* () {
146
146
  return;
147
147
  }
148
148
  overviewOpened = !overviewOpened;
149
+ streamsInCategoryOpened = false;
149
150
  if (overviewOpened && !overviewData) {
150
151
  overviewData = { loading: true };
151
152
  try {
@@ -209,8 +210,13 @@ const onScrollMounted = (node) => {
209
210
  {#if mediaDataLoading}
210
211
  <Loading positionFixedCenter={true} timeout={600} />
211
212
  {:else}
212
- {#snippet categoriesSwitcher(data: { maxItemsWidth: Number; onMounted: (data: { height: Number }) => void })}
213
+ {#snippet categoriesSwitcher(data: { maxItemsWidth: Number; onMounted: (data: { height: Number }) => void; closeButton?: Snippet })}
213
214
  <div class="media-center" use:mounted={data.onMounted}>
215
+ {#if data.closeButton}
216
+ <div class="media-center__close-button">
217
+ {@render data.closeButton()}
218
+ </div>
219
+ {/if}
214
220
  <div class="media-center__row" style={`max-width: ${data.maxItemsWidth}px;`}>
215
221
  <div
216
222
  class="media-center__scroll"
@@ -313,11 +319,6 @@ const onScrollMounted = (node) => {
313
319
  display: flex;
314
320
  justify-content: center;
315
321
  padding: 1.25rem 5rem;
316
- position: absolute;
317
- top: 0;
318
- left: 0;
319
- right: 0;
320
- z-index: 1;
321
322
  pointer-events: none;
322
323
  }
323
324
  .media-center__row {
@@ -335,6 +336,20 @@ const onScrollMounted = (node) => {
335
336
  display: none;
336
337
  }
337
338
  }
339
+ .media-center__close-button {
340
+ pointer-events: auto;
341
+ position: absolute;
342
+ top: 0.9375rem;
343
+ left: 0.625rem;
344
+ z-index: 1;
345
+ /* Set 'container-type: inline-size;' to reference container*/
346
+ }
347
+ @container (width < 576px) {
348
+ .media-center__close-button {
349
+ left: unset;
350
+ right: 0.625rem;
351
+ }
352
+ }
338
353
  .media-center__scroll {
339
354
  pointer-events: auto;
340
355
  position: relative;
@@ -54,7 +54,7 @@ const trackControlsPanelSize = (node) => {
54
54
  <LineClamp value={model.text} maxLines={2} enableShowMore={true} />
55
55
  {/if}
56
56
  </div>
57
- {#if uiManager.showAttachments}
57
+ {#if uiManager.showAttachments && model.hasAttachments}
58
58
  <div class="short-video-viewer__attachments">
59
59
  <AttachmentsHorizontal
60
60
  model={model}
@@ -114,10 +114,12 @@ const onShortVideoAdImpression = (adId) => {
114
114
  class:short-videos-player-container--faded={fadeContent}
115
115
  style={background && !disableBackground ? `--background-image: url(${background})` : null}>
116
116
  {#if categoriesSwitcher}
117
- {@render categoriesSwitcher({
118
- maxItemsWidth: Math.min(uiManager.mainViewColumnWidth * 1.4, uiManager.viewTotalWidth),
119
- onMounted: onMediaCenterHeaderMounted
120
- })}
117
+ <div class="short-videos-player-container__media-center">
118
+ {@render categoriesSwitcher({
119
+ maxItemsWidth: Math.min(uiManager.mainViewColumnWidth * 1.4, uiManager.viewTotalWidth),
120
+ onMounted: onMediaCenterHeaderMounted
121
+ })}
122
+ </div>
121
123
  {/if}
122
124
 
123
125
  <div class="short-videos-player" style={uiManager.globalCssVariables}>
@@ -211,6 +213,13 @@ const onShortVideoAdImpression = (adId) => {
211
213
  .short-videos-player-container--faded {
212
214
  --short-videos-player--elements-opacity: 0;
213
215
  }
216
+ .short-videos-player-container__media-center {
217
+ position: absolute;
218
+ top: 0;
219
+ left: 0;
220
+ right: 0;
221
+ z-index: 1;
222
+ }
214
223
 
215
224
  .short-videos-player {
216
225
  display: flex;
@@ -0,0 +1,24 @@
1
+ @use 'src/styles/functions';
2
+ @use 'src/styles/mixins';
3
+ @use 'src/styles/colors';
4
+
5
+ @mixin button() {
6
+ @include mixins.width(functions.rem(48));
7
+ @include mixins.height(functions.rem(48));
8
+ background-color: rgba(0, 0, 0, 0.6);
9
+ border: 1px solid colors.$color-gray-900;
10
+ border-radius: 50%;
11
+ text-align: center;
12
+ --icon--color: #{colors.$color-white};
13
+ --icon--size: #{functions.rem(28)};
14
+
15
+ &:hover {
16
+ background-color: rgba(0, 0, 0, 0.9);
17
+ transition: background-color 0.5s;
18
+ }
19
+
20
+ &:disabled {
21
+ opacity: 0.5;
22
+ cursor: default;
23
+ }
24
+ }
@@ -9,7 +9,7 @@ import { StreamPlayerLocalization } from './stream-player-localization';
9
9
  import IconChevronDown from '@fluentui/svg-icons/icons/chevron_down_28_regular.svg?raw';
10
10
  import IconChevronUp from '@fluentui/svg-icons/icons/chevron_up_28_regular.svg?raw';
11
11
  import IconDismiss from '@fluentui/svg-icons/icons/dismiss_28_regular.svg?raw';
12
- let { buffer, uiManager, postSocialInteractionsHandler, localization, on, playerLogo } = $props();
12
+ let { buffer, uiManager, postSocialInteractionsHandler, localization, on, playerLogo, showCloseButton } = $props();
13
13
  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);
14
14
  const singleWebViewPage = $derived.by(() => {
15
15
  var _a;
@@ -122,9 +122,11 @@ const trackNavigationButtonsSize = (node) => {
122
122
  </div>
123
123
  {/if}
124
124
 
125
- <button type="button" class="close-button" onclick={on.closePlayer}>
126
- <Icon src={IconDismiss} />
127
- </button>
125
+ {#if showCloseButton}
126
+ <button type="button" class="close-button" onclick={on.closePlayer}>
127
+ <Icon src={IconDismiss} />
128
+ </button>
129
+ {/if}
128
130
 
129
131
  <style>@keyframes fadeIn {
130
132
  0% {
@@ -240,7 +242,7 @@ const trackNavigationButtonsSize = (node) => {
240
242
  min-height: 3rem;
241
243
  max-height: 3rem;
242
244
  background-color: rgba(0, 0, 0, 0.6);
243
- border: 0.0625rem solid #1c1c1c;
245
+ border: 1px solid #1c1c1c;
244
246
  border-radius: 50%;
245
247
  text-align: center;
246
248
  --icon--color: #ffffff;
@@ -251,14 +253,14 @@ const trackNavigationButtonsSize = (node) => {
251
253
  z-index: 1;
252
254
  /* Set 'container-type: inline-size;' to reference container*/
253
255
  }
254
- .close-button:disabled {
255
- opacity: 0.5;
256
- cursor: default;
257
- }
258
256
  .close-button:hover {
259
257
  background-color: rgba(0, 0, 0, 0.9);
260
258
  transition: background-color 0.5s;
261
259
  }
260
+ .close-button:disabled {
261
+ opacity: 0.5;
262
+ cursor: default;
263
+ }
262
264
  @container (width < 576px) {
263
265
  .close-button {
264
266
  left: unset;
@@ -275,12 +277,16 @@ const trackNavigationButtonsSize = (node) => {
275
277
  min-height: 3rem;
276
278
  max-height: 3rem;
277
279
  background-color: rgba(0, 0, 0, 0.6);
278
- border: 0.0625rem solid #1c1c1c;
280
+ border: 1px solid #1c1c1c;
279
281
  border-radius: 50%;
280
282
  text-align: center;
281
283
  --icon--color: #ffffff;
282
284
  --icon--size: 1.75rem;
283
285
  }
286
+ .navigation-button:hover {
287
+ background-color: rgba(0, 0, 0, 0.9);
288
+ transition: background-color 0.5s;
289
+ }
284
290
  .navigation-button:disabled {
285
291
  opacity: 0.5;
286
292
  cursor: default;
@@ -8,6 +8,7 @@ type Props = {
8
8
  postSocialInteractionsHandler?: IPostSocialInteractionsHandler;
9
9
  localization: StreamPlayerLocalization;
10
10
  playerLogo: string | null;
11
+ showCloseButton: boolean;
11
12
  on: {
12
13
  closePlayer: () => void;
13
14
  productClick?: (productId: string) => void;
@@ -118,9 +118,9 @@ const overviewAttached = (node) => {
118
118
  }
119
119
  @container (width < 576px) {
120
120
  .stream-overview {
121
- width: 100%;
122
- min-width: 100%;
123
- max-width: 100%;
121
+ width: calc(100% - 80px);
122
+ min-width: calc(100% - 80px);
123
+ max-width: calc(100% - 80px);
124
124
  }
125
125
  }
126
126
 
@@ -131,6 +131,8 @@ const overviewAttached = (node) => {
131
131
  z-index: 1;
132
132
  --icon--color: #ffffff;
133
133
  --icon--size: 1.25rem;
134
+ opacity: var(--stream-player--elements-opacity);
135
+ transition: opacity 0.3s ease-in-out;
134
136
  /* Set 'container-type: inline-size;' to reference container*/
135
137
  }
136
138
  .toggle-collapsed-button--left {
@@ -13,6 +13,7 @@ import { toastrWarning } from '../../core/toastr';
13
13
  import { ShortVideoViewer } from '../../short-videos/short-video-viewer';
14
14
  import { mapToShortVideoViewerModel } from '../layout/models';
15
15
  import { StreamPageViewer } from '../stream-page-viewer';
16
+ import { Icon } from '../../ui/icon';
16
17
  import { Loading } from '../../ui/loading';
17
18
  import { PlayerSlider } from '../../ui/player';
18
19
  import { SpotlightLayout } from '../../ui/spotlight-layout';
@@ -22,6 +23,7 @@ import { default as Overview } from './stream-overview.svelte';
22
23
  import { StreamPlayerBuffer } from './stream-player-buffer.svelte';
23
24
  import { StreamPlayerLocalization } from './stream-player-localization';
24
25
  import { StreamPlayerUiManager } from './ui-manager.svelte';
26
+ import IconDismiss from '@fluentui/svg-icons/icons/dismiss_28_regular.svg?raw';
25
27
  import { onMount, untrack } from 'svelte';
26
28
  let { streamId, dataProvider, analyticsHandler, locale = 'en', showStreamsCloudWatermark, postSocialInteractionsHandler, on, categoriesSwitcher, playerLogo = null, fadeContent = false } = $props();
27
29
  const localization = $derived(new StreamPlayerLocalization(locale));
@@ -36,7 +38,6 @@ let isActive = true;
36
38
  let activityTimeout = null;
37
39
  let trackingInterval = null;
38
40
  let maxPageIndexViewed = 0;
39
- let background = $state(null);
40
41
  const uiManager = new StreamPlayerUiManager();
41
42
  const resetInactivityTimer = () => {
42
43
  if (!isActive) {
@@ -80,7 +81,7 @@ const initBuffer = (dataProvider) => __awaiter(void 0, void 0, void 0, function*
80
81
  if (coverUrl) {
81
82
  yield preloadImage(coverUrl);
82
83
  }
83
- background = coverUrl;
84
+ uiManager.setBackgroundImageUrl(coverUrl);
84
85
  }
85
86
  buffer = instance;
86
87
  bufferIsLoading = false;
@@ -157,7 +158,7 @@ const contentMounted = (node) => {
157
158
  };
158
159
  const onPageActivated = (id) => {
159
160
  const page = buffer === null || buffer === void 0 ? void 0 : buffer.loaded.find((x) => x.id === id);
160
- background = (page === null || page === void 0 ? void 0 : page.cover) || null;
161
+ uiManager.setBackgroundImageUrl((page === null || page === void 0 ? void 0 : page.cover) || null);
161
162
  if (page) {
162
163
  analyticsHandler === null || analyticsHandler === void 0 ? void 0 : analyticsHandler.trackStreamPageView(id, streamId);
163
164
  if (page.type === 'short-video' && page.shortVideo) {
@@ -203,16 +204,24 @@ const onProgress = (pageId, videoId, progress) => {
203
204
 
204
205
  <div
205
206
  class="stream-player-container"
206
- class:stream-player-container--background-loading={!background}
207
+ class:stream-player-container--background-loading={!uiManager.isMobileView}
207
208
  class:stream-player-container--faded={fadeContent}
208
- style={background ? `--background-image: url(${background})` : null}>
209
+ style={uiManager.globalCssVariables}>
209
210
  {#if categoriesSwitcher}
210
- {@render categoriesSwitcher({
211
- maxItemsWidth: Math.min(uiManager.mainViewColumnWidth * 1.4, uiManager.viewTotalWidth),
212
- onMounted: onMediaCenterHeaderMounted
213
- })}
211
+ {#snippet closeButton()}
212
+ <button type="button" class="close-button" onclick={onPlayerClose}>
213
+ <Icon src={IconDismiss} />
214
+ </button>
215
+ {/snippet}
216
+ <div class="stream-player-container__media-center">
217
+ {@render categoriesSwitcher({
218
+ maxItemsWidth: Math.min(uiManager.mainViewColumnWidth * 1.4, uiManager.viewTotalWidth),
219
+ onMounted: onMediaCenterHeaderMounted,
220
+ closeButton: on?.playerClosed && closeButton
221
+ })}
222
+ </div>
214
223
  {/if}
215
- <div class="stream-player" style={uiManager.globalCssVariables}>
224
+ <div class="stream-player">
216
225
  {#if showStreamsCloudWatermark}
217
226
  <div class="stream-player__watermark">
218
227
  <a href="https://streamscloud.com/" tabindex="-1" aria-label="none">
@@ -278,6 +287,7 @@ const onProgress = (pageId, videoId, progress) => {
278
287
  localization={localization}
279
288
  postSocialInteractionsHandler={postSocialInteractionsHandler}
280
289
  playerLogo={playerLogo}
290
+ showCloseButton={!categoriesSwitcher}
281
291
  on={{
282
292
  closePlayer: () => onPlayerClose(),
283
293
  productClick: (productId: String) => onProductCardClick(productId),
@@ -314,7 +324,7 @@ const onProgress = (pageId, videoId, progress) => {
314
324
  }
315
325
  .stream-player-container {
316
326
  background-color: #c1c1c1;
317
- background-image: var(--background-image);
327
+ background-image: var(--stream-player--background-image-url);
318
328
  background-size: cover;
319
329
  background-blend-mode: multiply;
320
330
  }
@@ -324,6 +334,13 @@ const onProgress = (pageId, videoId, progress) => {
324
334
  .stream-player-container--faded {
325
335
  --stream-player--elements-opacity: 0;
326
336
  }
337
+ .stream-player-container__media-center {
338
+ position: absolute;
339
+ top: 0;
340
+ left: var(--stream-player--overview--width);
341
+ right: var(--stream-player--overview--width);
342
+ z-index: 1;
343
+ }
327
344
 
328
345
  .stream-player {
329
346
  display: flex;
@@ -350,4 +367,27 @@ const onProgress = (pageId, videoId, progress) => {
350
367
  height: 100%;
351
368
  opacity: var(--stream-player--elements-opacity);
352
369
  transition: opacity 0.3s ease-in-out;
370
+ }
371
+
372
+ .close-button {
373
+ width: 3rem;
374
+ min-width: 3rem;
375
+ max-width: 3rem;
376
+ height: 3rem;
377
+ min-height: 3rem;
378
+ max-height: 3rem;
379
+ background-color: rgba(0, 0, 0, 0.6);
380
+ border: 1px solid #1c1c1c;
381
+ border-radius: 50%;
382
+ text-align: center;
383
+ --icon--color: #ffffff;
384
+ --icon--size: 1.75rem;
385
+ }
386
+ .close-button:hover {
387
+ background-color: rgba(0, 0, 0, 0.9);
388
+ transition: background-color 0.5s;
389
+ }
390
+ .close-button:disabled {
391
+ opacity: 0.5;
392
+ cursor: default;
353
393
  }</style>
@@ -6,6 +6,7 @@ type $$ComponentProps = StreamPlayerProps & {
6
6
  onMounted: (data: {
7
7
  height: number;
8
8
  }) => void;
9
+ closeButton?: Snippet;
9
10
  }]>;
10
11
  playerLogo?: string | null;
11
12
  fadeContent?: boolean;
@@ -6,6 +6,7 @@ export declare class StreamPlayerUiManager {
6
6
  viewInitialized: boolean;
7
7
  showShortVideoOverlayAttachments: boolean;
8
8
  showShortVideoOverlayControls: boolean;
9
+ private _backgroundImageUrl;
9
10
  private _viewTotalWidth;
10
11
  private _mainViewColumnWidth;
11
12
  private _mediaCenterHeaderHeight;
@@ -16,6 +17,7 @@ export declare class StreamPlayerUiManager {
16
17
  private _controlsContentWidth;
17
18
  get viewTotalWidth(): number;
18
19
  get mainViewColumnWidth(): number;
20
+ get backgroundImageUrl(): string | null;
19
21
  updateDimensions: (dimensions: {
20
22
  viewTotalWidth: number;
21
23
  mainViewColumnWidth: number;
@@ -24,4 +26,5 @@ export declare class StreamPlayerUiManager {
24
26
  updateMediaCenterHeaderHeight: (height: number) => void;
25
27
  setAttachmentsPanelWidth: (width: number) => void;
26
28
  setNavigationButtonsBlockWidth: (width: number) => void;
29
+ setBackgroundImageUrl: (url: string | null) => void;
27
30
  }
@@ -14,12 +14,16 @@ export class StreamPlayerUiManager {
14
14
  `--stream-player--overview--width: ${this._overviewWidth}px`,
15
15
  `--stream-player--padding: ${this._mediaCenterHeaderHeight ? this._mediaCenterHeaderHeight : PLAYER_PADDING_VERTICAL}px 0 ${PLAYER_PADDING_VERTICAL}px`
16
16
  ];
17
+ if (this._backgroundImageUrl) {
18
+ values.push(`--stream-player--background-image-url: url(${this._backgroundImageUrl})`);
19
+ }
17
20
  return values.join(';');
18
21
  });
19
22
  isMobileView = $derived.by(() => this._viewTotalWidth <= 576);
20
23
  viewInitialized = $derived.by(() => !!this._viewTotalWidth && !!this._mainViewColumnWidth);
21
24
  showShortVideoOverlayAttachments = $derived.by(() => this.viewInitialized && this._controlsAttachmentsPanelWidth < CONTROLS_ATTACHMENTS_MAX_WIDTH + 10);
22
25
  showShortVideoOverlayControls = $derived.by(() => this.viewInitialized && this._controlsContentWidth < this._controlsNavitagionButtonsWidth);
26
+ _backgroundImageUrl = $state(null);
23
27
  _viewTotalWidth = $state(0);
24
28
  _mainViewColumnWidth = $state(0);
25
29
  _mediaCenterHeaderHeight = $state(0);
@@ -34,6 +38,9 @@ export class StreamPlayerUiManager {
34
38
  get mainViewColumnWidth() {
35
39
  return this._mainViewColumnWidth;
36
40
  }
41
+ get backgroundImageUrl() {
42
+ return this._backgroundImageUrl;
43
+ }
37
44
  updateDimensions = (dimensions) => {
38
45
  this._viewTotalWidth = dimensions.viewTotalWidth;
39
46
  this._mainViewColumnWidth = dimensions.mainViewColumnWidth;
@@ -50,4 +57,7 @@ export class StreamPlayerUiManager {
50
57
  setNavigationButtonsBlockWidth = (width) => {
51
58
  this._controlsNavitagionButtonsWidth = width;
52
59
  };
60
+ setBackgroundImageUrl = (url) => {
61
+ this._backgroundImageUrl = url;
62
+ };
53
63
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@streamscloud/embeddable",
3
- "version": "7.0.0-1758321646285",
3
+ "version": "7.0.0",
4
4
  "author": "StreamsCloud",
5
5
  "repository": {
6
6
  "type": "git",