@streamscloud/embeddable 16.3.1 → 17.0.0-1775740482426
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/ads/ad-card/cmp.ad-card.svelte +11 -9
- package/dist/feed-player/cmp.close-button.svelte +40 -0
- package/dist/feed-player/cmp.close-button.svelte.d.ts +19 -0
- package/dist/feed-player/cmp.feed-player.svelte +516 -0
- package/dist/feed-player/cmp.feed-player.svelte.d.ts +14 -0
- package/dist/feed-player/feed-player-localization.d.ts +16 -0
- package/dist/feed-player/feed-player-localization.js +70 -0
- package/dist/feed-player/index.d.ts +3 -0
- package/dist/feed-player/index.js +2 -0
- package/dist/feed-player/sidebar/article-tab.svelte +98 -0
- package/dist/feed-player/sidebar/article-tab.svelte.d.ts +19 -0
- package/dist/feed-player/sidebar/information-tab.svelte +102 -0
- package/dist/feed-player/sidebar/information-tab.svelte.d.ts +26 -0
- package/dist/feed-player/sidebar/playlist-tab.svelte +110 -0
- package/dist/feed-player/sidebar/playlist-tab.svelte.d.ts +19 -0
- package/dist/feed-player/sidebar/post-card.svelte +128 -0
- package/dist/feed-player/sidebar/post-card.svelte.d.ts +24 -0
- package/dist/feed-player/sidebar/recommended-tab.svelte +165 -0
- package/dist/feed-player/sidebar/recommended-tab.svelte.d.ts +24 -0
- package/dist/feed-player/sidebar/sidebar-panel.svelte +84 -0
- package/dist/feed-player/sidebar/sidebar-panel.svelte.d.ts +28 -0
- package/dist/feed-player/sidebar/sidebar-tab-bar.svelte +45 -0
- package/dist/feed-player/sidebar/sidebar-tab-bar.svelte.d.ts +20 -0
- package/dist/feed-player/sidebar/types.d.ts +4 -0
- package/dist/feed-player/sidebar/types.js +1 -0
- package/dist/feed-player/types.d.ts +62 -0
- package/dist/feed-player/types.js +1 -0
- package/dist/posts/attachments/cmp.attachments.svelte +7 -2
- package/dist/posts/post-viewer/cmp.post-viewer.svelte +10 -7
- package/dist/posts/post-viewer/media/post-media.svelte +1 -2
- package/dist/posts/posts-player/posts-player-view.svelte +2 -0
- package/dist/products/product-card/cmp.product-card.svelte +16 -12
- package/dist/streams/streams-player/streams-player-view.svelte +2 -0
- package/dist/ui/media-items/media-item-view/cmp.media-item-view.svelte +1 -1
- package/package.json +7 -3
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
<script lang="ts">import { ProductCard } from '../../products/product-card';
|
|
2
|
+
import { FeedPlayerLocalization } from '../feed-player-localization';
|
|
3
|
+
import { default as PostCard } from './post-card.svelte';
|
|
4
|
+
import { Image } from '@streamscloud/kit/ui/image';
|
|
5
|
+
import { untrack } from 'svelte';
|
|
6
|
+
const { handler, currentPostId, trackingParams, on } = $props();
|
|
7
|
+
const localization = new FeedPlayerLocalization();
|
|
8
|
+
let data = $state.raw(null);
|
|
9
|
+
$effect(() => {
|
|
10
|
+
const postId = currentPostId;
|
|
11
|
+
untrack(() => {
|
|
12
|
+
data = null;
|
|
13
|
+
handler.getRecommendations(postId).then((result) => {
|
|
14
|
+
data = result;
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
</script>
|
|
19
|
+
|
|
20
|
+
{#if data}
|
|
21
|
+
<div class="recommended-tab">
|
|
22
|
+
{#if data.relatedPosts.length}
|
|
23
|
+
<div class="recommended-tab__section">
|
|
24
|
+
<div class="recommended-tab__section-title">{localization.relatedPosts}</div>
|
|
25
|
+
<div class="recommended-tab__posts">
|
|
26
|
+
{#each data.relatedPosts as post (post.id)}
|
|
27
|
+
<PostCard {post} thumbnailWidth={82} thumbnailHeight={146} thumbnailRadius={6} on={{ click: () => on?.postActivate?.(post.id) }} />
|
|
28
|
+
{/each}
|
|
29
|
+
</div>
|
|
30
|
+
</div>
|
|
31
|
+
{/if}
|
|
32
|
+
|
|
33
|
+
{#if data.suggestedPlaylists.length}
|
|
34
|
+
<div class="recommended-tab__section">
|
|
35
|
+
<div class="recommended-tab__section-title">{localization.suggestedPlaylist}</div>
|
|
36
|
+
<div class="recommended-tab__playlists">
|
|
37
|
+
{#each data.suggestedPlaylists as playlist (playlist.id)}
|
|
38
|
+
<div class="recommended-tab__playlist-card">
|
|
39
|
+
<div class="recommended-tab__playlist-thumbnail">
|
|
40
|
+
<Image src={playlist.thumbnailUrl} />
|
|
41
|
+
</div>
|
|
42
|
+
<div class="recommended-tab__playlist-info">
|
|
43
|
+
<div class="recommended-tab__playlist-name">{playlist.name}</div>
|
|
44
|
+
<div class="recommended-tab__playlist-count">{localization.postsCount(playlist.postsCount)}</div>
|
|
45
|
+
<div
|
|
46
|
+
class="recommended-tab__playlist-link"
|
|
47
|
+
onclick={() => on?.playlistSelect?.(playlist.id)}
|
|
48
|
+
onkeydown={() => {}}
|
|
49
|
+
role="none">{localization.showList}</div>
|
|
50
|
+
</div>
|
|
51
|
+
</div>
|
|
52
|
+
{/each}
|
|
53
|
+
</div>
|
|
54
|
+
</div>
|
|
55
|
+
{/if}
|
|
56
|
+
|
|
57
|
+
{#if data.suggestedProducts.length}
|
|
58
|
+
<div class="recommended-tab__section">
|
|
59
|
+
<div class="recommended-tab__section-title">{localization.suggestedProducts}</div>
|
|
60
|
+
<div class="recommended-tab__products">
|
|
61
|
+
{#each data.suggestedProducts as product (product.id)}
|
|
62
|
+
<div class="recommended-tab__product-wrapper">
|
|
63
|
+
<ProductCard
|
|
64
|
+
{product}
|
|
65
|
+
{trackingParams}
|
|
66
|
+
on={{ buy: on?.productBuy }} />
|
|
67
|
+
</div>
|
|
68
|
+
{/each}
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
71
|
+
{/if}
|
|
72
|
+
</div>
|
|
73
|
+
{/if}
|
|
74
|
+
|
|
75
|
+
<!--
|
|
76
|
+
@component
|
|
77
|
+
Recommended tab — shows related posts, suggested playlists, and suggested products.
|
|
78
|
+
|
|
79
|
+
### CSS Custom Properties
|
|
80
|
+
| Property | Description | Default |
|
|
81
|
+
|---|---|---|
|
|
82
|
+
| `--recommended-tab--section-gap` | Gap between sections | `24px` |
|
|
83
|
+
| `--recommended-tab--link-color` | "Show list" link color | `#144ab0` |
|
|
84
|
+
-->
|
|
85
|
+
|
|
86
|
+
<style>.recommended-tab {
|
|
87
|
+
--_recommended-tab--background: var(--recommended-tab--background, rgba(255, 255, 255, 0.8));
|
|
88
|
+
--_recommended-tab--border-color: var(--recommended-tab--border-color, #f9fafb);
|
|
89
|
+
--_recommended-tab--section-gap: var(--recommended-tab--section-gap, 1.5rem);
|
|
90
|
+
--_recommended-tab--link-color: var(--recommended-tab--link-color, #144ab0);
|
|
91
|
+
display: flex;
|
|
92
|
+
flex-direction: column;
|
|
93
|
+
gap: var(--_recommended-tab--section-gap);
|
|
94
|
+
background: var(--_recommended-tab--background);
|
|
95
|
+
border: 1px solid var(--_recommended-tab--border-color);
|
|
96
|
+
padding: 1rem 1rem 1.5rem;
|
|
97
|
+
min-height: 100%;
|
|
98
|
+
}
|
|
99
|
+
.recommended-tab__section {
|
|
100
|
+
display: flex;
|
|
101
|
+
flex-direction: column;
|
|
102
|
+
gap: 0.5rem;
|
|
103
|
+
}
|
|
104
|
+
.recommended-tab__section-title {
|
|
105
|
+
font-size: 1rem;
|
|
106
|
+
font-weight: 500;
|
|
107
|
+
}
|
|
108
|
+
.recommended-tab__posts {
|
|
109
|
+
display: flex;
|
|
110
|
+
flex-direction: column;
|
|
111
|
+
gap: 0.75rem;
|
|
112
|
+
}
|
|
113
|
+
.recommended-tab__playlists {
|
|
114
|
+
display: flex;
|
|
115
|
+
flex-direction: column;
|
|
116
|
+
gap: 0.75rem;
|
|
117
|
+
}
|
|
118
|
+
.recommended-tab__playlist-card {
|
|
119
|
+
display: flex;
|
|
120
|
+
gap: 1rem;
|
|
121
|
+
align-items: flex-end;
|
|
122
|
+
background: white;
|
|
123
|
+
border-radius: 0.375rem;
|
|
124
|
+
overflow: hidden;
|
|
125
|
+
}
|
|
126
|
+
.recommended-tab__playlist-thumbnail {
|
|
127
|
+
flex-shrink: 0;
|
|
128
|
+
width: 6.0625rem;
|
|
129
|
+
height: 9.125rem;
|
|
130
|
+
--sc-kit--image--object-fit: cover;
|
|
131
|
+
--sc-kit--image--border-radius: 0.25rem;
|
|
132
|
+
}
|
|
133
|
+
.recommended-tab__playlist-info {
|
|
134
|
+
display: flex;
|
|
135
|
+
flex-direction: column;
|
|
136
|
+
gap: 0.25rem;
|
|
137
|
+
padding: 0.5rem 0;
|
|
138
|
+
min-width: 0;
|
|
139
|
+
height: 9.125rem;
|
|
140
|
+
}
|
|
141
|
+
.recommended-tab__playlist-name {
|
|
142
|
+
font-size: 0.875rem;
|
|
143
|
+
font-weight: 600;
|
|
144
|
+
}
|
|
145
|
+
.recommended-tab__playlist-count {
|
|
146
|
+
font-size: 0.75rem;
|
|
147
|
+
font-weight: 400;
|
|
148
|
+
color: #999;
|
|
149
|
+
flex: 1;
|
|
150
|
+
}
|
|
151
|
+
.recommended-tab__playlist-link {
|
|
152
|
+
font-size: 0.75rem;
|
|
153
|
+
font-weight: 500;
|
|
154
|
+
color: var(--_recommended-tab--link-color);
|
|
155
|
+
cursor: pointer;
|
|
156
|
+
}
|
|
157
|
+
.recommended-tab__products {
|
|
158
|
+
display: flex;
|
|
159
|
+
gap: 0.75rem;
|
|
160
|
+
overflow-x: auto;
|
|
161
|
+
scrollbar-width: none;
|
|
162
|
+
}
|
|
163
|
+
.recommended-tab__product-wrapper {
|
|
164
|
+
flex: 0 0 10.0625rem;
|
|
165
|
+
}</style>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { TrackingParams } from '../../marketing-tracking';
|
|
2
|
+
import type { IFeedPlayerRecommendedHandler } from '../types';
|
|
3
|
+
type Props = {
|
|
4
|
+
handler: IFeedPlayerRecommendedHandler;
|
|
5
|
+
currentPostId: string;
|
|
6
|
+
trackingParams: TrackingParams;
|
|
7
|
+
on?: {
|
|
8
|
+
postActivate?: (postId: string) => void;
|
|
9
|
+
playlistSelect?: (playlistId: string) => void;
|
|
10
|
+
productBuy?: (productId: string) => void;
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Recommended tab — shows related posts, suggested playlists, and suggested products.
|
|
15
|
+
*
|
|
16
|
+
* ### CSS Custom Properties
|
|
17
|
+
* | Property | Description | Default |
|
|
18
|
+
* |---|---|---|
|
|
19
|
+
* | `--recommended-tab--section-gap` | Gap between sections | `24px` |
|
|
20
|
+
* | `--recommended-tab--link-color` | "Show list" link color | `#144ab0` |
|
|
21
|
+
*/
|
|
22
|
+
declare const RecommendedTab: import("svelte").Component<Props, {}, "">;
|
|
23
|
+
type RecommendedTab = ReturnType<typeof RecommendedTab>;
|
|
24
|
+
export default RecommendedTab;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
<script lang="ts">import { ProductCard } from '../../products/product-card';
|
|
2
|
+
import { default as ArticleTab } from './article-tab.svelte';
|
|
3
|
+
import { default as InformationTab } from './information-tab.svelte';
|
|
4
|
+
import { default as PlaylistTab } from './playlist-tab.svelte';
|
|
5
|
+
import { default as RecommendedTab } from './recommended-tab.svelte';
|
|
6
|
+
import { default as SidebarTabBar } from './sidebar-tab-bar.svelte';
|
|
7
|
+
const selectedProduct = $derived.by(() => {
|
|
8
|
+
if (!selectedProductId || !model.attachments) {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
return model.attachments.products.find((p) => p.id === selectedProductId) ?? null;
|
|
12
|
+
});
|
|
13
|
+
let { tabs, activeTabId, model, trackingParams, selectedProductId, recommendedHandler, playlistHandler, on } = $props();
|
|
14
|
+
</script>
|
|
15
|
+
|
|
16
|
+
<div class="sidebar-panel">
|
|
17
|
+
{#if tabs.length > 1}
|
|
18
|
+
<SidebarTabBar tabs={tabs} activeTabId={activeTabId} on={{ tabChange: on.tabChange }} />
|
|
19
|
+
{/if}
|
|
20
|
+
|
|
21
|
+
<div class="sidebar-panel__content">
|
|
22
|
+
{#if activeTabId === 'information'}
|
|
23
|
+
<InformationTab
|
|
24
|
+
model={model}
|
|
25
|
+
{trackingParams}
|
|
26
|
+
selectedProductId={selectedProductId}
|
|
27
|
+
on={{
|
|
28
|
+
productImpression: on.productImpression,
|
|
29
|
+
productBuy: on.productBuy,
|
|
30
|
+
productSelect: on.productSelect,
|
|
31
|
+
adClick: on.adClick,
|
|
32
|
+
adImpression: on.adImpression
|
|
33
|
+
}} />
|
|
34
|
+
{:else if activeTabId === 'product' && selectedProduct}
|
|
35
|
+
<div class="sidebar-panel__product">
|
|
36
|
+
<ProductCard
|
|
37
|
+
product={selectedProduct}
|
|
38
|
+
{trackingParams}
|
|
39
|
+
on={{
|
|
40
|
+
click: on.productClick,
|
|
41
|
+
buy: on.productBuy
|
|
42
|
+
}} />
|
|
43
|
+
</div>
|
|
44
|
+
{:else if activeTabId === 'article'}
|
|
45
|
+
<ArticleTab model={model} on={{ readMore: on.articleReadMore }} />
|
|
46
|
+
{:else if activeTabId === 'recommended' && recommendedHandler}
|
|
47
|
+
<RecommendedTab
|
|
48
|
+
handler={recommendedHandler}
|
|
49
|
+
currentPostId={model.id}
|
|
50
|
+
{trackingParams}
|
|
51
|
+
on={{
|
|
52
|
+
postActivate: on.postActivate,
|
|
53
|
+
playlistSelect: on.playlistSelect,
|
|
54
|
+
productBuy: on.productBuy
|
|
55
|
+
}} />
|
|
56
|
+
{:else if activeTabId === 'playlist' && playlistHandler}
|
|
57
|
+
<PlaylistTab
|
|
58
|
+
handler={playlistHandler}
|
|
59
|
+
activePostId={model.id}
|
|
60
|
+
on={{ postActivate: on.postActivate }} />
|
|
61
|
+
{/if}
|
|
62
|
+
</div>
|
|
63
|
+
</div>
|
|
64
|
+
|
|
65
|
+
<style>.sidebar-panel {
|
|
66
|
+
display: flex;
|
|
67
|
+
flex-direction: column;
|
|
68
|
+
gap: 1rem;
|
|
69
|
+
height: 100%;
|
|
70
|
+
overflow: hidden;
|
|
71
|
+
}
|
|
72
|
+
.sidebar-panel__content {
|
|
73
|
+
flex: 1;
|
|
74
|
+
min-height: 0;
|
|
75
|
+
overflow-y: auto;
|
|
76
|
+
overflow-x: hidden;
|
|
77
|
+
overscroll-behavior: contain;
|
|
78
|
+
scrollbar-width: none;
|
|
79
|
+
border-radius: 0.5rem;
|
|
80
|
+
}
|
|
81
|
+
.sidebar-panel__product {
|
|
82
|
+
padding: 0.75rem;
|
|
83
|
+
--product-card--aspect-ratio: auto;
|
|
84
|
+
}</style>
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { TrackingParams } from '../../marketing-tracking';
|
|
2
|
+
import type { PostModel } from '../../posts/model';
|
|
3
|
+
import type { IFeedPlayerPlaylistHandler, IFeedPlayerRecommendedHandler } from '../types';
|
|
4
|
+
import type { SidebarTab } from './types';
|
|
5
|
+
type Props = {
|
|
6
|
+
tabs: SidebarTab[];
|
|
7
|
+
activeTabId: string;
|
|
8
|
+
model: PostModel;
|
|
9
|
+
trackingParams: TrackingParams;
|
|
10
|
+
selectedProductId: string | null;
|
|
11
|
+
recommendedHandler?: IFeedPlayerRecommendedHandler;
|
|
12
|
+
playlistHandler?: IFeedPlayerPlaylistHandler;
|
|
13
|
+
on: {
|
|
14
|
+
tabChange: (id: string) => void;
|
|
15
|
+
productClick?: (productId: string) => void;
|
|
16
|
+
productImpression?: (productId: string) => void;
|
|
17
|
+
productBuy?: (productId: string) => void;
|
|
18
|
+
productSelect?: (productId: string) => void;
|
|
19
|
+
adClick?: (adId: string) => void;
|
|
20
|
+
adImpression?: (adId: string) => void;
|
|
21
|
+
articleReadMore?: (articleId: string) => void;
|
|
22
|
+
postActivate?: (postId: string) => void;
|
|
23
|
+
playlistSelect?: (playlistId: string) => void;
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
declare const SidebarPanel: import("svelte").Component<Props, {}, "">;
|
|
27
|
+
type SidebarPanel = ReturnType<typeof SidebarPanel>;
|
|
28
|
+
export default SidebarPanel;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
<script lang="ts">let { tabs, activeTabId, on } = $props();
|
|
2
|
+
export {};
|
|
3
|
+
</script>
|
|
4
|
+
|
|
5
|
+
<div class="sidebar-tab-bar">
|
|
6
|
+
{#each tabs as tab (tab.id)}
|
|
7
|
+
<button type="button" class="sidebar-tab-bar__tab" class:sidebar-tab-bar__tab--active={tab.id === activeTabId} onclick={() => on.tabChange(tab.id)}>
|
|
8
|
+
{tab.label}
|
|
9
|
+
</button>
|
|
10
|
+
{/each}
|
|
11
|
+
</div>
|
|
12
|
+
|
|
13
|
+
<!--
|
|
14
|
+
@component
|
|
15
|
+
Tab bar for the feed player sidebar.
|
|
16
|
+
|
|
17
|
+
### CSS Custom Properties
|
|
18
|
+
| Property | Description | Default |
|
|
19
|
+
|---|---|---|
|
|
20
|
+
| `--sidebar-tab-bar--color` | Inactive tab text color | `#9ca3af` |
|
|
21
|
+
| `--sidebar-tab-bar--color-active` | Active tab text color | `currentColor` |
|
|
22
|
+
-->
|
|
23
|
+
|
|
24
|
+
<style>.sidebar-tab-bar {
|
|
25
|
+
--_sidebar-tab-bar--color: var(--sidebar-tab-bar--color, #9ca3af);
|
|
26
|
+
--_sidebar-tab-bar--color-active: var(--sidebar-tab-bar--color-active, currentColor);
|
|
27
|
+
display: flex;
|
|
28
|
+
gap: 2.25rem;
|
|
29
|
+
flex-shrink: 0;
|
|
30
|
+
}
|
|
31
|
+
.sidebar-tab-bar__tab {
|
|
32
|
+
font-size: 0.75rem;
|
|
33
|
+
font-weight: 400;
|
|
34
|
+
line-height: 1rem;
|
|
35
|
+
color: var(--_sidebar-tab-bar--color);
|
|
36
|
+
background: none;
|
|
37
|
+
border: none;
|
|
38
|
+
padding: 0;
|
|
39
|
+
cursor: pointer;
|
|
40
|
+
white-space: nowrap;
|
|
41
|
+
}
|
|
42
|
+
.sidebar-tab-bar__tab--active {
|
|
43
|
+
font-weight: 500;
|
|
44
|
+
color: var(--_sidebar-tab-bar--color-active);
|
|
45
|
+
}</style>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { SidebarTab } from './types';
|
|
2
|
+
type Props = {
|
|
3
|
+
tabs: SidebarTab[];
|
|
4
|
+
activeTabId: string;
|
|
5
|
+
on: {
|
|
6
|
+
tabChange: (id: string) => void;
|
|
7
|
+
};
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Tab bar for the feed player sidebar.
|
|
11
|
+
*
|
|
12
|
+
* ### CSS Custom Properties
|
|
13
|
+
* | Property | Description | Default |
|
|
14
|
+
* |---|---|---|
|
|
15
|
+
* | `--sidebar-tab-bar--color` | Inactive tab text color | `#9ca3af` |
|
|
16
|
+
* | `--sidebar-tab-bar--color-active` | Active tab text color | `currentColor` |
|
|
17
|
+
*/
|
|
18
|
+
declare const SidebarTabBar: import("svelte").Component<Props, {}, "">;
|
|
19
|
+
type SidebarTabBar = ReturnType<typeof SidebarTabBar>;
|
|
20
|
+
export default SidebarTabBar;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { TrackingParams } from '../marketing-tracking';
|
|
2
|
+
import type { IPostModel } from '../posts/model';
|
|
3
|
+
import type { IPostAnalyticsHandler } from '../posts/posts-player';
|
|
4
|
+
import type { ProductCardModel } from '../products/product-card';
|
|
5
|
+
import type { IPostSharingHandler } from '../posts/sharing';
|
|
6
|
+
import type { IPostSocialInteractionsHandler } from '../posts/social-interactions';
|
|
7
|
+
import type { AppLocaleValue } from '@streamscloud/kit/core/locale';
|
|
8
|
+
import type { IPlayerDataProvider } from '@streamscloud/kit/ui/player/providers';
|
|
9
|
+
import type { Snippet } from 'svelte';
|
|
10
|
+
export type FeedPlayerPostPreview = {
|
|
11
|
+
id: string;
|
|
12
|
+
thumbnailUrl: string | null;
|
|
13
|
+
title: string;
|
|
14
|
+
description: string | null;
|
|
15
|
+
displayDate: string;
|
|
16
|
+
viewsCount: number;
|
|
17
|
+
durationSeconds: number | null;
|
|
18
|
+
};
|
|
19
|
+
export type FeedPlayerSuggestedPlaylist = {
|
|
20
|
+
id: string;
|
|
21
|
+
name: string;
|
|
22
|
+
postsCount: number;
|
|
23
|
+
thumbnailUrl: string | null;
|
|
24
|
+
};
|
|
25
|
+
export type FeedPlayerRecommendedData = {
|
|
26
|
+
relatedPosts: FeedPlayerPostPreview[];
|
|
27
|
+
suggestedPlaylists: FeedPlayerSuggestedPlaylist[];
|
|
28
|
+
suggestedProducts: ProductCardModel[];
|
|
29
|
+
};
|
|
30
|
+
export interface IFeedPlayerRecommendedHandler {
|
|
31
|
+
getRecommendations: (postId: string) => Promise<FeedPlayerRecommendedData>;
|
|
32
|
+
}
|
|
33
|
+
export type FeedPlayerPlaylistData = {
|
|
34
|
+
name: string;
|
|
35
|
+
updatedAt: string;
|
|
36
|
+
posts: FeedPlayerPostPreview[];
|
|
37
|
+
};
|
|
38
|
+
export interface IFeedPlayerPlaylistHandler {
|
|
39
|
+
getPlaylist: () => Promise<FeedPlayerPlaylistData>;
|
|
40
|
+
}
|
|
41
|
+
export type FeedPlayerProps = {
|
|
42
|
+
dataProvider: IPlayerDataProvider<IPostModel>;
|
|
43
|
+
socialInteractionsHandler?: IPostSocialInteractionsHandler;
|
|
44
|
+
sharingHandler?: IPostSharingHandler;
|
|
45
|
+
analyticsHandler?: IPostAnalyticsHandler;
|
|
46
|
+
recommendedHandler?: IFeedPlayerRecommendedHandler;
|
|
47
|
+
playlistHandler?: IFeedPlayerPlaylistHandler;
|
|
48
|
+
trackingParams?: TrackingParams;
|
|
49
|
+
settings?: FeedPlayerSettings;
|
|
50
|
+
header?: Snippet;
|
|
51
|
+
on?: {
|
|
52
|
+
postActivated?: (id: string) => void;
|
|
53
|
+
productBuy?: (productId: string) => void;
|
|
54
|
+
articleReadMore?: (articleId: string) => void;
|
|
55
|
+
playlistSelect?: (playlistId: string) => void;
|
|
56
|
+
closed?: () => void;
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
export type FeedPlayerSettings = {
|
|
60
|
+
locale?: AppLocaleValue;
|
|
61
|
+
background?: 'solid' | 'glass' | 'transparent';
|
|
62
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -44,11 +44,16 @@ const trackingParams = $derived.by(() => {
|
|
|
44
44
|
|
|
45
45
|
<style>.post-attachments {
|
|
46
46
|
--_post-attachments--gap: var(--post-attachments--gap, 1.875rem);
|
|
47
|
+
--ad-card--background-color: var(--sc-player--card-background);
|
|
48
|
+
--ad-card--price-color: var(--sc-player--price);
|
|
49
|
+
--ad-card--text--primary: var(--sc-mc-color--text-primary);
|
|
50
|
+
--ad-card--text-secondary: var(--sc-mc-color--text-secondary);
|
|
47
51
|
--product-card--background-color: var(--sc-player--card-background);
|
|
52
|
+
--product-card--button--background: var(--sc-player--card-button);
|
|
53
|
+
--product-card--button--color: var(--sc-mc-color--text-primary);
|
|
48
54
|
--product-card--price-color: var(--sc-player--price);
|
|
49
55
|
--product-card--sale-price-color: var(--sc-player--sale-price);
|
|
50
|
-
--
|
|
51
|
-
--ad-card--price-color: var(--sc-player--price);
|
|
56
|
+
--product-card--text-secondary: var(--sc-mc-color--text-secondary);
|
|
52
57
|
display: flex;
|
|
53
58
|
flex-direction: column;
|
|
54
59
|
gap: var(--_post-attachments--gap);
|
|
@@ -14,13 +14,14 @@ $effect(() => {
|
|
|
14
14
|
uiManager.enableControls = enableControls;
|
|
15
15
|
});
|
|
16
16
|
const trackingParams = $derived.by(() => {
|
|
17
|
-
if (externalTrackingParams
|
|
18
|
-
return
|
|
17
|
+
if (externalTrackingParams === false) {
|
|
18
|
+
return false;
|
|
19
19
|
}
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
const shortVideoId = model.postType === 'SHORT_VIDEO' ? model.id : undefined;
|
|
21
|
+
if (!externalTrackingParams && !shortVideoId) {
|
|
22
|
+
return false;
|
|
22
23
|
}
|
|
23
|
-
return
|
|
24
|
+
return { ...externalTrackingParams, shortVideoId };
|
|
24
25
|
});
|
|
25
26
|
const viewerMounted = (node) => {
|
|
26
27
|
const resizeObserver = new ResizeObserver(() => {
|
|
@@ -97,6 +98,8 @@ const variables = $derived.by(() => {
|
|
|
97
98
|
</div>
|
|
98
99
|
|
|
99
100
|
<style>.post-viewer {
|
|
101
|
+
--_post-viewer--button--color: var(--post-viewer--button--color, light-dark(#272727, #000000));
|
|
102
|
+
--_post-viewer--button--color--inactive: var(--post-viewer--button--color--inactive, rgb(from var(--_post-viewer--button--color) r g b / 60%));
|
|
100
103
|
width: 100%;
|
|
101
104
|
min-width: 100%;
|
|
102
105
|
max-width: 100%;
|
|
@@ -115,8 +118,8 @@ const variables = $derived.by(() => {
|
|
|
115
118
|
}
|
|
116
119
|
}
|
|
117
120
|
.post-viewer__controls-panel {
|
|
118
|
-
--sc-kit--player-button--color: var(--
|
|
119
|
-
--sc-kit--player-button--color--inactive: var(--
|
|
121
|
+
--sc-kit--player-button--color: var(--_post-viewer--button--color);
|
|
122
|
+
--sc-kit--player-button--color--inactive: var(--_post-viewer--button--color--inactive);
|
|
120
123
|
position: absolute;
|
|
121
124
|
left: auto;
|
|
122
125
|
right: 0;
|
|
@@ -188,4 +188,6 @@ const currentItemActions = $derived.by(() => {
|
|
|
188
188
|
display: contents;
|
|
189
189
|
--sc-kit--player-button--color: var(--sc-player--button);
|
|
190
190
|
--sc-kit--player-button--color--inactive: var(--sc-player--button-inactive);
|
|
191
|
+
--post-viewer--button--color: var(--sc-player--button);
|
|
192
|
+
--post-viewer--button--color--inactive: var(--sc-player--button-inactive);
|
|
191
193
|
}</style>
|
|
@@ -46,7 +46,7 @@ const onBuyClicked = (event) => {
|
|
|
46
46
|
};
|
|
47
47
|
</script>
|
|
48
48
|
|
|
49
|
-
<div class="product-card" class:product-card--with-buy={!!on?.buy}
|
|
49
|
+
<div class="product-card" class:product-card--with-buy={!!on?.buy} use:trackImpression>
|
|
50
50
|
<ProportionalContainer ratio={1}>
|
|
51
51
|
<Image src={product.image} />
|
|
52
52
|
</ProportionalContainer>
|
|
@@ -84,10 +84,12 @@ const onBuyClicked = (event) => {
|
|
|
84
84
|
{/if}
|
|
85
85
|
</div>
|
|
86
86
|
|
|
87
|
-
{#if
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
87
|
+
{#if !inert}
|
|
88
|
+
{#if enrichedLink}
|
|
89
|
+
<a href={enrichedLink.href} onclick={onProductClicked} target="_blank" rel="noopener noreferrer" class="product-card__link" aria-label="none"> </a>
|
|
90
|
+
{:else if on?.click}
|
|
91
|
+
<button type="button" onclick={onProductClicked} class="product-card__link" aria-label="none"> </button>
|
|
92
|
+
{/if}
|
|
91
93
|
{/if}
|
|
92
94
|
</div>
|
|
93
95
|
|
|
@@ -96,8 +98,11 @@ const onBuyClicked = (event) => {
|
|
|
96
98
|
--_product-card--border-radius: var(--product-card--border-radius, 0.5rem);
|
|
97
99
|
--_product-card--background-color: var(--product-card--background-color, rgb(from light-dark(#ffffff, #000000) r g b / 90%));
|
|
98
100
|
--_product-card--border-color: var(--product-card--border-color, light-dark(#f2f2f2, #000000));
|
|
101
|
+
--_product-card--button--background: var(--product-card--button--background, light-dark(#f9fafb, #1f2937));
|
|
102
|
+
--_product-card--button--color: var(--product-card--button--color, #9ca3af);
|
|
99
103
|
--_product-card--price-color: var(--product-card--price-color, inherit);
|
|
100
104
|
--_product-card--sale-price-color: var(--product-card--sale-price-color, inherit);
|
|
105
|
+
--_product-card--text-secondary: var(--product-card--text-secondary, light-dark(#6b7280, #d1d5db));
|
|
101
106
|
--product-price-color: var(--_product-card--price-color);
|
|
102
107
|
--product-price--sale--color: var(--_product-card--sale-price-color);
|
|
103
108
|
--sc-kit--image--border-radius: 0.25rem;
|
|
@@ -169,7 +174,7 @@ const onBuyClicked = (event) => {
|
|
|
169
174
|
}
|
|
170
175
|
.product-card__description {
|
|
171
176
|
font-weight: 400;
|
|
172
|
-
color: var(--
|
|
177
|
+
color: var(--_product-card--text-secondary);
|
|
173
178
|
font-size: 0.9375rem;
|
|
174
179
|
line-height: 1.375rem;
|
|
175
180
|
min-height: 1.375rem;
|
|
@@ -195,11 +200,10 @@ const onBuyClicked = (event) => {
|
|
|
195
200
|
position: relative;
|
|
196
201
|
z-index: 1;
|
|
197
202
|
margin-top: 0.625rem;
|
|
198
|
-
--sc-kit--button--background:
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
--sc-kit--button--font--color: var(--sc-mc-color--text-primary);
|
|
203
|
+
--sc-kit--button--background: var(--_product-card--button--background);
|
|
204
|
+
--sc-kit--button--font--color: var(--_product-card--button--color);
|
|
205
|
+
--sc-kit--button--text--font-size: 0.75rem;
|
|
206
|
+
--sc-kit--button--icon--font-size: 1rem;
|
|
203
207
|
/* Set 'container-type: inline-size;' to reference container*/
|
|
204
208
|
}
|
|
205
209
|
@container (width < 230px) {
|
|
@@ -215,7 +219,7 @@ const onBuyClicked = (event) => {
|
|
|
215
219
|
.product-price {
|
|
216
220
|
--_product-price--color: var(--product-price-color);
|
|
217
221
|
--_product-price--sale--color: var(--product-price--sale--color);
|
|
218
|
-
--_product-price--before--color: var(--
|
|
222
|
+
--_product-price--before--color: var(--_product-card--text-secondary);
|
|
219
223
|
--_product-price--before--font-size: 0.75em;
|
|
220
224
|
--_product-price--font-size: 1.875em;
|
|
221
225
|
--_product-price--gap: 0.375em;
|
|
@@ -405,6 +405,8 @@ const stopActivityTracking = () => {
|
|
|
405
405
|
display: contents;
|
|
406
406
|
--sc-kit--player-button--color: var(--sc-player--button);
|
|
407
407
|
--sc-kit--player-button--color--inactive: var(--sc-player--button-inactive);
|
|
408
|
+
--post-viewer--button--color: var(--sc-player--button);
|
|
409
|
+
--post-viewer--button--color--inactive: var(--sc-player--button-inactive);
|
|
408
410
|
--player--overview-panel--background: var(--sc-player--sidebar-background);
|
|
409
411
|
}
|
|
410
412
|
|
|
@@ -45,7 +45,7 @@ const parsedRatio = $derived.by(() => {
|
|
|
45
45
|
</div>
|
|
46
46
|
{:else}
|
|
47
47
|
<div class="media-item-view__video" onclick={handleClick} onkeydown={() => {}} role="none">
|
|
48
|
-
<Video src={media.url} poster={
|
|
48
|
+
<Video src={media.url} poster={null} inert={!!on?.click} />
|
|
49
49
|
</div>
|
|
50
50
|
{/if}
|
|
51
51
|
{/snippet}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@streamscloud/embeddable",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "17.0.0-1775740482426",
|
|
4
4
|
"author": "StreamsCloud",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -42,6 +42,10 @@
|
|
|
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
|
+
},
|
|
45
49
|
"./media-center": {
|
|
46
50
|
"types": "./dist/media-center/index.d.ts",
|
|
47
51
|
"svelte": "./dist/media-center/index.js"
|
|
@@ -142,7 +146,7 @@
|
|
|
142
146
|
}
|
|
143
147
|
},
|
|
144
148
|
"peerDependencies": {
|
|
145
|
-
"@streamscloud/kit": "^0.2.
|
|
149
|
+
"@streamscloud/kit": "^0.2.28",
|
|
146
150
|
"@streamscloud/streams-analytics-collector": "^4.0.1",
|
|
147
151
|
"svelte": "^5.51.0"
|
|
148
152
|
},
|
|
@@ -158,7 +162,7 @@
|
|
|
158
162
|
"@graphql-codegen/typescript": "^5.0.7",
|
|
159
163
|
"@graphql-codegen/typescript-operations": "^5.0.7",
|
|
160
164
|
"@graphql-typed-document-node/core": "^3.2.0",
|
|
161
|
-
"@streamscloud/kit": "^0.2.
|
|
165
|
+
"@streamscloud/kit": "^0.2.28",
|
|
162
166
|
"@streamscloud/streams-analytics-collector": "^4.0.1",
|
|
163
167
|
"@sveltejs/package": "^2.5.7",
|
|
164
168
|
"@sveltejs/vite-plugin-svelte": "^6.2.4",
|