@streamscloud/embeddable 16.0.7 → 16.1.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.
Files changed (164) hide show
  1. package/dist/ads/ad-card/types.d.ts +1 -1
  2. package/dist/ads/ad-card/types.js +1 -1
  3. package/dist/articles/article/article-layout.svelte +32 -0
  4. package/dist/articles/article/article-layout.svelte.d.ts +9 -0
  5. package/dist/articles/article/article-proxy.svelte +8 -0
  6. package/dist/articles/article/article-proxy.svelte.d.ts +12 -0
  7. package/dist/articles/article/article-section.svelte +52 -0
  8. package/dist/articles/article/article-section.svelte.d.ts +9 -0
  9. package/dist/articles/article/article-view.svelte +41 -0
  10. package/dist/articles/article/article-view.svelte.d.ts +8 -0
  11. package/dist/articles/article/cmp.article.svelte +36 -0
  12. package/dist/articles/article/cmp.article.svelte.d.ts +12 -0
  13. package/dist/articles/article/cmp.facts-container.svelte +27 -0
  14. package/dist/articles/article/cmp.facts-container.svelte.d.ts +7 -0
  15. package/dist/articles/article/fields/alt-text.svelte +15 -0
  16. package/dist/articles/article/fields/alt-text.svelte.d.ts +6 -0
  17. package/dist/articles/article/fields/article-field.svelte +45 -0
  18. package/dist/articles/article/fields/article-field.svelte.d.ts +8 -0
  19. package/dist/articles/article/fields/byline-field.svelte +23 -0
  20. package/dist/articles/article/fields/byline-field.svelte.d.ts +8 -0
  21. package/dist/articles/article/fields/image-field.svelte +8 -0
  22. package/dist/articles/article/fields/image-field.svelte.d.ts +7 -0
  23. package/dist/articles/article/fields/media-field.svelte +8 -0
  24. package/dist/articles/article/fields/media-field.svelte.d.ts +7 -0
  25. package/dist/articles/article/fields/media-gallery-field.svelte +8 -0
  26. package/dist/articles/article/fields/media-gallery-field.svelte.d.ts +7 -0
  27. package/dist/articles/article/fields/rich-text-field.svelte +19 -0
  28. package/dist/articles/article/fields/rich-text-field.svelte.d.ts +7 -0
  29. package/dist/articles/article/fields/text-field.svelte +24 -0
  30. package/dist/articles/article/fields/text-field.svelte.d.ts +7 -0
  31. package/dist/articles/article/fields/types.d.ts +72 -0
  32. package/dist/articles/article/fields/types.js +1 -0
  33. package/dist/articles/article/fields/video-field.svelte +8 -0
  34. package/dist/articles/article/fields/video-field.svelte.d.ts +7 -0
  35. package/dist/articles/article/helpers.d.ts +5 -0
  36. package/dist/articles/article/helpers.js +27 -0
  37. package/dist/articles/article/index.d.ts +8 -0
  38. package/dist/articles/article/index.js +5 -0
  39. package/dist/articles/article/styles-transformer.d.ts +47 -0
  40. package/dist/articles/article/styles-transformer.js +38 -0
  41. package/dist/articles/article/types.d.ts +32 -0
  42. package/dist/articles/article/types.js +1 -0
  43. package/dist/articles/article-dialog/article-dialog-localization.d.ts +3 -0
  44. package/dist/articles/article-dialog/article-dialog-localization.js +9 -0
  45. package/dist/articles/article-dialog/cmp.article-dialog.svelte +104 -0
  46. package/dist/articles/article-dialog/cmp.article-dialog.svelte.d.ts +9 -0
  47. package/dist/articles/article-dialog/index.d.ts +6 -0
  48. package/dist/articles/article-dialog/index.js +10 -0
  49. package/dist/articles/article-dialog/types.d.ts +6 -0
  50. package/dist/articles/data-providers/index.d.ts +1 -0
  51. package/dist/articles/data-providers/index.js +1 -0
  52. package/dist/articles/data-providers/types.d.ts +14 -0
  53. package/dist/articles/data-providers/types.js +1 -0
  54. package/dist/core/enums.d.ts +15 -50
  55. package/dist/core/enums.js +1 -61
  56. package/dist/core/graphql.d.ts +4 -1
  57. package/dist/core/graphql.js +3 -3
  58. package/dist/core/media/index.d.ts +0 -1
  59. package/dist/core/media/index.js +0 -1
  60. package/dist/core/media/media-item-url.service.d.ts +6 -2
  61. package/dist/core/media/media-item-url.service.js +1 -3
  62. package/dist/external-api/article/cmp.embed-article.svelte +98 -0
  63. package/dist/external-api/article/cmp.embed-article.svelte.d.ts +47 -0
  64. package/dist/external-api/article/index.d.ts +1 -0
  65. package/dist/external-api/article/index.js +1 -0
  66. package/dist/external-api/data-providers/article/article-data-provider.d.ts +4 -0
  67. package/dist/external-api/data-providers/article/article-data-provider.js +32 -0
  68. package/dist/external-api/data-providers/article/index.d.ts +1 -0
  69. package/dist/external-api/data-providers/article/index.js +1 -0
  70. package/dist/external-api/data-providers/article/operations.generated.d.ts +104 -0
  71. package/dist/external-api/data-providers/article/operations.generated.js +262 -0
  72. package/dist/external-api/data-providers/article/operations.graphql +99 -0
  73. package/dist/external-api/data-providers/internal-media-center-data-provider.svelte.js +6 -5
  74. package/dist/external-api/data-providers/internal-short-video-player-items-provider.d.ts +1 -1
  75. package/dist/external-api/data-providers/internal-short-video-player-items-provider.js +2 -4
  76. package/dist/external-api/data-providers/internal-streams-player-data-provider.js +1 -1
  77. package/dist/external-api/data-providers/mapper.d.ts +1 -1
  78. package/dist/external-api/data-providers/mapper.js +5 -6
  79. package/dist/external-api/data-providers/mocks/mock-content-management-handler.svelte.js +2 -3
  80. package/dist/external-api/data-providers/post-data-loaders/posts-loader.d.ts +1 -1
  81. package/dist/external-api/data-providers/post-data-loaders/posts-loader.js +0 -1
  82. package/dist/external-api/data-providers/stream-data-loaders/mapper.js +1 -2
  83. package/dist/external-api/data-providers/stream-data-loaders/stream-pages-loader.d.ts +1 -1
  84. package/dist/external-api/data-providers/stream-data-loaders/stream-pages-loader.js +1 -2
  85. package/dist/external-api/data-providers/stream-data-loaders/streams-loader.d.ts +1 -1
  86. package/dist/external-api/data-providers/stream-data-loaders/streams-loader.js +1 -2
  87. package/dist/external-api/index.d.ts +2 -1
  88. package/dist/external-api/index.js +2 -1
  89. package/dist/media-center/config/types.d.ts +4 -1
  90. package/dist/media-center/config/types.js +1 -1
  91. package/dist/media-center/media-center/cmp.media-center-proxy.svelte +9 -4
  92. package/dist/media-center/media-center/cmp.media-center-proxy.svelte.d.ts +2 -3
  93. package/dist/media-center/media-center/discover/data-loading.js +1 -2
  94. package/dist/media-center/media-center/discover/discover-view-handler.svelte.js +1 -2
  95. package/dist/media-center/media-center/discover/discover-view.svelte +1 -1
  96. package/dist/media-center/media-center/index.d.ts +0 -1
  97. package/dist/media-center/media-center/index.js +0 -1
  98. package/dist/media-center/media-center/media-center-settings.svelte.d.ts +1 -1
  99. package/dist/media-center/media-center/media-center-settings.svelte.js +2 -2
  100. package/dist/media-center/media-center/media-center-view.svelte +1 -1
  101. package/dist/media-center/media-center/menu/menu.svelte +1 -1
  102. package/dist/media-center/media-center/moments/moments-feed-handler.svelte.d.ts +1 -1
  103. package/dist/media-center/media-center/moments/moments-feed-handler.svelte.js +2 -3
  104. package/dist/media-center/media-center/moments/moments-state.svelte.d.ts +1 -1
  105. package/dist/media-center/media-center/moments/moments-state.svelte.js +1 -3
  106. package/dist/media-center/media-center/posts-feed/feed-providers-generator.js +1 -2
  107. package/dist/media-center/media-center/posts-feed/posts-feed-handler.svelte.d.ts +1 -1
  108. package/dist/media-center/media-center/posts-feed/posts-feed-handler.svelte.js +2 -2
  109. package/dist/media-page/cmp.media-page.svelte +10 -9
  110. package/dist/media-page/index.js +4 -4
  111. package/dist/posts/attachments/cmp.attachments.svelte +2 -3
  112. package/dist/posts/model/post-model.d.ts +2 -1
  113. package/dist/posts/model/post-model.js +2 -1
  114. package/dist/posts/post-viewer/attachments-horizontal.svelte +1 -2
  115. package/dist/posts/post-viewer/cmp.post-viewer.svelte +12 -5
  116. package/dist/posts/post-viewer/cmp.post-viewer.svelte.d.ts +1 -0
  117. package/dist/posts/post-viewer/mapper.js +6 -7
  118. package/dist/posts/post-viewer/post-texts.svelte +8 -1
  119. package/dist/posts/post-viewer/post-texts.svelte.d.ts +3 -0
  120. package/dist/posts/posts-player/cmp.posts-player.svelte +23 -13
  121. package/dist/posts/posts-player/cmp.posts-player.svelte.d.ts +2 -0
  122. package/dist/posts/posts-player/index.d.ts +8 -1
  123. package/dist/posts/posts-player/index.js +7 -1
  124. package/dist/posts/posts-player/posts-player-proxy.svelte +3 -2
  125. package/dist/posts/posts-player/posts-player-proxy.svelte.d.ts +2 -0
  126. package/dist/posts/posts-player/posts-player-view.svelte +21 -9
  127. package/dist/posts/posts-player/types.d.ts +3 -0
  128. package/dist/products/price-helper.d.ts +1 -1
  129. package/dist/products/price-helper.js +3 -4
  130. package/dist/streams/layout/models/mapper.d.ts +1 -1
  131. package/dist/streams/layout/models/mapper.js +2 -6
  132. package/dist/streams/layout/models/stream-layout-media-item-model.d.ts +1 -1
  133. package/dist/streams/layout/models/stream-layout-media-item-model.js +1 -1
  134. package/dist/streams/layout/models/stream-layout-short-video-model.d.ts +1 -1
  135. package/dist/streams/layout/models/stream-layout-short-video-model.js +1 -1
  136. package/dist/streams/streams-player/cmp.streams-player.svelte +22 -13
  137. package/dist/streams/streams-player/stream-overview.svelte +1 -1
  138. package/dist/streams/streams-player/streams-player-proxy.svelte +1 -1
  139. package/dist/ui/media-items/index.d.ts +3 -0
  140. package/dist/ui/media-items/index.js +3 -0
  141. package/dist/ui/{media-item-view → media-items/media-item-view}/cmp.media-item-view.svelte +23 -5
  142. package/dist/ui/{media-item-view → media-items/media-item-view}/cmp.media-item-view.svelte.d.ts +5 -3
  143. package/dist/ui/{media-items-gallery → media-items/media-items-gallery}/cmp.media-items-gallery.svelte +37 -32
  144. package/dist/ui/{media-items-gallery → media-items/media-items-gallery}/cmp.media-items-gallery.svelte.d.ts +5 -3
  145. package/dist/ui/{media-items-gallery/types.d.ts → media-items/media-items-gallery/gallery-layout.d.ts} +1 -1
  146. package/dist/ui/{media-items-gallery/types.js → media-items/media-items-gallery/gallery-layout.js} +1 -1
  147. package/dist/ui/media-items/types.d.ts +14 -0
  148. package/dist/ui/media-items/types.js +1 -0
  149. package/dist/ui/shadow-dom/cmp.shadow-root.svelte +3 -2
  150. package/dist/ui/shadow-dom/index.d.ts +1 -1
  151. package/dist/ui/shadow-dom/index.js +1 -1
  152. package/dist/ui/shadow-dom/shadow-root-service.d.ts +1 -0
  153. package/dist/ui/shadow-dom/shadow-root-service.js +8 -0
  154. package/package.json +11 -3
  155. package/dist/core/media/types.d.ts +0 -13
  156. package/dist/posts/posts-player/posts-player-host-settings.svelte.d.ts +0 -20
  157. package/dist/posts/posts-player/posts-player-host-settings.svelte.js +0 -15
  158. package/dist/streams/streams-player/streams-player-host-settings.svelte.d.ts +0 -20
  159. package/dist/streams/streams-player/streams-player-host-settings.svelte.js +0 -15
  160. /package/dist/{core/media → articles/article-dialog}/types.js +0 -0
  161. /package/dist/ui/{media-item-view → media-items/media-item-view}/index.d.ts +0 -0
  162. /package/dist/ui/{media-item-view → media-items/media-item-view}/index.js +0 -0
  163. /package/dist/ui/{media-items-gallery → media-items/media-items-gallery}/index.d.ts +0 -0
  164. /package/dist/ui/{media-items-gallery → media-items/media-items-gallery}/index.js +0 -0
@@ -5,6 +5,9 @@ type Props = {
5
5
  model: PostModel['texts'];
6
6
  uiManager: PostViewerUiManager;
7
7
  localization: PostViewerLocalization;
8
+ on?: {
9
+ readMore?: () => void;
10
+ };
8
11
  };
9
12
  declare const PostTexts: import("svelte").Component<Props, {}, "">;
10
13
  type PostTexts = ReturnType<typeof PostTexts>;
@@ -1,30 +1,40 @@
1
1
  <script lang="ts">import { CloseOrchestrator } from '../../ui/player/close-orchestrator';
2
2
  import { createShadowRoot } from '../../ui/shadow-dom';
3
- import { PostsPlayerHostSettings } from './posts-player-host-settings.svelte';
4
3
  import { default as PostsPlayerProxy } from './posts-player-proxy.svelte';
5
- import { mount, unmount, untrack } from 'svelte';
6
- let { dataProvider, socialInteractionsHandler, sharingHandler, playerSettings, analyticsHandler, on } = $props();
7
- const settingsHolder = untrack(() => new PostsPlayerHostSettings(playerSettings));
8
- $effect(() => {
9
- settingsHolder.update(playerSettings);
10
- });
4
+ import { mount, unmount } from 'svelte';
5
+ let { dataProvider, socialInteractionsHandler, sharingHandler, playerSettings, analyticsHandler, articleDataProvider, on } = $props();
11
6
  const initHost = (node) => {
12
7
  const shadowRoot = createShadowRoot(node);
13
8
  const mounted = mount(PostsPlayerProxy, {
14
9
  target: shadowRoot,
15
10
  props: {
16
- dataProvider,
17
- socialInteractionsHandler,
18
- sharingHandler,
19
- playerSettings: settingsHolder,
20
- analyticsHandler,
11
+ get dataProvider() {
12
+ return dataProvider;
13
+ },
14
+ get socialInteractionsHandler() {
15
+ return socialInteractionsHandler;
16
+ },
17
+ get sharingHandler() {
18
+ return sharingHandler;
19
+ },
20
+ get playerSettings() {
21
+ return playerSettings;
22
+ },
23
+ get analyticsHandler() {
24
+ return analyticsHandler;
25
+ },
26
+ get articleDataProvider() {
27
+ return articleDataProvider;
28
+ },
21
29
  closeOrchestrator: new CloseOrchestrator({
22
30
  closeFn: async () => {
23
31
  await unmount(mounted);
24
32
  },
25
33
  canClose: false
26
34
  }),
27
- on
35
+ get on() {
36
+ return on;
37
+ }
28
38
  }
29
39
  });
30
40
  return {
@@ -1,3 +1,4 @@
1
+ import type { ArticleDataProvider } from '../../articles/data-providers';
1
2
  import type { IPostSocialInteractionsHandler } from '..';
2
3
  import type { IPostSharingHandler } from '../sharing';
3
4
  import type { IPostAnalyticsHandler, PostPlayerModel } from './types';
@@ -8,6 +9,7 @@ type Props = {
8
9
  socialInteractionsHandler?: IPostSocialInteractionsHandler;
9
10
  sharingHandler?: IPostSharingHandler;
10
11
  analyticsHandler?: IPostAnalyticsHandler;
12
+ articleDataProvider?: ArticleDataProvider;
11
13
  playerSettings?: {
12
14
  locale?: AppLocaleValue;
13
15
  showStreamsCloudWatermark?: boolean;
@@ -1,3 +1,4 @@
1
+ import type { ArticleDataProvider } from '../../articles/data-providers';
1
2
  import { type IMediaCenterDataProvider } from '../../media-center/config/types';
2
3
  import type { IPostSharingHandler } from '../sharing';
3
4
  import type { IPostSocialInteractionsHandler } from '../social-interactions';
@@ -5,7 +6,7 @@ import { default as PostsPlayer } from './cmp.posts-player.svelte';
5
6
  import type { IPostAnalyticsHandler, PostPlayerModel } from './types';
6
7
  import type { AppLocaleValue } from '@streamscloud/kit/core/locale';
7
8
  export { PostsPlayer, type PostPlayerModel };
8
- export type { IMediaCenterDataProvider, IPostAnalyticsHandler };
9
+ export type { ArticleDataProvider, IMediaCenterDataProvider, IPostAnalyticsHandler };
9
10
  /**
10
11
  * Opens the posts player modal.
11
12
  *
@@ -23,6 +24,11 @@ export type { IMediaCenterDataProvider, IPostAnalyticsHandler };
23
24
  * @param {IPostSocialInteractionsHandler} [init.socialInteractionsHandler]
24
25
  * Handler for social interactions (like, share, etc.).
25
26
  *
27
+ * Article data provider (optional)
28
+ * @param {ArticleDataProvider} [init.articleDataProvider]
29
+ * Provider for fetching article content. When provided, article posts will show
30
+ * a "Read more" button that opens an article dialog instead of navigating to a URL.
31
+ *
26
32
  * Player settings (optional)
27
33
  * @param {object} [init.playerSettings]
28
34
  * Player UI and behavior settings.
@@ -87,6 +93,7 @@ export declare function openPostsPlayer(init: {
87
93
  analyticsHandler?: IPostAnalyticsHandler;
88
94
  socialInteractionsHandler?: IPostSocialInteractionsHandler;
89
95
  sharingHandler?: IPostSharingHandler;
96
+ articleDataProvider?: ArticleDataProvider;
90
97
  playerSettings?: {
91
98
  disableBackground?: boolean;
92
99
  locale?: AppLocaleValue;
@@ -22,6 +22,11 @@ export { PostsPlayer };
22
22
  * @param {IPostSocialInteractionsHandler} [init.socialInteractionsHandler]
23
23
  * Handler for social interactions (like, share, etc.).
24
24
  *
25
+ * Article data provider (optional)
26
+ * @param {ArticleDataProvider} [init.articleDataProvider]
27
+ * Provider for fetching article content. When provided, article posts will show
28
+ * a "Read more" button that opens an article dialog instead of navigating to a URL.
29
+ *
25
30
  * Player settings (optional)
26
31
  * @param {object} [init.playerSettings]
27
32
  * Player UI and behavior settings.
@@ -82,7 +87,7 @@ export { PostsPlayer };
82
87
  * ```
83
88
  */
84
89
  export function openPostsPlayer(init) {
85
- const { postsProvider: dataProvider, analyticsHandler, socialInteractionsHandler, sharingHandler, playerSettings, on } = init;
90
+ const { postsProvider: dataProvider, analyticsHandler, socialInteractionsHandler, sharingHandler, articleDataProvider, playerSettings, on } = init;
86
91
  const shadowHost = new ModalShadowHost();
87
92
  let mounted = null;
88
93
  const makeCloseOrchestrator = () => new CloseOrchestrator({
@@ -102,6 +107,7 @@ export function openPostsPlayer(init) {
102
107
  socialInteractionsHandler,
103
108
  sharingHandler,
104
109
  analyticsHandler,
110
+ articleDataProvider,
105
111
  playerSettings,
106
112
  closeOrchestrator: makeCloseOrchestrator(),
107
113
  on: {
@@ -1,7 +1,7 @@
1
1
  <script lang="ts">import {} from '../../ui/player/close-orchestrator';
2
2
  import { ShadowRoot } from '../../ui/shadow-dom';
3
3
  import { default as PostsPlayerView } from './posts-player-view.svelte';
4
- let { dataProvider, socialInteractionsHandler, sharingHandler, closeOrchestrator, playerSettings, analyticsHandler, on } = $props();
4
+ let { dataProvider, socialInteractionsHandler, sharingHandler, closeOrchestrator, playerSettings, analyticsHandler, articleDataProvider, on } = $props();
5
5
  let backgroundImageUrl = $state(null);
6
6
  const handleBackgroundImagedLoaded = (url) => {
7
7
  backgroundImageUrl = url;
@@ -10,7 +10,7 @@ const handleBackgroundImagedLoaded = (url) => {
10
10
 
11
11
  <ShadowRoot
12
12
  locale={playerSettings?.locale}
13
- theme={playerSettings?.theme ?? 'dark'}
13
+ theme={playerSettings?.theme}
14
14
  backgroundDisabled={playerSettings?.disableBackground === true}
15
15
  backgroundImageUrl={backgroundImageUrl}>
16
16
  <PostsPlayerView
@@ -19,6 +19,7 @@ const handleBackgroundImagedLoaded = (url) => {
19
19
  sharingHandler={sharingHandler}
20
20
  playerSettings={playerSettings}
21
21
  analyticsHandler={analyticsHandler}
22
+ articleDataProvider={articleDataProvider}
22
23
  closeOrchestrator={closeOrchestrator}
23
24
  on={{ postActivated: on?.postActivated, backgroundImageLoaded: playerSettings?.disableBackground === true ? undefined : handleBackgroundImagedLoaded }} />
24
25
  </ShadowRoot>
@@ -1,3 +1,4 @@
1
+ import type { ArticleDataProvider } from '../../articles/data-providers';
1
2
  import type { IPostSharingHandler } from '../sharing';
2
3
  import type { IPostSocialInteractionsHandler } from '../social-interactions';
3
4
  import { type ICloseOrchestrator } from '../../ui/player/close-orchestrator';
@@ -9,6 +10,7 @@ type Props = {
9
10
  socialInteractionsHandler?: IPostSocialInteractionsHandler;
10
11
  sharingHandler?: IPostSharingHandler;
11
12
  analyticsHandler?: IPostAnalyticsHandler;
13
+ articleDataProvider?: ArticleDataProvider;
12
14
  closeOrchestrator: ICloseOrchestrator;
13
15
  playerSettings?: {
14
16
  locale?: AppLocaleValue;
@@ -1,15 +1,26 @@
1
- <script lang="ts">import { PostType } from '../../core/enums';
1
+ <script lang="ts">import { openArticleDialog } from '../../articles/article-dialog';
2
2
  import { PostAttachments } from '../attachments';
3
3
  import { PostActionsGenerator } from '../controls';
4
4
  import { getPostCoverImage, PostModel } from '../model';
5
5
  import { PostViewer } from '../post-viewer';
6
6
  import { Player, PlayerConfig, PlayerSettings } from '../../ui/player';
7
+ import { getDialogAnchor } from '../../ui/shadow-dom';
7
8
  import IconDelete from '@fluentui/svg-icons/icons/delete_32_regular.svg?raw';
8
9
  import IconEdit from '@fluentui/svg-icons/icons/edit_32_regular.svg?raw';
9
10
  import { preloadImage } from '@streamscloud/kit/core/utils';
10
11
  import { initBufferFromProvider } from '@streamscloud/kit/ui/player/providers';
11
12
  import { untrack } from 'svelte';
12
- let { dataProvider, socialInteractionsHandler, sharingHandler, playerSettings, analyticsHandler, managementActions, closeOrchestrator, on } = $props();
13
+ let { dataProvider, socialInteractionsHandler, sharingHandler, playerSettings, analyticsHandler, managementActions, articleDataProvider, closeOrchestrator, on } = $props();
14
+ let dialogAnchor;
15
+ const resolveDialogAnchor = (el) => {
16
+ dialogAnchor = getDialogAnchor(el) ?? undefined;
17
+ };
18
+ const handleArticleReadMore = (articleId) => {
19
+ if (!articleDataProvider || !dialogAnchor) {
20
+ return;
21
+ }
22
+ openArticleDialog({ anchor: dialogAnchor, articleId, fetchArticle: articleDataProvider.fetchArticle });
23
+ };
13
24
  let buffer = $state.raw(null);
14
25
  let mappedPostsCache = {};
15
26
  $effect(() => {
@@ -57,7 +68,7 @@ const contentPlayerConfig = untrack(() => new PlayerConfig({
57
68
  if (on?.backgroundImageLoaded) {
58
69
  on.backgroundImageLoaded(getPostCoverImage(post));
59
70
  }
60
- if (post.postType === PostType.ShortVideo) {
71
+ if (post.postType === 'SHORT_VIDEO') {
61
72
  analyticsHandler?.trackShortVideoView(id);
62
73
  }
63
74
  else if (post.postType) {
@@ -73,12 +84,12 @@ const postActionsGenerator = untrack(() => new PostActionsGenerator({
73
84
  on: { attachmentClicked: () => (contentPlayerConfig.uiManager.attachmentsCollapsed = !contentPlayerConfig.uiManager.attachmentsCollapsed) }
74
85
  }));
75
86
  const onProductClick = (id, postId) => {
76
- if (getLoadedItemById(postId)?.postType === PostType.ShortVideo) {
87
+ if (getLoadedItemById(postId)?.postType === 'SHORT_VIDEO') {
77
88
  analyticsHandler?.trackShortVideoProductClick(id, postId);
78
89
  }
79
90
  };
80
91
  const onProductImpression = (id, postId) => {
81
- if (getLoadedItemById(postId)?.postType === PostType.ShortVideo) {
92
+ if (getLoadedItemById(postId)?.postType === 'SHORT_VIDEO') {
82
93
  analyticsHandler?.trackShortVideoProductImpression(id, postId);
83
94
  }
84
95
  };
@@ -104,7 +115,7 @@ const currentItemActions = $derived.by(() => {
104
115
  const postModel = itemAsPostModel(buffer.current);
105
116
  const handler = postActionsGenerator.getPostActionsHandler(postModel);
106
117
  result.push(...handler.actions);
107
- if (managementActions?.editPost && postModel.postType !== PostType.Article) {
118
+ if (managementActions?.editPost && postModel.postType !== 'ARTICLE') {
108
119
  result.push({
109
120
  icon: IconEdit,
110
121
  callback: async () => {
@@ -112,7 +123,7 @@ const currentItemActions = $derived.by(() => {
112
123
  }
113
124
  });
114
125
  }
115
- if (managementActions?.editArticle && postModel.postType === PostType.Article && buffer.current.articleId) {
126
+ if (managementActions?.editArticle && postModel.postType === 'ARTICLE' && buffer.current.articleId) {
116
127
  result.push({
117
128
  icon: IconEdit,
118
129
  callback: async () => {
@@ -146,7 +157,7 @@ const currentItemActions = $derived.by(() => {
146
157
  adImpression: (id) => onAdImpression(id)
147
158
  }} />
148
159
  {/snippet}
149
- <div class="player-host">
160
+ <div class="player-host" use:resolveDialogAnchor>
150
161
  <Player
151
162
  config={contentPlayerConfig}
152
163
  itemActions={currentItemActions}
@@ -165,7 +176,8 @@ const currentItemActions = $derived.by(() => {
165
176
  productClick: (productId) => onProductClick(productId, postModel.id),
166
177
  productImpression: (productId) => onProductImpression(productId, postModel.id),
167
178
  adClick: (adId) => onAdClick(adId),
168
- adImpression: (adId) => onAdImpression(adId)
179
+ adImpression: (adId) => onAdImpression(adId),
180
+ articleReadMore: articleDataProvider ? handleArticleReadMore : undefined
169
181
  }} />
170
182
  {/snippet}
171
183
  </Player>
@@ -1,3 +1,4 @@
1
+ import type { ArticleDataProvider } from '../../articles/data-providers';
1
2
  import type { PostType } from '../../core/enums';
2
3
  import type { IPostModel } from '..';
3
4
  import type { IPostSharingHandler } from '../sharing';
@@ -26,6 +27,8 @@ export type PostsPlayerProps = {
26
27
  sharingHandler?: IPostSharingHandler;
27
28
  analyticsHandler?: IPostAnalyticsHandler;
28
29
  managementActions?: PostManagementActions;
30
+ /** Provider for fetching article content. Enables "Read more" button that opens an article dialog. */
31
+ articleDataProvider?: ArticleDataProvider;
29
32
  playerSettings?: PostPlayerSettings;
30
33
  closeOrchestrator: ICloseOrchestrator;
31
34
  on?: {
@@ -1,4 +1,4 @@
1
- import { Currency } from '../core/enums';
1
+ import type { Currency } from '../core/enums';
2
2
  type CurrencyMode = 'none' | 'symbol' | 'code';
3
3
  export type PriceRepresentationOptions = {
4
4
  currencyMode?: CurrencyMode;
@@ -1,4 +1,3 @@
1
- import { Currency } from '../core/enums';
2
1
  import { Utils } from '@streamscloud/kit/core/utils';
3
2
  export const toPriceRepresentation = (data) => {
4
3
  const { amount, currency, options } = data;
@@ -52,9 +51,9 @@ export const toPriceRepresentation = (data) => {
52
51
  }
53
52
  };
54
53
  const currencyDefaults = {
55
- [Currency.Nok]: { symbol: 'kr', code: 'NOK', missingFractionPlaceholder: '-' },
56
- [Currency.Usd]: { symbol: '$', code: 'USD' },
57
- [Currency.Eur]: { symbol: '€', code: 'EUR' }
54
+ ['NOK']: { symbol: 'kr', code: 'NOK', missingFractionPlaceholder: '-' },
55
+ ['USD']: { symbol: '$', code: 'USD' },
56
+ ['EUR']: { symbol: '€', code: 'EUR' }
58
57
  };
59
58
  const getDecimalSeparator = (locale) => {
60
59
  const nf = new Intl.NumberFormat(locale);
@@ -1,3 +1,3 @@
1
- import { type IPostModel } from '../../../posts/model';
1
+ import type { IPostModel } from '../../../posts/model';
2
2
  import type { StreamLayoutShortVideoModel } from '../models/stream-layout-short-video-model';
3
3
  export declare const mapToPostModel: (model: StreamLayoutShortVideoModel) => IPostModel;
@@ -1,13 +1,9 @@
1
- import { MediaType, PostType } from '../../../core/enums';
2
- import {} from '../../../posts/model';
3
1
  export const mapToPostModel = (model) => {
4
2
  return {
5
3
  id: model.id,
6
- postType: PostType.ShortVideo,
4
+ postType: 'SHORT_VIDEO',
7
5
  media: [
8
- model.media.type === MediaType.Image
9
- ? { isImage: true, url: model.media.url }
10
- : { isImage: false, url: model.media.url, thumbnailUrl: model.media.thumbnailUrl }
6
+ model.media.type === 'IMAGE' ? { isImage: true, url: model.media.url } : { isImage: false, url: model.media.url, thumbnailUrl: model.media.thumbnailUrl }
11
7
  ],
12
8
  mediaFit: 'cover',
13
9
  kicker: null,
@@ -1,4 +1,4 @@
1
- import { MediaType } from '../../../core/enums';
1
+ import type { MediaType } from '../../../core/enums';
2
2
  export type StreamLayoutMediaItemModel = {
3
3
  url: string;
4
4
  thumbnailUrl: string | null;
@@ -1 +1 @@
1
- import { MediaType } from '../../../core/enums';
1
+ export {};
@@ -1,4 +1,4 @@
1
- import { AdType, type Currency } from '../../../core/enums';
1
+ import type { AdType, Currency } from '../../../core/enums';
2
2
  import type { StreamLayoutMediaItemModel } from './stream-layout-media-item-model';
3
3
  import type { StreamLayoutPostHeaderModel } from './stream-layout-post-header-model';
4
4
  export type StreamLayoutShortVideoModel = {
@@ -1 +1 @@
1
- import { AdType } from '../../../core/enums';
1
+ export {};
@@ -1,31 +1,40 @@
1
1
  <script lang="ts">import { CloseOrchestrator } from '../../ui/player/close-orchestrator';
2
2
  import { createShadowRoot } from '../../ui/shadow-dom';
3
- import { StreamsPlayerHostSettings } from './streams-player-host-settings.svelte';
4
3
  import { default as StreamsPlayerProxy } from './streams-player-proxy.svelte';
5
- import { mount, unmount, untrack } from 'svelte';
4
+ import { mount, unmount } from 'svelte';
6
5
  let { dataProvider, postSocialInteractionsHandler, sharingHandler, amplificationParameters, playerSettings, analyticsHandler, on } = $props();
7
- const settingsHolder = untrack(() => new StreamsPlayerHostSettings(playerSettings));
8
- $effect(() => {
9
- settingsHolder.update(playerSettings);
10
- });
11
6
  const initHost = (node) => {
12
7
  const shadowRoot = createShadowRoot(node);
13
8
  const mounted = mount(StreamsPlayerProxy, {
14
9
  target: shadowRoot,
15
10
  props: {
16
- dataProvider,
17
- postSocialInteractionsHandler,
18
- sharingHandler,
19
- analyticsHandler,
20
- amplificationParameters,
21
- playerSettings: settingsHolder,
11
+ get dataProvider() {
12
+ return dataProvider;
13
+ },
14
+ get postSocialInteractionsHandler() {
15
+ return postSocialInteractionsHandler;
16
+ },
17
+ get sharingHandler() {
18
+ return sharingHandler;
19
+ },
20
+ get analyticsHandler() {
21
+ return analyticsHandler;
22
+ },
23
+ get amplificationParameters() {
24
+ return amplificationParameters;
25
+ },
26
+ get playerSettings() {
27
+ return playerSettings;
28
+ },
22
29
  closeOrchestrator: new CloseOrchestrator({
23
30
  closeFn: async () => {
24
31
  await unmount(mounted);
25
32
  },
26
33
  canClose: false
27
34
  }),
28
- on
35
+ get on() {
36
+ return on;
37
+ }
29
38
  }
30
39
  });
31
40
  return {
@@ -36,7 +36,7 @@ let { buffer, activePageId, on } = $props();
36
36
  --_cross-browser-scrollbar--track-color: transparent;
37
37
  }
38
38
  .stream-overview-pages:hover {
39
- --_cross-browser-scrollbar--thumb-color: var(--scrollbar--thumb-color, #7d7d7d);
39
+ --_cross-browser-scrollbar--thumb-color: var(--scrollbar--thumb-color, light-dark(#999999, #333333));
40
40
  --_cross-browser-scrollbar--track-color: var(--scrollbar--track-color, transparent);
41
41
  }
42
42
  .stream-overview-pages::-webkit-scrollbar {
@@ -10,7 +10,7 @@ const handleBackgroundImagedLoaded = (url) => {
10
10
 
11
11
  <ShadowRoot
12
12
  locale={playerSettings?.locale}
13
- theme={playerSettings?.theme ?? 'dark'}
13
+ theme={playerSettings?.theme}
14
14
  backgroundDisabled={playerSettings?.disableBackground === true}
15
15
  backgroundImageUrl={backgroundImageUrl}>
16
16
  <StreamsPlayerView
@@ -0,0 +1,3 @@
1
+ export { MediaItemView } from './media-item-view';
2
+ export { MediaItemsGallery } from './media-items-gallery';
3
+ export { type MediaItem, type MediaItemMetadataModel, type MediaItemWithMetadataModel, getMediaItemImageUrl } from './types';
@@ -0,0 +1,3 @@
1
+ export { MediaItemView } from './media-item-view';
2
+ export { MediaItemsGallery } from './media-items-gallery';
3
+ export { getMediaItemImageUrl } from './types';
@@ -1,9 +1,21 @@
1
- <script lang="ts">import { MediaFormat, MediaType } from '../../core/enums';
2
- import { getMediaItemImageUrl } from '../../core/media';
1
+ <script lang="ts">import { getMediaItemImageUrl } from '../types';
2
+ import IconDelete from '@fluentui/svg-icons/icons/delete_20_regular.svg?raw';
3
+ import IconEdit from '@fluentui/svg-icons/icons/edit_20_regular.svg?raw';
4
+ import { cardActionContainer, CardActions } from '@streamscloud/kit/ui/card-actions';
3
5
  import { Image } from '@streamscloud/kit/ui/image';
4
6
  import { ProportionalContainer } from '@streamscloud/kit/ui/proportional-container';
5
7
  import { Video } from '@streamscloud/kit/ui/video';
6
8
  let { media, ratio = 0, inert = false, on } = $props();
9
+ const actions = $derived.by(() => {
10
+ const result = [];
11
+ if (on?.edit) {
12
+ result.push({ icon: IconEdit, iconColor: 'blue', callback: on.edit });
13
+ }
14
+ if (on?.remove) {
15
+ result.push({ icon: IconDelete, iconColor: 'red', callback: on.remove });
16
+ }
17
+ return result;
18
+ });
7
19
  const handleClick = (e) => {
8
20
  if (on?.click) {
9
21
  e.stopPropagation();
@@ -16,7 +28,7 @@ const parsedRatio = $derived.by(() => {
16
28
  }
17
29
  else {
18
30
  if (typeof ratio !== 'number') {
19
- return ratio === MediaFormat.W16H9 ? 16 / 9 : 4 / 3;
31
+ return ratio === 'W16H9' ? 16 / 9 : 4 / 3;
20
32
  }
21
33
  else {
22
34
  return ratio;
@@ -27,7 +39,7 @@ const parsedRatio = $derived.by(() => {
27
39
 
28
40
  {#if media}
29
41
  {#snippet mediaView()}
30
- {#if media.type === MediaType.Image}
42
+ {#if media.type === 'IMAGE'}
31
43
  <div class="media-item-view__image" onclick={handleClick} onkeydown={() => {}} role="none">
32
44
  <Image src={getMediaItemImageUrl(media)} />
33
45
  </div>
@@ -38,7 +50,12 @@ const parsedRatio = $derived.by(() => {
38
50
  {/if}
39
51
  {/snippet}
40
52
 
41
- <div class="media-item-view" class:media-item-view--clickable={on?.click} class:media-item-view--fit-parent={ratio === 'fit-parent'} inert={inert}>
53
+ <div
54
+ class="media-item-view"
55
+ class:media-item-view--clickable={on?.click}
56
+ class:media-item-view--fit-parent={ratio === 'fit-parent'}
57
+ use:cardActionContainer
58
+ inert={inert}>
42
59
  {#if parsedRatio}
43
60
  <ProportionalContainer ratio={parsedRatio}>
44
61
  {@render mediaView()}
@@ -46,6 +63,7 @@ const parsedRatio = $derived.by(() => {
46
63
  {:else}
47
64
  {@render mediaView()}
48
65
  {/if}
66
+ <CardActions actions={actions} />
49
67
  </div>
50
68
  {/if}
51
69
 
@@ -1,11 +1,13 @@
1
- import { MediaFormat } from '../../core/enums';
2
- import { type MediaItemModel } from '../../core/media';
1
+ import type { MediaFormat } from '../../../core/enums';
2
+ import { type MediaItem } from '../types';
3
3
  type Props = {
4
- media: MediaItemModel | null;
4
+ media: MediaItem | null;
5
5
  ratio?: number | MediaFormat | 'fit-parent';
6
6
  inert?: boolean;
7
7
  on?: {
8
8
  click?: () => void;
9
+ edit?: () => void;
10
+ remove?: () => void;
9
11
  };
10
12
  };
11
13
  declare const Cmp: import("svelte").Component<Props, {}, "">;
@@ -1,9 +1,14 @@
1
- <script lang="ts">import { MediaFormat } from '../../core/enums';
2
- import {} from '../../core/media';
3
- import { MediaItemView } from '../media-item-view';
4
- import { GalleryLayout } from './types';
1
+ <script lang="ts">import { MediaItemView } from '../media-item-view';
2
+ import { getDialogAnchor } from '../../shadow-dom/shadow-root-service';
3
+ import {} from '../types';
4
+ import { GalleryLayout } from './gallery-layout';
5
+ import { openMediaViewer } from '@streamscloud/kit/ui/media-viewer-dialog';
5
6
  let { media, singleImageRatio = 0, inert = false, on } = $props();
7
+ let dialogHost;
6
8
  let layout = $state(null);
9
+ const resolveDialogHost = (el) => {
10
+ dialogHost = getDialogAnchor(el) ?? undefined;
11
+ };
7
12
  const initLayout = async () => {
8
13
  if (!media.length || media.length === 1 || media.length > 4) {
9
14
  layout = null;
@@ -17,35 +22,31 @@ $effect(() => {
17
22
  });
18
23
  const upperTwoImages = $derived(media.length > 4 ? media.slice(0, 2) : []);
19
24
  const bottomThreeImages = $derived(media.length > 4 ? media.slice(2, 5) : []);
25
+ const toMediaViewerItemType = (type) => {
26
+ switch (type) {
27
+ case 'VIDEO':
28
+ case 'SHORT_VIDEO':
29
+ case 'AUDIO':
30
+ return 'video';
31
+ default:
32
+ return 'image';
33
+ }
34
+ };
20
35
  const handleGalleryItemClick = (index) => {
21
36
  if (on?.click) {
22
- on?.click(index);
37
+ on.click(index);
23
38
  return;
24
39
  }
25
- /*const toMediaViewerItemType = (type: MediaType) => {
26
- switch (type) {
27
- case MediaType.Image:
28
- return MediaViewerItemType.Image;
29
- case MediaType.Video:
30
- case MediaType.ShortVideo:
31
- return MediaViewerItemType.Video;
32
- case MediaType.Audio:
33
- return MediaViewerItemType.Audio;
34
- default:
35
- Utils.assertUnreachable(type);
36
- }
37
- };
38
40
  openMediaViewer({
39
- items: media.map((i) => ({
40
- id: randomNanoid(),
41
- url: i.url,
42
- thumbnailUrl: i.thumbnailUrl,
43
- type: toMediaViewerItemType(i.type),
44
- width: i.metadata.width,
45
- height: i.metadata.height
46
- })),
47
- index
48
- });*/
41
+ items: media.map((i) => ({
42
+ url: i.url,
43
+ thumbnailUrl: i.thumbnailUrl ?? null,
44
+ type: toMediaViewerItemType(i.type),
45
+ width: i.metadata.width,
46
+ height: i.metadata.height
47
+ })),
48
+ index
49
+ }, dialogHost);
49
50
  };
50
51
  </script>
51
52
 
@@ -56,17 +57,21 @@ const handleGalleryItemClick = (index) => {
56
57
  ratio={singleImageRatio}
57
58
  inert={inert}
58
59
  on={{
59
- click: on?.click ? () => on?.click(0) : undefined
60
+ click: on?.click ? () => on?.click?.(0) : undefined,
61
+ edit: on?.edit ? () => on?.edit?.(0) : undefined,
62
+ remove: on?.remove ? () => on?.remove?.(0) : undefined
60
63
  }} />
61
64
  {:else}
62
- <div class="gallery-container" inert={inert}>
63
- {#snippet galleryItem(index: NumberType)}
65
+ <div class="gallery-container" use:resolveDialogHost inert={inert}>
66
+ {#snippet galleryItem(index: number)}
64
67
  <div class="gallery-item">
65
68
  <MediaItemView
66
69
  media={media[index]}
67
70
  ratio="fit-parent"
68
71
  on={{
69
- click: () => handleGalleryItemClick(index)
72
+ click: () => handleGalleryItemClick(index),
73
+ edit: on?.edit ? () => on?.edit?.(index) : undefined,
74
+ remove: on?.remove ? () => on?.remove?.(index) : undefined
70
75
  }} />
71
76
  </div>
72
77
  {/snippet}
@@ -1,11 +1,13 @@
1
- import { MediaFormat } from '../../core/enums';
2
- import { type MediaItemWithMetadataModel } from '../../core/media';
1
+ import type { MediaFormat } from '../../../core/enums';
2
+ import { type MediaItemWithMetadataModel } from '../types';
3
3
  type Props = {
4
4
  media: Array<MediaItemWithMetadataModel> | ReadonlyArray<MediaItemWithMetadataModel>;
5
5
  singleImageRatio?: number | MediaFormat;
6
6
  inert?: boolean;
7
7
  on?: {
8
- click: (index: number) => void;
8
+ click?: (index: number) => void;
9
+ edit?: (index: number) => void;
10
+ remove?: (index: number) => void;
9
11
  };
10
12
  };
11
13
  declare const Cmp: import("svelte").Component<Props, {}, "">;
@@ -1,4 +1,4 @@
1
- import { type MediaItemWithMetadataModel } from '../../core/media';
1
+ import { type MediaItemWithMetadataModel } from '../types';
2
2
  export declare class GalleryLayout {
3
3
  layoutClass: string;
4
4
  firstImage: MediaItemWithMetadataModel;