@streamscloud/embeddable 16.0.7 → 16.1.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 (160) 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 +38 -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 +103 -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/index.d.ts +0 -1
  96. package/dist/media-center/media-center/index.js +0 -1
  97. package/dist/media-center/media-center/media-center-settings.svelte.d.ts +1 -1
  98. package/dist/media-center/media-center/media-center-settings.svelte.js +2 -2
  99. package/dist/media-center/media-center/moments/moments-feed-handler.svelte.d.ts +1 -1
  100. package/dist/media-center/media-center/moments/moments-feed-handler.svelte.js +2 -3
  101. package/dist/media-center/media-center/moments/moments-state.svelte.d.ts +1 -1
  102. package/dist/media-center/media-center/moments/moments-state.svelte.js +1 -3
  103. package/dist/media-center/media-center/posts-feed/feed-providers-generator.js +1 -2
  104. package/dist/media-center/media-center/posts-feed/posts-feed-handler.svelte.d.ts +1 -1
  105. package/dist/media-center/media-center/posts-feed/posts-feed-handler.svelte.js +2 -2
  106. package/dist/media-page/cmp.media-page.svelte +10 -9
  107. package/dist/media-page/index.js +4 -4
  108. package/dist/posts/attachments/cmp.attachments.svelte +2 -3
  109. package/dist/posts/model/post-model.d.ts +2 -1
  110. package/dist/posts/model/post-model.js +2 -1
  111. package/dist/posts/post-viewer/attachments-horizontal.svelte +1 -2
  112. package/dist/posts/post-viewer/cmp.post-viewer.svelte +12 -5
  113. package/dist/posts/post-viewer/cmp.post-viewer.svelte.d.ts +1 -0
  114. package/dist/posts/post-viewer/mapper.js +6 -7
  115. package/dist/posts/post-viewer/post-texts.svelte +8 -1
  116. package/dist/posts/post-viewer/post-texts.svelte.d.ts +3 -0
  117. package/dist/posts/posts-player/cmp.posts-player.svelte +23 -13
  118. package/dist/posts/posts-player/cmp.posts-player.svelte.d.ts +2 -0
  119. package/dist/posts/posts-player/index.d.ts +8 -1
  120. package/dist/posts/posts-player/index.js +7 -1
  121. package/dist/posts/posts-player/posts-player-proxy.svelte +3 -2
  122. package/dist/posts/posts-player/posts-player-proxy.svelte.d.ts +2 -0
  123. package/dist/posts/posts-player/posts-player-view.svelte +22 -9
  124. package/dist/posts/posts-player/types.d.ts +3 -0
  125. package/dist/products/price-helper.d.ts +1 -1
  126. package/dist/products/price-helper.js +3 -4
  127. package/dist/streams/layout/models/mapper.d.ts +1 -1
  128. package/dist/streams/layout/models/mapper.js +2 -6
  129. package/dist/streams/layout/models/stream-layout-media-item-model.d.ts +1 -1
  130. package/dist/streams/layout/models/stream-layout-media-item-model.js +1 -1
  131. package/dist/streams/layout/models/stream-layout-short-video-model.d.ts +1 -1
  132. package/dist/streams/layout/models/stream-layout-short-video-model.js +1 -1
  133. package/dist/streams/streams-player/cmp.streams-player.svelte +22 -13
  134. package/dist/streams/streams-player/streams-player-proxy.svelte +1 -1
  135. package/dist/ui/media-items/index.d.ts +3 -0
  136. package/dist/ui/media-items/index.js +3 -0
  137. package/dist/ui/{media-item-view → media-items/media-item-view}/cmp.media-item-view.svelte +23 -5
  138. package/dist/ui/{media-item-view → media-items/media-item-view}/cmp.media-item-view.svelte.d.ts +5 -3
  139. package/dist/ui/{media-items-gallery → media-items/media-items-gallery}/cmp.media-items-gallery.svelte +31 -31
  140. package/dist/ui/{media-items-gallery → media-items/media-items-gallery}/cmp.media-items-gallery.svelte.d.ts +5 -3
  141. package/dist/ui/{media-items-gallery/types.d.ts → media-items/media-items-gallery/gallery-layout.d.ts} +1 -1
  142. package/dist/ui/{media-items-gallery/types.js → media-items/media-items-gallery/gallery-layout.js} +1 -1
  143. package/dist/ui/media-items/types.d.ts +14 -0
  144. package/dist/ui/media-items/types.js +1 -0
  145. package/dist/ui/shadow-dom/cmp.shadow-root.svelte +3 -2
  146. package/dist/ui/shadow-dom/index.d.ts +1 -1
  147. package/dist/ui/shadow-dom/index.js +1 -1
  148. package/dist/ui/shadow-dom/shadow-root-service.d.ts +1 -0
  149. package/dist/ui/shadow-dom/shadow-root-service.js +8 -0
  150. package/package.json +11 -3
  151. package/dist/core/media/types.d.ts +0 -13
  152. package/dist/posts/posts-player/posts-player-host-settings.svelte.d.ts +0 -20
  153. package/dist/posts/posts-player/posts-player-host-settings.svelte.js +0 -15
  154. package/dist/streams/streams-player/streams-player-host-settings.svelte.d.ts +0 -20
  155. package/dist/streams/streams-player/streams-player-host-settings.svelte.js +0 -15
  156. /package/dist/{core/media → articles/article-dialog}/types.js +0 -0
  157. /package/dist/ui/{media-item-view → media-items/media-item-view}/index.d.ts +0 -0
  158. /package/dist/ui/{media-item-view → media-items/media-item-view}/index.js +0 -0
  159. /package/dist/ui/{media-items-gallery → media-items/media-items-gallery}/index.d.ts +0 -0
  160. /package/dist/ui/{media-items-gallery → media-items/media-items-gallery}/index.js +0 -0
@@ -0,0 +1,5 @@
1
+ export { default as Article } from './cmp.article.svelte';
2
+ export { default as ArticleView } from './article-view.svelte';
3
+ export { default as FactsContainer } from './cmp.facts-container.svelte';
4
+ export { fieldIsFilled, layoutIsFilled, sectionIsFilled } from './helpers';
5
+ export { ArticleStylesHelper } from './styles-transformer';
@@ -0,0 +1,47 @@
1
+ type IndentValues = {
2
+ top: number;
3
+ right: number;
4
+ bottom: number;
5
+ left: number;
6
+ };
7
+ export declare class ArticleStylesHelper {
8
+ static generatePaddingsCssVar: (data: {
9
+ styles: {
10
+ paddingTop?: number | null;
11
+ paddingBottom?: number | null;
12
+ paddingLeft?: number | null;
13
+ paddingRight?: number | null;
14
+ };
15
+ mobileView: boolean;
16
+ }) => string;
17
+ static parsePaddingValues: (data: {
18
+ styles: {
19
+ paddingTop?: number | null;
20
+ paddingBottom?: number | null;
21
+ paddingLeft?: number | null;
22
+ paddingRight?: number | null;
23
+ };
24
+ mobileView: boolean;
25
+ }) => IndentValues;
26
+ static generateMarginsCssVar: (data: {
27
+ styles: {
28
+ marginTop?: number | null;
29
+ marginBottom?: number | null;
30
+ marginLeft?: number | null;
31
+ marginRight?: number | null;
32
+ } | null;
33
+ mobileView: boolean;
34
+ useFallbackIfMissing?: boolean;
35
+ }) => string;
36
+ static parseMarginValues: (data: {
37
+ styles: {
38
+ marginTop?: number | null;
39
+ marginBottom?: number | null;
40
+ marginLeft?: number | null;
41
+ marginRight?: number | null;
42
+ } | null;
43
+ mobileView: boolean;
44
+ useFallbackIfMissing?: boolean;
45
+ }) => IndentValues;
46
+ }
47
+ export {};
@@ -0,0 +1,38 @@
1
+ export class ArticleStylesHelper {
2
+ static generatePaddingsCssVar = (data) => {
3
+ const indents = ArticleStylesHelper.parsePaddingValues(data);
4
+ const paddings = [indents.top, indents.right, indents.bottom, indents.left];
5
+ return paddings.map((p) => p + 'rem').join(' ');
6
+ };
7
+ static parsePaddingValues = (data) => {
8
+ const { styles, mobileView } = data;
9
+ const verticalScaleFactor = mobileView ? 0.7 : 1;
10
+ const horizontalScaleFactor = mobileView ? 0.3 : 1;
11
+ return {
12
+ top: styles.paddingTop ? styles.paddingTop * verticalScaleFactor : 0,
13
+ right: styles.paddingRight ? styles.paddingRight * horizontalScaleFactor : 0,
14
+ bottom: styles.paddingBottom ? styles.paddingBottom * verticalScaleFactor : 0,
15
+ left: styles.paddingLeft ? styles.paddingLeft * horizontalScaleFactor : 0
16
+ };
17
+ };
18
+ static generateMarginsCssVar = (data) => {
19
+ const indents = ArticleStylesHelper.parseMarginValues(data);
20
+ const margins = [indents.top, indents.right, indents.bottom, indents.left];
21
+ return margins.map((p) => p + 'rem').join(' ');
22
+ };
23
+ static parseMarginValues = (data) => {
24
+ const { styles, useFallbackIfMissing = true, mobileView } = data;
25
+ if (!styles && !useFallbackIfMissing) {
26
+ return { top: 0, right: 0, bottom: 0, left: 0 };
27
+ }
28
+ const parsedStyles = styles || { marginBottom: 0.875 };
29
+ const verticalScaleFactor = mobileView ? 0.7 : 1;
30
+ const horizontalScaleFactor = mobileView ? 0.3 : 1;
31
+ return {
32
+ top: 'marginTop' in parsedStyles && parsedStyles.marginTop ? parsedStyles.marginTop * verticalScaleFactor : 0,
33
+ right: 'marginRight' in parsedStyles && parsedStyles.marginRight ? parsedStyles.marginRight * horizontalScaleFactor : 0,
34
+ bottom: 'marginBottom' in parsedStyles && parsedStyles.marginBottom ? parsedStyles.marginBottom * verticalScaleFactor : 0,
35
+ left: 'marginLeft' in parsedStyles && parsedStyles.marginLeft ? parsedStyles.marginLeft * horizontalScaleFactor : 0
36
+ };
37
+ };
38
+ }
@@ -0,0 +1,32 @@
1
+ import type { ArticleFieldModel } from './fields/types';
2
+ export type ArticleMetadata = {
3
+ displayDate: string;
4
+ };
5
+ export type ArticleSeo = {
6
+ title: string;
7
+ description: string;
8
+ keywords: string[];
9
+ };
10
+ export type ArticleSectionModel = {
11
+ id: string;
12
+ styles: ArticleSectionStylesModel | null;
13
+ layouts: ArticleLayoutModel[];
14
+ facts: string | null;
15
+ };
16
+ export type ArticleSectionStylesModel = {
17
+ paddingTop: number | null;
18
+ paddingBottom: number | null;
19
+ paddingLeft: number | null;
20
+ paddingRight: number | null;
21
+ };
22
+ export type ArticleLayoutModel = {
23
+ id: string;
24
+ styles: ArticleLayoutStylesModel | null;
25
+ fields: ArticleFieldModel[];
26
+ };
27
+ export type ArticleLayoutStylesModel = {
28
+ paddingTop: number | null;
29
+ paddingBottom: number | null;
30
+ paddingLeft: number | null;
31
+ paddingRight: number | null;
32
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,3 @@
1
+ export declare class ArticleDialogLocalization {
2
+ get failedToLoad(): string;
3
+ }
@@ -0,0 +1,9 @@
1
+ import { AppLocale } from '@streamscloud/kit/core/locale';
2
+ export class ArticleDialogLocalization {
3
+ get failedToLoad() {
4
+ return loc.failedToLoad[AppLocale.current];
5
+ }
6
+ }
7
+ const loc = {
8
+ failedToLoad: { en: 'Failed to load article', no: 'Kunne ikke laste artikkelen' }
9
+ };
@@ -0,0 +1,103 @@
1
+ <script lang="ts">import { default as ArticleView } from '../article/article-view.svelte';
2
+ import { ArticleDialogLocalization } from './article-dialog-localization';
3
+ import { DialogCloseButton } from '@streamscloud/kit/ui/dialog';
4
+ import { Loading } from '@streamscloud/kit/ui/loading';
5
+ import { untrack } from 'svelte';
6
+ let { controller, data } = $props();
7
+ const localization = new ArticleDialogLocalization();
8
+ $effect(() => untrack(() => {
9
+ controller.updateSettings({ closeOnEsc: true, closeOnClickOutside: true });
10
+ controller.updateContainerSettings({ position: 'full-screen' });
11
+ }));
12
+ let articleData = $state.raw(null);
13
+ let loading = $state(true);
14
+ let failed = $state(false);
15
+ const load = async () => {
16
+ loading = true;
17
+ failed = false;
18
+ try {
19
+ const result = await data.fetchArticle({ id: data.articleId });
20
+ if (result) {
21
+ articleData = result;
22
+ }
23
+ else {
24
+ failed = true;
25
+ }
26
+ }
27
+ catch {
28
+ failed = true;
29
+ }
30
+ loading = false;
31
+ };
32
+ void load();
33
+ </script>
34
+
35
+ <div class="article-dialog">
36
+ <div class="article-dialog__close">
37
+ <DialogCloseButton controller={controller} />
38
+ </div>
39
+ <div class="article-dialog__content">
40
+ {#if loading}
41
+ <div class="article-dialog__loading">
42
+ <Loading positionAbsoluteCenter timeout={400} />
43
+ </div>
44
+ {:else if failed}
45
+ <div class="article-dialog__error">{localization.failedToLoad}</div>
46
+ {:else if articleData}
47
+ <ArticleView sections={articleData.sections} metadata={articleData.metadata} />
48
+ {/if}
49
+ </div>
50
+ </div>
51
+
52
+ <style>.article-dialog {
53
+ width: 100%;
54
+ height: 100%;
55
+ position: relative;
56
+ }
57
+ .article-dialog__close {
58
+ --sc-kit--dialog-close-button--color: #fff;
59
+ --sc-kit--icon--filter: drop-shadow(1px 1px 0 rgba(0, 0, 0, 0.2));
60
+ position: absolute;
61
+ top: 0.75rem;
62
+ right: 1rem;
63
+ z-index: 10;
64
+ }
65
+ .article-dialog__content {
66
+ --article--max-width: 56.25rem;
67
+ --article--container-background: light-dark(rgba(255, 255, 255, 0.8), rgba(0, 0, 0, 0.8));
68
+ width: 100%;
69
+ height: 100%;
70
+ overflow-y: auto;
71
+ --_cross-browser-scrollbar--thumb-color: var(--scrollbar--thumb-color, #7d7d7d);
72
+ --_cross-browser-scrollbar--track-color: var(--scrollbar--track-color, transparent);
73
+ }
74
+ .article-dialog__content::-webkit-scrollbar {
75
+ width: 6px;
76
+ height: 6px;
77
+ }
78
+ .article-dialog__content::-webkit-scrollbar-track {
79
+ background: var(--_cross-browser-scrollbar--track-color);
80
+ border-radius: 100vw;
81
+ }
82
+ .article-dialog__content::-webkit-scrollbar-thumb {
83
+ background: var(--_cross-browser-scrollbar--thumb-color);
84
+ border-radius: 100vw;
85
+ }
86
+ @supports (scrollbar-color: transparent transparent) {
87
+ .article-dialog__content {
88
+ scrollbar-color: var(--_cross-browser-scrollbar--thumb-color) var(--_cross-browser-scrollbar--track-color);
89
+ scrollbar-width: thin;
90
+ }
91
+ }
92
+ .article-dialog__loading {
93
+ position: relative;
94
+ min-height: 18.75rem;
95
+ }
96
+ .article-dialog__error {
97
+ display: flex;
98
+ align-items: center;
99
+ justify-content: center;
100
+ min-height: 12.5rem;
101
+ color: light-dark(#9ca3af, #6b7280);
102
+ font-size: 1rem;
103
+ }</style>
@@ -0,0 +1,9 @@
1
+ import type { ArticleDialogViewData } from './types';
2
+ import { type DialogController } from '@streamscloud/kit/ui/dialog';
3
+ type Props = {
4
+ controller: DialogController;
5
+ data: ArticleDialogViewData;
6
+ };
7
+ declare const Cmp: import("svelte").Component<Props, {}, "">;
8
+ type Cmp = ReturnType<typeof Cmp>;
9
+ export default Cmp;
@@ -0,0 +1,6 @@
1
+ import type { ArticleDataProvider } from '../data-providers';
2
+ export declare const openArticleDialog: (data: {
3
+ anchor: HTMLElement;
4
+ articleId: string;
5
+ fetchArticle: ArticleDataProvider["fetchArticle"];
6
+ }) => void;
@@ -0,0 +1,10 @@
1
+ import { default as ArticleDialog } from './cmp.article-dialog.svelte';
2
+ import { Dialogs } from '@streamscloud/kit/ui/dialog';
3
+ export const openArticleDialog = (data) => {
4
+ const { anchor, articleId, fetchArticle } = data;
5
+ void Dialogs.open({
6
+ view: ArticleDialog,
7
+ data: { articleId, fetchArticle },
8
+ host: anchor
9
+ });
10
+ };
@@ -0,0 +1,6 @@
1
+ import type { ArticleDataProvider } from '../data-providers';
2
+ /** Data passed to the article dialog view component. */
3
+ export type ArticleDialogViewData = {
4
+ articleId: string;
5
+ fetchArticle: ArticleDataProvider['fetchArticle'];
6
+ };
@@ -0,0 +1 @@
1
+ export type { ArticleData, ArticleDataProvider } from './types';
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,14 @@
1
+ import type { ArticleMetadata, ArticleSectionModel, ArticleSeo } from '../article';
2
+ /** Article data returned by a data provider. */
3
+ export type ArticleData = {
4
+ sections: ArticleSectionModel[];
5
+ metadata: ArticleMetadata;
6
+ seo: ArticleSeo;
7
+ };
8
+ /** Provider for fetching article content by ID. */
9
+ export type ArticleDataProvider = {
10
+ fetchArticle: (input: {
11
+ id?: string;
12
+ slug?: string;
13
+ }) => Promise<ArticleData | null>;
14
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -1,50 +1,15 @@
1
- export declare enum PostSourceType {
2
- MediaPage = "MEDIA_PAGE",
3
- Organization = "ORGANIZATION",
4
- UserProfile = "USER_PROFILE"
5
- }
6
- export declare enum AdType {
7
- BannerResponsive = "BANNER_RESPONSIVE",
8
- MediaDialogPromotion = "MEDIA_DIALOG_PROMOTION",
9
- Story = "STORY"
10
- }
11
- export declare enum Currency {
12
- Eur = "EUR",
13
- Nok = "NOK",
14
- Usd = "USD"
15
- }
16
- export declare enum MediaType {
17
- Audio = "AUDIO",
18
- Image = "IMAGE",
19
- ShortVideo = "SHORT_VIDEO",
20
- Video = "VIDEO"
21
- }
22
- export declare enum MediaFormat {
23
- W4H3 = "W4H3",
24
- W16H9 = "W16H9"
25
- }
26
- export declare enum ImageScale {
27
- Big = "BIG",
28
- Medium = "MEDIUM",
29
- OriginalEncoded = "ORIGINAL_ENCODED",
30
- Small = "SMALL"
31
- }
32
- export declare enum ProfileType {
33
- Organization = "ORGANIZATION"
34
- }
35
- export declare enum PostType {
36
- Article = "ARTICLE",
37
- Media = "MEDIA",
38
- Moment = "MOMENT",
39
- ShortVideo = "SHORT_VIDEO",
40
- Video = "VIDEO"
41
- }
42
- export declare enum Status {
43
- Published = "PUBLISHED"
44
- }
45
- export declare enum StreamStatus {
46
- Published = "PUBLISHED"
47
- }
48
- export declare enum EmbedStreamsOrderBy {
49
- ContentUpdatedAt = "CONTENT_UPDATED_AT"
50
- }
1
+ export type PostSourceType = 'MEDIA_PAGE' | 'ORGANIZATION' | 'USER_PROFILE';
2
+ export type AdType = 'BANNER_RESPONSIVE' | 'MEDIA_DIALOG_PROMOTION' | 'STORY';
3
+ export type Currency = 'EUR' | 'NOK' | 'USD';
4
+ export type MediaType = 'AUDIO' | 'IMAGE' | 'SHORT_VIDEO' | 'VIDEO';
5
+ export type MediaFormat = 'W4H3' | 'W16H9';
6
+ export type ImageScale = 'BIG' | 'MEDIUM' | 'ORIGINAL_ENCODED' | 'SMALL';
7
+ export type ProfileType = 'ORGANIZATION';
8
+ export type PostType = 'ARTICLE' | 'MEDIA' | 'MOMENT' | 'SHORT_VIDEO' | 'VIDEO';
9
+ export type Status = 'PUBLISHED';
10
+ export type StreamStatus = 'PUBLISHED';
11
+ export type EmbedStreamsOrderBy = 'CONTENT_UPDATED_AT';
12
+ export type ArticleFieldType = 'BYLINE' | 'IMAGE' | 'MEDIA' | 'MEDIA_GALLERY' | 'RICH_TEXT' | 'TEXT' | 'VIDEO';
13
+ export type TextFieldMode = 'MULTILINE' | 'SINGLE_LINE';
14
+ export type TextFieldWeight = 'BOLD' | 'NORMAL' | 'SEMI_BOLD';
15
+ export type GalleryFieldMode = 'GALLERY' | 'SLIDER';
@@ -1,61 +1 @@
1
- export var PostSourceType;
2
- (function (PostSourceType) {
3
- PostSourceType["MediaPage"] = "MEDIA_PAGE";
4
- PostSourceType["Organization"] = "ORGANIZATION";
5
- PostSourceType["UserProfile"] = "USER_PROFILE";
6
- })(PostSourceType || (PostSourceType = {}));
7
- export var AdType;
8
- (function (AdType) {
9
- AdType["BannerResponsive"] = "BANNER_RESPONSIVE";
10
- AdType["MediaDialogPromotion"] = "MEDIA_DIALOG_PROMOTION";
11
- AdType["Story"] = "STORY";
12
- })(AdType || (AdType = {}));
13
- export var Currency;
14
- (function (Currency) {
15
- Currency["Eur"] = "EUR";
16
- Currency["Nok"] = "NOK";
17
- Currency["Usd"] = "USD";
18
- })(Currency || (Currency = {}));
19
- export var MediaType;
20
- (function (MediaType) {
21
- MediaType["Audio"] = "AUDIO";
22
- MediaType["Image"] = "IMAGE";
23
- MediaType["ShortVideo"] = "SHORT_VIDEO";
24
- MediaType["Video"] = "VIDEO";
25
- })(MediaType || (MediaType = {}));
26
- export var MediaFormat;
27
- (function (MediaFormat) {
28
- MediaFormat["W4H3"] = "W4H3";
29
- MediaFormat["W16H9"] = "W16H9";
30
- })(MediaFormat || (MediaFormat = {}));
31
- export var ImageScale;
32
- (function (ImageScale) {
33
- ImageScale["Big"] = "BIG";
34
- ImageScale["Medium"] = "MEDIUM";
35
- ImageScale["OriginalEncoded"] = "ORIGINAL_ENCODED";
36
- ImageScale["Small"] = "SMALL";
37
- })(ImageScale || (ImageScale = {}));
38
- export var ProfileType;
39
- (function (ProfileType) {
40
- ProfileType["Organization"] = "ORGANIZATION";
41
- })(ProfileType || (ProfileType = {}));
42
- export var PostType;
43
- (function (PostType) {
44
- PostType["Article"] = "ARTICLE";
45
- PostType["Media"] = "MEDIA";
46
- PostType["Moment"] = "MOMENT";
47
- PostType["ShortVideo"] = "SHORT_VIDEO";
48
- PostType["Video"] = "VIDEO";
49
- })(PostType || (PostType = {}));
50
- export var Status;
51
- (function (Status) {
52
- Status["Published"] = "PUBLISHED";
53
- })(Status || (Status = {}));
54
- export var StreamStatus;
55
- (function (StreamStatus) {
56
- StreamStatus["Published"] = "PUBLISHED";
57
- })(StreamStatus || (StreamStatus = {}));
58
- export var EmbedStreamsOrderBy;
59
- (function (EmbedStreamsOrderBy) {
60
- EmbedStreamsOrderBy["ContentUpdatedAt"] = "CONTENT_UPDATED_AT";
61
- })(EmbedStreamsOrderBy || (EmbedStreamsOrderBy = {}));
1
+ export {};
@@ -1,3 +1,6 @@
1
- export declare const createLocalGQLClient: (graphqlOrigin?: string, headers?: HeadersInit, customFetch?: typeof fetch) => any;
1
+ export declare const createLocalGQLClient: (graphqlOrigin?: string, options?: {
2
+ initiator?: string;
3
+ customFetch?: typeof fetch;
4
+ }) => any;
2
5
  export declare const resolveGraphQLOrigin: (origin?: string) => string;
3
6
  export declare const constructGraphQLUrl: (graphqlOrigin?: string) => string;
@@ -1,8 +1,8 @@
1
1
  import { createGQLClient } from '@streamscloud/kit/core';
2
- export const createLocalGQLClient = (graphqlOrigin, headers, customFetch) => createGQLClient({
2
+ export const createLocalGQLClient = (graphqlOrigin, options) => createGQLClient({
3
3
  url: constructGraphQLUrl(resolveGraphQLOrigin(graphqlOrigin)),
4
- headers,
5
- customFetch
4
+ headers: options?.initiator ? { 'x-initiator': options.initiator } : undefined,
5
+ customFetch: options?.customFetch
6
6
  });
7
7
  export const resolveGraphQLOrigin = (origin) => {
8
8
  return origin || 'https://api.streamscloud.com';
@@ -1,2 +1 @@
1
- export { type MediaItemModel, type MediaItemMetadataModel, type MediaItemWithMetadataModel } from './types';
2
1
  export { getMediaItemImageUrl } from './media-item-url.service';
@@ -1,2 +1 @@
1
- export {} from './types';
2
1
  export { getMediaItemImageUrl } from './media-item-url.service';
@@ -1,2 +1,6 @@
1
- import { type MediaItemModel } from './types';
2
- export declare const getMediaItemImageUrl: (media: MediaItemModel) => string;
1
+ import type { MediaType } from '../enums';
2
+ export declare const getMediaItemImageUrl: (media: {
3
+ type: MediaType;
4
+ url: string;
5
+ thumbnailUrl?: string | null;
6
+ }) => string;
@@ -1,3 +1 @@
1
- import { MediaType } from '../enums';
2
- import {} from './types';
3
- export const getMediaItemImageUrl = (media) => (media.type === MediaType.Image ? media.url : media.thumbnailUrl);
1
+ export const getMediaItemImageUrl = (media) => media.type === 'IMAGE' ? media.url : (media.thumbnailUrl ?? '');
@@ -0,0 +1,98 @@
1
+ <script lang="ts">import { Article } from '../../articles/article';
2
+ import { createLocalGQLClient } from '../../core/graphql';
3
+ import { createArticleDataProvider } from '../data-providers/article/article-data-provider';
4
+ import { Loading } from '@streamscloud/kit/ui/loading';
5
+ import { untrack } from 'svelte';
6
+ let { id, slug, initiator, graphqlOrigin, theme, on } = $props();
7
+ let data = $state.raw(null);
8
+ let notFound = $state(false);
9
+ const extractCoverImageUrl = (article) => {
10
+ for (const section of article.sections) {
11
+ for (const layout of section.layouts) {
12
+ for (const field of layout.fields) {
13
+ const { fieldData } = field;
14
+ const media = fieldData.imageData?.image ?? fieldData.mediaData?.media ?? fieldData.videoData?.video ?? fieldData.mediaGalleryData?.media?.[0];
15
+ if (media) {
16
+ return media.type === 'IMAGE' ? media.url : (media.thumbnailUrl ?? null);
17
+ }
18
+ }
19
+ }
20
+ }
21
+ return null;
22
+ };
23
+ const load = async (articleId, articleSlug) => {
24
+ try {
25
+ const graphql = createLocalGQLClient(graphqlOrigin, { initiator });
26
+ const dataProvider = createArticleDataProvider(graphql);
27
+ data = await dataProvider.fetchArticle({ id: articleId, slug: articleSlug });
28
+ if (!data) {
29
+ notFound = true;
30
+ return;
31
+ }
32
+ on?.seoLoaded?.({ ...data.seo, imageUrl: extractCoverImageUrl(data) });
33
+ }
34
+ catch {
35
+ notFound = true;
36
+ }
37
+ };
38
+ $effect(() => {
39
+ const currentId = id;
40
+ const currentSlug = slug;
41
+ untrack(() => {
42
+ void load(currentId, currentSlug);
43
+ });
44
+ });
45
+ </script>
46
+
47
+ {#if notFound}
48
+ <div class="embed-article__not-found">¯\_(ツ)_/¯</div>
49
+ {:else if data}
50
+ <Article sections={data.sections} metadata={data.metadata} theme={theme} />
51
+ {:else}
52
+ <div class="embed-article__loading">
53
+ <Loading positionAbsoluteCenter timeout={600} />
54
+ </div>
55
+ {/if}
56
+
57
+ <!--
58
+ @component
59
+ Fetches and renders an article by `id` or `slug` via the `embedArticle` GraphQL query.
60
+ Displays a placeholder when the article is not found.
61
+
62
+ ### Props
63
+ | Prop | Type | Description |
64
+ |---|---|---|
65
+ | `id` | `string?` | Article ID to fetch |
66
+ | `slug` | `string?` | Article slug to fetch (alternative to `id`) |
67
+ | `initiator` | `string?` | Value for the `x-initiator` header |
68
+ | `graphqlOrigin` | `string?` | Custom GraphQL API origin |
69
+ | `theme` | `'light' \| 'dark'` | Color theme (default: `'light'`) |
70
+
71
+ ### Callbacks (`on`)
72
+ | Callback | Type | Description |
73
+ |---|---|---|
74
+ | `seoLoaded` | `(seo: ArticleSeoModel) => void` | Called after article is loaded with SEO data and cover image URL |
75
+
76
+ ### CSS Custom Properties
77
+ | Property | Description | Default |
78
+ |---|---|---|
79
+ | `--article--max-width` | Article max width (centered when constrained) | `100%` |
80
+ | `--article--container-background` | Outer container background (visible when width constrained) | `gray-50` / `gray-900` |
81
+ | `--article--background` | Article background color | `white` / `gray-800` |
82
+ | `--article--text-color` | Article text color | `black` / `white` |
83
+ | `--article--min-height` | Minimum article height | `0` |
84
+ -->
85
+
86
+ <style>.embed-article__not-found {
87
+ display: flex;
88
+ align-items: center;
89
+ justify-content: center;
90
+ min-height: 12.5rem;
91
+ font-size: 1.5rem;
92
+ color: light-dark(#9ca3af, #6b7280);
93
+ }
94
+
95
+ .embed-article__loading {
96
+ position: relative;
97
+ min-height: 12.5rem;
98
+ }</style>
@@ -0,0 +1,47 @@
1
+ import type { ThemeValue } from '../../core/theme';
2
+ export type ArticleSeoModel = {
3
+ title: string;
4
+ description: string;
5
+ keywords: string[];
6
+ imageUrl: string | null;
7
+ };
8
+ type Props = {
9
+ id?: string;
10
+ slug?: string;
11
+ initiator?: string;
12
+ graphqlOrigin?: string;
13
+ theme?: ThemeValue;
14
+ on?: {
15
+ seoLoaded?: (seo: ArticleSeoModel) => void;
16
+ };
17
+ };
18
+ /**
19
+ * Fetches and renders an article by `id` or `slug` via the `embedArticle` GraphQL query.
20
+ * Displays a placeholder when the article is not found.
21
+ *
22
+ * ### Props
23
+ * | Prop | Type | Description |
24
+ * |---|---|---|
25
+ * | `id` | `string?` | Article ID to fetch |
26
+ * | `slug` | `string?` | Article slug to fetch (alternative to `id`) |
27
+ * | `initiator` | `string?` | Value for the `x-initiator` header |
28
+ * | `graphqlOrigin` | `string?` | Custom GraphQL API origin |
29
+ * | `theme` | `'light' \| 'dark'` | Color theme (default: `'light'`) |
30
+ *
31
+ * ### Callbacks (`on`)
32
+ * | Callback | Type | Description |
33
+ * |---|---|---|
34
+ * | `seoLoaded` | `(seo: ArticleSeoModel) => void` | Called after article is loaded with SEO data and cover image URL |
35
+ *
36
+ * ### CSS Custom Properties
37
+ * | Property | Description | Default |
38
+ * |---|---|---|
39
+ * | `--article--max-width` | Article max width (centered when constrained) | `100%` |
40
+ * | `--article--container-background` | Outer container background (visible when width constrained) | `gray-50` / `gray-900` |
41
+ * | `--article--background` | Article background color | `white` / `gray-800` |
42
+ * | `--article--text-color` | Article text color | `black` / `white` |
43
+ * | `--article--min-height` | Minimum article height | `0` |
44
+ */
45
+ declare const Cmp: import("svelte").Component<Props, {}, "">;
46
+ type Cmp = ReturnType<typeof Cmp>;
47
+ export default Cmp;
@@ -0,0 +1 @@
1
+ export { default as Article, type ArticleSeoModel } from './cmp.embed-article.svelte';
@@ -0,0 +1 @@
1
+ export { default as Article } from './cmp.embed-article.svelte';
@@ -0,0 +1,4 @@
1
+ import type { ArticleDataProvider } from '../../../articles/data-providers';
2
+ import type { Client } from '@urql/core';
3
+ /** Creates an ArticleDataProvider that fetches articles via the GetEmbedArticle GraphQL query. */
4
+ export declare const createArticleDataProvider: (graphql: Client) => ArticleDataProvider;