@streamscloud/embeddable 17.0.5 → 18.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.
Files changed (27) hide show
  1. package/package.json +1 -5
  2. package/dist/feed-player/cmp.close-button.svelte +0 -40
  3. package/dist/feed-player/cmp.close-button.svelte.d.ts +0 -19
  4. package/dist/feed-player/cmp.feed-player.svelte +0 -543
  5. package/dist/feed-player/cmp.feed-player.svelte.d.ts +0 -15
  6. package/dist/feed-player/feed-player-localization.d.ts +0 -16
  7. package/dist/feed-player/feed-player-localization.js +0 -70
  8. package/dist/feed-player/index.d.ts +0 -3
  9. package/dist/feed-player/index.js +0 -2
  10. package/dist/feed-player/sidebar/article-tab.svelte +0 -98
  11. package/dist/feed-player/sidebar/article-tab.svelte.d.ts +0 -19
  12. package/dist/feed-player/sidebar/information-tab.svelte +0 -98
  13. package/dist/feed-player/sidebar/information-tab.svelte.d.ts +0 -26
  14. package/dist/feed-player/sidebar/playlist-tab.svelte +0 -115
  15. package/dist/feed-player/sidebar/playlist-tab.svelte.d.ts +0 -19
  16. package/dist/feed-player/sidebar/post-card.svelte +0 -127
  17. package/dist/feed-player/sidebar/post-card.svelte.d.ts +0 -24
  18. package/dist/feed-player/sidebar/recommended-tab.svelte +0 -169
  19. package/dist/feed-player/sidebar/recommended-tab.svelte.d.ts +0 -19
  20. package/dist/feed-player/sidebar/sidebar-panel.svelte +0 -71
  21. package/dist/feed-player/sidebar/sidebar-panel.svelte.d.ts +0 -28
  22. package/dist/feed-player/sidebar/sidebar-tab-bar.svelte +0 -49
  23. package/dist/feed-player/sidebar/sidebar-tab-bar.svelte.d.ts +0 -21
  24. package/dist/feed-player/sidebar/types.d.ts +0 -4
  25. package/dist/feed-player/sidebar/types.js +0 -1
  26. package/dist/feed-player/types.d.ts +0 -67
  27. package/dist/feed-player/types.js +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@streamscloud/embeddable",
3
- "version": "17.0.5",
3
+ "version": "18.0.0",
4
4
  "author": "StreamsCloud",
5
5
  "repository": {
6
6
  "type": "git",
@@ -42,10 +42,6 @@
42
42
  "types": "./dist/external-api/index.d.ts",
43
43
  "svelte": "./dist/external-api/index.js"
44
44
  },
45
- "./feed-player": {
46
- "types": "./dist/feed-player/index.d.ts",
47
- "svelte": "./dist/feed-player/index.js"
48
- },
49
45
  "./media-center": {
50
46
  "types": "./dist/media-center/index.d.ts",
51
47
  "svelte": "./dist/media-center/index.js"
@@ -1,40 +0,0 @@
1
- <script lang="ts">import IconDismiss from '@fluentui/svg-icons/icons/dismiss_20_regular.svg?raw';
2
- import { Icon } from '@streamscloud/kit/ui/icon';
3
- const { on } = $props();
4
- </script>
5
-
6
- <button type="button" class="close-button" onclick={() => on?.click?.()}>
7
- <Icon src={IconDismiss} />
8
- </button>
9
-
10
- <!--
11
- @component
12
- Round close button — 32px circle with dismiss icon.
13
-
14
- ### CSS Custom Properties
15
- | Property | Description | Default |
16
- |---|---|---|
17
- | `--sc-fp--close-button--size` | Button size | `32px` |
18
- | `--sc-fp--close-button--background` | Button background | `light-dark(#f1f6fd, #2a2a2a)` |
19
- | `--sc-fp--close-button--color` | Icon color | `currentColor` |
20
- | `--sc-fp--close-button--icon-size` | Icon size | `16px` |
21
- -->
22
-
23
- <style>.close-button {
24
- --_close-button--size: var(--sc-fp--close-button--size, 2rem);
25
- --_close-button--background: var(--sc-fp--close-button--background, light-dark(#f1f6fd, #2a2a2a));
26
- --_close-button--color: var(--sc-fp--close-button--color, light-dark(#000000, #ffffff));
27
- --_close-button--icon-size: var(--sc-fp--close-button--icon-size, 1rem);
28
- display: flex;
29
- align-items: center;
30
- justify-content: center;
31
- width: var(--_close-button--size);
32
- height: var(--_close-button--size);
33
- padding: 0;
34
- background: var(--_close-button--background);
35
- border: none;
36
- border-radius: 50%;
37
- cursor: pointer;
38
- --sc-kit--icon--size: var(--_close-button--icon-size);
39
- --sc-kit--icon--color: var(--_close-button--color);
40
- }</style>
@@ -1,19 +0,0 @@
1
- type Props = {
2
- on?: {
3
- click?: () => void;
4
- };
5
- };
6
- /**
7
- * Round close button — 32px circle with dismiss icon.
8
- *
9
- * ### CSS Custom Properties
10
- * | Property | Description | Default |
11
- * |---|---|---|
12
- * | `--sc-fp--close-button--size` | Button size | `32px` |
13
- * | `--sc-fp--close-button--background` | Button background | `light-dark(#f1f6fd, #2a2a2a)` |
14
- * | `--sc-fp--close-button--color` | Icon color | `currentColor` |
15
- * | `--sc-fp--close-button--icon-size` | Icon size | `16px` |
16
- */
17
- declare const Cmp: import("svelte").Component<Props, {}, "">;
18
- type Cmp = ReturnType<typeof Cmp>;
19
- export default Cmp;
@@ -1,543 +0,0 @@
1
- <script lang="ts">import { PostActionsGenerator } from '../posts/controls';
2
- import { getPostCoverImage, PostModel } from '../posts/model';
3
- import { PostViewer } from '../posts/post-viewer';
4
- import { default as CloseButton } from './cmp.close-button.svelte';
5
- import { FeedPlayerLocalization } from './feed-player-localization';
6
- import { default as SidebarPanel } from './sidebar/sidebar-panel.svelte';
7
- import IconChevronDown from '@fluentui/svg-icons/icons/chevron_down_28_regular.svg?raw';
8
- import IconChevronUp from '@fluentui/svg-icons/icons/chevron_up_28_regular.svg?raw';
9
- import IconInfo from '@fluentui/svg-icons/icons/info_24_regular.svg?raw';
10
- import { AppLocale } from '@streamscloud/kit/core/locale';
11
- import { slideHorizontally } from '@streamscloud/kit/core/transitions';
12
- import { preloadImage } from '@streamscloud/kit/core/utils';
13
- import { Loading } from '@streamscloud/kit/ui/loading';
14
- import { PlayerButtons } from '@streamscloud/kit/ui/player/buttons';
15
- import { FeedSlider } from '@streamscloud/kit/ui/player/feed-slider';
16
- import { initBufferFromProvider } from '@streamscloud/kit/ui/player/providers';
17
- import { untrack } from 'svelte';
18
- let { dataProvider, socialInteractionsHandler, sharingHandler, analyticsHandler, recommendedHandler, playlistHandler, trackingParams: externalTrackingParams, settings, header, on } = $props();
19
- $effect(() => {
20
- if (settings?.locale) {
21
- AppLocale.change(settings.locale);
22
- }
23
- });
24
- const localization = new FeedPlayerLocalization();
25
- // ── Mode ──
26
- const isPreview = $derived(settings?.mode === 'preview');
27
- // ── Background mode ──
28
- const isGlassBackground = $derived(settings?.background === 'glass');
29
- const isTransparentBackground = $derived(settings?.background === 'transparent');
30
- let backgroundImageUrl = $state(null);
31
- // ── Buffer ──
32
- let buffer = $state.raw(null);
33
- $effect(() => {
34
- void dataProvider;
35
- untrack(() => {
36
- buffer = null;
37
- backgroundImageUrl = null;
38
- mappedPostsCache = {};
39
- initBuffer();
40
- });
41
- });
42
- const initBuffer = async () => {
43
- const newBuffer = initBufferFromProvider(dataProvider);
44
- await newBuffer.ensureWarmedUp();
45
- if (newBuffer.loaded.length) {
46
- const coverUrl = getPostCoverImage(newBuffer.loaded[0]);
47
- await preloadImage(coverUrl);
48
- backgroundImageUrl = coverUrl;
49
- }
50
- buffer = newBuffer;
51
- };
52
- // ── PostModel cache ──
53
- let mappedPostsCache = {};
54
- const itemAsPostModel = (item) => {
55
- if (mappedPostsCache[item.id]) {
56
- return mappedPostsCache[item.id];
57
- }
58
- const postModel = new PostModel(item);
59
- mappedPostsCache[item.id] = postModel;
60
- return postModel;
61
- };
62
- // ── Current post ──
63
- const currentPostModel = $derived.by(() => {
64
- if (!buffer?.current) {
65
- return null;
66
- }
67
- return itemAsPostModel(buffer.current);
68
- });
69
- const currentTrackingParams = $derived.by(() => {
70
- if (externalTrackingParams === false) {
71
- return false;
72
- }
73
- const shortVideoId = currentPostModel?.postType === 'SHORT_VIDEO' ? currentPostModel.id : undefined;
74
- if (!externalTrackingParams && !shortVideoId) {
75
- return false;
76
- }
77
- return { ...externalTrackingParams, shortVideoId };
78
- });
79
- const hasProducts = $derived(!!currentPostModel?.attachments && currentPostModel.attachments.products.length > 0);
80
- const isArticle = $derived(currentPostModel?.postType === 'ARTICLE' && !!currentPostModel.articleId);
81
- const hasAttachments = $derived(!!currentPostModel?.attachments);
82
- // ── Sidebar tabs ──
83
- let preferredTab = $state('information');
84
- let activeSidebarTab = $state('information');
85
- let selectedProductId = $state(null);
86
- const visibleTabs = $derived.by(() => {
87
- const tabs = [];
88
- if (hasAttachments) {
89
- tabs.push({ id: 'information', label: localization.tabInformation });
90
- }
91
- if (hasProducts) {
92
- tabs.push({ id: 'product', label: localization.tabProduct });
93
- }
94
- if (isArticle) {
95
- tabs.push({ id: 'article', label: localization.tabArticle });
96
- }
97
- if (recommendedHandler) {
98
- tabs.push({ id: 'recommended', label: localization.tabRecommended });
99
- }
100
- if (playlistHandler) {
101
- tabs.push({ id: 'playlist', label: localization.tabPlaylist });
102
- }
103
- return tabs;
104
- });
105
- const sidebarVisible = $derived(visibleTabs.length > 0);
106
- const handleTabChange = (id) => {
107
- preferredTab = id;
108
- activeSidebarTab = id;
109
- };
110
- // Tab resolution: preferred tab if available, otherwise first visible
111
- $effect(() => {
112
- const tabs = visibleTabs;
113
- if (tabs.length === 0) {
114
- return;
115
- }
116
- if (tabs.some((t) => t.id === preferredTab)) {
117
- activeSidebarTab = preferredTab;
118
- }
119
- else {
120
- activeSidebarTab = tabs[0].id;
121
- }
122
- });
123
- // Reset selectedProductId on post change
124
- $effect(() => {
125
- const post = currentPostModel;
126
- untrack(() => {
127
- if (post?.attachments && post.attachments.products.length > 0) {
128
- selectedProductId = post.attachments.products[0].id;
129
- }
130
- else {
131
- selectedProductId = null;
132
- }
133
- });
134
- });
135
- // ── Sidebar collapsed (user toggle) ──
136
- let sidebarCollapsed = $state(false);
137
- // ── Layout ──
138
- const SAFE_AREA_SIZE = 80;
139
- const SIDEBAR_WIDTH = 378;
140
- const MOBILE_BREAKPOINT = 576;
141
- // Measured from the root element
142
- let totalWidth = $state(0);
143
- let isMobileView = $derived(totalWidth <= MOBILE_BREAKPOINT);
144
- const handleRootResize = (node) => {
145
- const observer = new ResizeObserver(([entry]) => {
146
- totalWidth = entry.contentRect.width;
147
- });
148
- observer.observe(node);
149
- return { destroy: () => observer.disconnect() };
150
- };
151
- // Measured from header
152
- let headerHeight = $state(0);
153
- const handleHeaderResize = (node) => {
154
- const observer = new ResizeObserver(([entry]) => {
155
- headerHeight = entry.contentRect.height;
156
- });
157
- observer.observe(node);
158
- return { destroy: () => observer.disconnect() };
159
- };
160
- // Measured from video-area
161
- let contentViewWidth = $state(0);
162
- let videoAreaWidth = $state(0);
163
- let videoAreaHeight = $state(0);
164
- // Priority: sidebar hides first, then video shrinks, then controls go overlay
165
- // Step 1: Would sidebar + video + safe areas fit?
166
- const sidebarCanBeShown = $derived.by(() => {
167
- if (!sidebarVisible || isMobileView || videoAreaHeight === 0) {
168
- return false;
169
- }
170
- // Estimate video width from height at 9:16
171
- const videoW = videoAreaHeight * (9 / 16);
172
- const areaWithSidebar = totalWidth - SIDEBAR_WIDTH;
173
- const sideSpace = (areaWithSidebar - videoW) / 2;
174
- return sideSpace >= SAFE_AREA_SIZE;
175
- });
176
- const sidebarWidth = $derived(sidebarCanBeShown && !sidebarCollapsed ? SIDEBAR_WIDTH : 0);
177
- // Step 2: Controls overlay — only when side space without sidebar is still too small
178
- const sidePanelsMaxWidth = $derived((videoAreaWidth - contentViewWidth) / 2);
179
- const showControlsOverlay = $derived(isMobileView);
180
- // ResizeObserver on video-area — same logic as generic player's handleSliderMounted
181
- const handleVideoAreaResize = (node) => {
182
- const observer = new ResizeObserver(([entry]) => {
183
- const { width: areaW, height: areaH } = entry.contentRect;
184
- videoAreaWidth = areaW;
185
- videoAreaHeight = areaH;
186
- const ratio = 9 / 16;
187
- let width;
188
- let height;
189
- let margin;
190
- let contentWidthNumber = areaW;
191
- if (isMobileView) {
192
- width = '100%';
193
- height = '100%';
194
- margin = '0';
195
- }
196
- else {
197
- // On desktop, reserve safe area on each side for controls
198
- const maxContentWidth = areaW - 2 * SAFE_AREA_SIZE;
199
- const heightBasedWidth = areaH * ratio;
200
- contentWidthNumber = Math.min(maxContentWidth, heightBasedWidth);
201
- width = `${contentWidthNumber}px`;
202
- height = `${contentWidthNumber / ratio}px`;
203
- margin = 'auto';
204
- }
205
- node.style.setProperty('--_feed-player--content--width', width);
206
- node.style.setProperty('--_feed-player--content--height', height);
207
- node.style.setProperty('--_feed-player--content--margin', margin);
208
- contentViewWidth = contentWidthNumber;
209
- });
210
- observer.observe(node);
211
- return { destroy: () => observer.disconnect() };
212
- };
213
- // ── Callbacks ──
214
- const handleItemActivated = (id) => {
215
- if (buffer) {
216
- const item = buffer.loaded.find((i) => i.id === id);
217
- if (item) {
218
- backgroundImageUrl = getPostCoverImage(item);
219
- if (item.postType === 'SHORT_VIDEO') {
220
- analyticsHandler?.trackShortVideoView(id);
221
- }
222
- else if (item.postType) {
223
- analyticsHandler?.trackPostOpened(item.postType, id);
224
- }
225
- }
226
- }
227
- on?.postActivated?.(id);
228
- };
229
- // ── Analytics callbacks ──
230
- const onProductClick = (productId) => {
231
- if (!currentPostModel) {
232
- return;
233
- }
234
- if (currentPostModel.postType === 'SHORT_VIDEO') {
235
- analyticsHandler?.trackShortVideoProductClick(productId, currentPostModel.id);
236
- }
237
- };
238
- const onProductImpression = (productId) => {
239
- if (!currentPostModel) {
240
- return;
241
- }
242
- if (currentPostModel.postType === 'SHORT_VIDEO') {
243
- analyticsHandler?.trackShortVideoProductImpression(productId, currentPostModel.id);
244
- }
245
- };
246
- const onAdClick = (adId) => {
247
- analyticsHandler?.trackAdClick(adId);
248
- };
249
- const onAdImpression = (adId) => {
250
- analyticsHandler?.trackAdImpression(adId);
251
- };
252
- // ── Action buttons (like, share, attachments toggle) ──
253
- const postActionsGenerator = untrack(() => new PostActionsGenerator({
254
- get socialInteractionsHandler() {
255
- return socialInteractionsHandler;
256
- },
257
- get sharingHandler() {
258
- return sharingHandler;
259
- },
260
- on: { attachmentClicked: () => (sidebarCollapsed = !sidebarCollapsed) }
261
- }));
262
- const itemActions = $derived.by(() => {
263
- if (!currentPostModel) {
264
- return [];
265
- }
266
- const handler = postActionsGenerator.getPostActionsHandler(currentPostModel);
267
- const actions = [...handler.actions];
268
- if (sidebarCanBeShown) {
269
- actions.push({ icon: IconInfo, callback: () => (sidebarCollapsed = !sidebarCollapsed) });
270
- }
271
- return actions;
272
- });
273
- </script>
274
-
275
- <div
276
- class="feed-player"
277
- class:feed-player--glass={isGlassBackground}
278
- class:feed-player--glass-active={isGlassBackground && backgroundImageUrl}
279
- class:feed-player--transparent={isTransparentBackground}
280
- style:--_feed-player--background-image-url={backgroundImageUrl ? `url(${backgroundImageUrl})` : undefined}
281
- use:handleRootResize>
282
- <div class="feed-player__main">
283
- {#if header}
284
- <div class="feed-player__header" use:handleHeaderResize>
285
- {@render header()}
286
- </div>
287
- {/if}
288
- {#if buffer}
289
- <div class="feed-player__video-area" class:feed-player__video-area--with-header={!!header} use:handleVideoAreaResize>
290
- <FeedSlider buffer={buffer} on={{ itemActivated: handleItemActivated }}>
291
- {#snippet children({ item })}
292
- {@const postModel = itemAsPostModel(item)}
293
- <div class="feed-player__content">
294
- <PostViewer
295
- model={postModel}
296
- controlActions={itemActions}
297
- trackingParams={externalTrackingParams ?? null}
298
- enableAttachments={false}
299
- enableControls={showControlsOverlay}
300
- autoplay="on-appearance"
301
- on={isPreview
302
- ? {}
303
- : {
304
- productClick: onProductClick,
305
- productImpression: onProductImpression,
306
- adClick: onAdClick,
307
- adImpression: onAdImpression,
308
- articleReadMore: (id) => on?.articleReadMore?.(id)
309
- }} />
310
- </div>
311
- {/snippet}
312
- </FeedSlider>
313
-
314
- {#if !showControlsOverlay}
315
- <div class="feed-player__controls" style:--_feed-player--controls-width="{sidePanelsMaxWidth}px">
316
- <div class="feed-player__controls-spacer">&nbsp;</div>
317
- <div class="feed-player__controls-left">
318
- <PlayerButtons actions={itemActions} scaleEffect={true} />
319
-
320
- {#if buffer && buffer.loaded.length > 1}
321
- <div class="feed-player__navigation">
322
- <PlayerButtons actions={[{ icon: IconChevronUp, callback: buffer.loadPrevious, disabled: !buffer.canLoadPrevious }]} scaleEffect={true} />
323
- <PlayerButtons actions={[{ icon: IconChevronDown, callback: buffer.loadNext, disabled: !buffer.canLoadNext }]} scaleEffect={true} />
324
- </div>
325
- {/if}
326
- </div>
327
- <div class="feed-player__controls-spacer feed-player__controls-spacer--right">&nbsp;</div>
328
- </div>
329
- {/if}
330
- </div>
331
- {/if}
332
- </div>
333
- {#if buffer}
334
- <div class="feed-player__sidebar-container">
335
- {#if on?.closed}
336
- <div class="feed-player__close">
337
- <CloseButton on={{ click: on.closed }} />
338
- </div>
339
- {/if}
340
-
341
- {#if sidebarWidth > 0 && currentPostModel}
342
- <div
343
- class="feed-player__sidebar"
344
- class:feed-player__sidebar--with-close={on?.closed}
345
- class:feed-player__sidebar--with-header={!on?.closed && !!header}
346
- style:--_--feed-player--sidebar--width={SIDEBAR_WIDTH + 'px'}
347
- style:--_--feed-player--header-height={headerHeight + 'px'}
348
- transition:slideHorizontally|local>
349
- <SidebarPanel
350
- tabs={visibleTabs}
351
- activeTabId={activeSidebarTab}
352
- model={currentPostModel}
353
- trackingParams={currentTrackingParams}
354
- selectedProductId={selectedProductId}
355
- interactionsDisabled={isPreview}
356
- recommendedHandler={recommendedHandler}
357
- playlistHandler={playlistHandler}
358
- on={isPreview
359
- ? { tabChange: () => {} }
360
- : {
361
- tabChange: handleTabChange,
362
- productClick: onProductClick,
363
- productImpression: onProductImpression,
364
- productBuy: on?.productBuy,
365
- productSelect: (id) => {
366
- selectedProductId = id;
367
- handleTabChange('product');
368
- },
369
- adClick: onAdClick,
370
- adImpression: onAdImpression,
371
- articleReadMore: on?.articleReadMore,
372
- postActivate: (id) => buffer?.tryActivateItemById(id)
373
- }} />
374
- </div>
375
- {/if}
376
- </div>
377
- {/if}
378
- {#if !buffer}
379
- <Loading positionAbsoluteCenter={true} timeout={500} />
380
- {/if}
381
- </div>
382
-
383
- <!--
384
- @component
385
- Vertical post feed player with a tabbed sidebar for products, articles, and recommendations.
386
-
387
- ### CSS Custom Properties
388
- | Property | Description | Default |
389
- |---|---|---|
390
- | `--sc-fp--background` | Player background | `light-dark(white, black)` |
391
- | `--sc-fp--padding-left` | Left padding for video area offset | `0px` |
392
- | `--sc-fp--button--color` | Control button color | inherited |
393
- | `--sc-fp--button--color--inactive` | Inactive control button color | inherited |
394
- -->
395
-
396
- <style>.feed-player {
397
- --_feed-player--background: var(--sc-fp--background, light-dark(#ffffff, #000000));
398
- --_feed-player--padding-left: var(--sc-fp--padding-left, 0px);
399
- --_feed-player--button--color: var(--sc-fp--button--color);
400
- --_feed-player--button--color--inactive: var(--sc-fp--button--color--inactive);
401
- --post-viewer--button--color: var(--_feed-player--button--color);
402
- --post-viewer--button--color--inactive: var(--_feed-player--button--color--inactive);
403
- position: relative;
404
- width: 100%;
405
- height: 100%;
406
- display: flex;
407
- padding-left: var(--_feed-player--padding-left);
408
- background: var(--_feed-player--background);
409
- overflow: hidden;
410
- container-type: inline-size;
411
- }
412
- .feed-player::before {
413
- content: "";
414
- position: absolute;
415
- inset: 0;
416
- backdrop-filter: blur(1.875rem);
417
- background-color: rgb(from var(--_feed-player--background) r g b/50%);
418
- display: none;
419
- z-index: 0;
420
- }
421
- .feed-player--glass::before {
422
- display: block;
423
- }
424
- .feed-player--glass-active {
425
- background-image: var(--_feed-player--background-image-url);
426
- background-size: cover;
427
- background-position: center;
428
- }
429
- .feed-player--transparent {
430
- background: transparent;
431
- }
432
- .feed-player__main {
433
- display: flex;
434
- flex-direction: column;
435
- width: 100%;
436
- flex: 1;
437
- min-height: 0;
438
- position: relative;
439
- z-index: 1;
440
- }
441
- .feed-player__header {
442
- position: relative;
443
- flex-shrink: 0;
444
- display: flex;
445
- justify-content: center;
446
- align-items: center;
447
- z-index: 1;
448
- pointer-events: none;
449
- /* Set 'container-type: inline-size;' to reference container*/
450
- }
451
- @container (width < 576px) {
452
- .feed-player__header {
453
- position: absolute;
454
- top: 0;
455
- left: 0;
456
- right: 0;
457
- z-index: 2;
458
- }
459
- }
460
- .feed-player__video-area {
461
- flex: 1;
462
- min-width: 0;
463
- min-height: 0;
464
- position: relative;
465
- padding-top: 0.625rem;
466
- padding-bottom: 0.625rem;
467
- overflow: hidden;
468
- }
469
- .feed-player__video-area--with-header {
470
- padding-top: 0;
471
- }
472
- .feed-player__video-area {
473
- /* Set 'container-type: inline-size;' to reference container*/
474
- }
475
- @container (width < 576px) {
476
- .feed-player__video-area {
477
- padding: 0;
478
- }
479
- }
480
- .feed-player__content {
481
- width: var(--_feed-player--content--width, 100%);
482
- height: var(--_feed-player--content--height, 100%);
483
- margin: var(--_feed-player--content--margin, 0);
484
- position: relative;
485
- display: flex;
486
- justify-content: center;
487
- align-items: center;
488
- }
489
- .feed-player__controls {
490
- position: absolute;
491
- top: 0;
492
- right: 0;
493
- height: 100%;
494
- width: var(--_feed-player--controls-width);
495
- display: flex;
496
- padding: 0.625rem 0 1.875rem;
497
- pointer-events: none;
498
- }
499
- .feed-player__controls-spacer {
500
- flex: 0 0 1rem;
501
- }
502
- .feed-player__controls-spacer--right {
503
- flex: 1;
504
- }
505
- .feed-player__controls-left {
506
- display: flex;
507
- flex-direction: column;
508
- gap: 2.3125rem;
509
- justify-content: flex-end;
510
- align-items: center;
511
- pointer-events: auto;
512
- }
513
- .feed-player__navigation {
514
- display: flex;
515
- flex-direction: column;
516
- gap: 1rem;
517
- }
518
- .feed-player__sidebar-container {
519
- flex-shrink: 0;
520
- display: flex;
521
- flex-direction: column;
522
- align-items: flex-end;
523
- position: relative;
524
- z-index: 1;
525
- }
526
- .feed-player__close {
527
- position: absolute;
528
- top: 0.75rem;
529
- right: 1rem;
530
- z-index: 1;
531
- }
532
- .feed-player__sidebar {
533
- flex: 1;
534
- min-height: 0;
535
- width: var(--_--feed-player--sidebar--width);
536
- padding: 0.625rem 0.625rem 0.625rem 0;
537
- }
538
- .feed-player__sidebar--with-close {
539
- padding-top: 3.75rem;
540
- }
541
- .feed-player__sidebar--with-header {
542
- padding-top: var(--_--feed-player--header-height, 0px);
543
- }</style>
@@ -1,15 +0,0 @@
1
- import type { FeedPlayerProps } from './types';
2
- /**
3
- * Vertical post feed player with a tabbed sidebar for products, articles, and recommendations.
4
- *
5
- * ### CSS Custom Properties
6
- * | Property | Description | Default |
7
- * |---|---|---|
8
- * | `--sc-fp--background` | Player background | `light-dark(white, black)` |
9
- * | `--sc-fp--padding-left` | Left padding for video area offset | `0px` |
10
- * | `--sc-fp--button--color` | Control button color | inherited |
11
- * | `--sc-fp--button--color--inactive` | Inactive control button color | inherited |
12
- */
13
- declare const Cmp: import("svelte").Component<FeedPlayerProps, {}, "">;
14
- type Cmp = ReturnType<typeof Cmp>;
15
- export default Cmp;
@@ -1,16 +0,0 @@
1
- export declare class FeedPlayerLocalization {
2
- get tabInformation(): string;
3
- get tabProduct(): string;
4
- get tabArticle(): string;
5
- get tabRecommended(): string;
6
- get tabPlaylist(): string;
7
- get show(): string;
8
- get relatedPosts(): string;
9
- get suggestedPlaylist(): string;
10
- get suggestedProducts(): string;
11
- get showList(): string;
12
- get updatedLabel(): string;
13
- postsCount(count: number): string;
14
- postOf(current: number, total: number): string;
15
- viewsLabel(count: number): string;
16
- }