@streamscloud/embeddable 3.4.2 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. package/dist/ads/ad-card/cmp.ad-card.svelte +220 -0
  2. package/dist/{short-videos/short-video-viewer/cmp.ad.svelte.d.ts → ads/ad-card/cmp.ad-card.svelte.d.ts} +3 -2
  3. package/dist/ads/ad-card/index.d.ts +3 -0
  4. package/dist/ads/ad-card/index.js +2 -0
  5. package/dist/ads/ad-card/mapper.d.ts +3 -0
  6. package/dist/ads/ad-card/mapper.js +14 -0
  7. package/dist/ads/ad-card/operations.generated.d.ts +24 -0
  8. package/dist/ads/ad-card/operations.generated.js +48 -0
  9. package/dist/ads/ad-card/operations.graphql +21 -0
  10. package/dist/ads/ad-card/types.d.ts +18 -0
  11. package/dist/ads/ad-card/types.js +1 -0
  12. package/dist/core/locale.d.ts +3 -0
  13. package/dist/products/price-helper.d.ts +18 -3
  14. package/dist/products/price-helper.js +9 -6
  15. package/dist/products/product-card/cmp.product-card.svelte +219 -0
  16. package/dist/products/product-card/cmp.product-card.svelte.d.ts +15 -0
  17. package/dist/products/product-card/index.d.ts +4 -0
  18. package/dist/products/product-card/index.js +2 -0
  19. package/dist/products/product-card/mapper.d.ts +3 -0
  20. package/dist/products/product-card/mapper.js +22 -0
  21. package/dist/products/product-card/operations.generated.d.ts +26 -0
  22. package/dist/products/product-card/operations.generated.js +59 -0
  23. package/dist/products/product-card/operations.graphql +23 -0
  24. package/dist/products/product-card/product-card-localization.d.ts +8 -0
  25. package/dist/{short-videos/short-video-viewer/short-video-product-localization.js → products/product-card/product-card-localization.js} +1 -1
  26. package/dist/products/product-card/types.d.ts +12 -0
  27. package/dist/products/product-card/types.js +1 -0
  28. package/dist/short-videos/short-video-viewer/cmp.attachments.svelte +12 -40
  29. package/dist/short-videos/short-video-viewer/cmp.attachments.svelte.d.ts +1 -1
  30. package/dist/short-videos/short-video-viewer/cmp.short-video-controls.svelte +145 -0
  31. package/dist/short-videos/short-video-viewer/cmp.short-video-controls.svelte.d.ts +19 -0
  32. package/dist/short-videos/short-video-viewer/cmp.short-video-viewer.svelte +46 -20
  33. package/dist/short-videos/short-video-viewer/cmp.short-video-viewer.svelte.d.ts +4 -2
  34. package/dist/short-videos/short-video-viewer/index.d.ts +3 -7
  35. package/dist/short-videos/short-video-viewer/index.js +2 -5
  36. package/dist/short-videos/short-video-viewer/mapper.d.ts +1 -1
  37. package/dist/short-videos/short-video-viewer/mapper.js +25 -22
  38. package/dist/short-videos/short-video-viewer/operations.generated.d.ts +6 -8
  39. package/dist/short-videos/short-video-viewer/operations.generated.js +10 -17
  40. package/dist/short-videos/short-video-viewer/operations.graphql +8 -10
  41. package/dist/short-videos/short-video-viewer/short-video-attachments-localization.d.ts +3 -7
  42. package/dist/short-videos/short-video-viewer/short-video-attachments-localization.js +0 -14
  43. package/dist/short-videos/short-video-viewer/short-video-viewer-localization.d.ts +3 -3
  44. package/dist/short-videos/short-video-viewer/types.d.ts +23 -13
  45. package/dist/short-videos/short-video-viewer/ui-manager.svelte.d.ts +5 -0
  46. package/dist/short-videos/short-video-viewer/ui-manager.svelte.js +15 -2
  47. package/dist/short-videos/short-videos-player/cmp.short-videos-player.svelte +25 -163
  48. package/dist/short-videos/short-videos-player/cmp.short-videos-player.svelte.d.ts +7 -2
  49. package/dist/short-videos/short-videos-player/controls.svelte +125 -125
  50. package/dist/short-videos/short-videos-player/controls.svelte.d.ts +4 -2
  51. package/dist/short-videos/short-videos-player/index.d.ts +2 -0
  52. package/dist/short-videos/short-videos-player/index.js +12 -3
  53. package/dist/short-videos/short-videos-player/operations.generated.d.ts +6 -8
  54. package/dist/short-videos/short-videos-player/operations.generated.js +10 -17
  55. package/dist/short-videos/short-videos-player/short-videos-player-localization.d.ts +1 -3
  56. package/dist/short-videos/short-videos-player/short-videos-player-localization.js +0 -2
  57. package/dist/short-videos/short-videos-player/short-videos-player-view.svelte +211 -0
  58. package/dist/short-videos/short-videos-player/short-videos-player-view.svelte.d.ts +18 -0
  59. package/dist/short-videos/short-videos-player/types.d.ts +10 -8
  60. package/dist/short-videos/short-videos-player/ui-manager.svelte.d.ts +4 -3
  61. package/dist/short-videos/short-videos-player/ui-manager.svelte.js +9 -8
  62. package/dist/streams/layout/element-views/price-element-view.svelte +5 -4
  63. package/dist/streams/layout/models/mapper.js +10 -18
  64. package/dist/streams/layout/models/stream-layout-short-video-model.d.ts +1 -0
  65. package/dist/streams/stream-player/cmp.stream-player.svelte +23 -8
  66. package/dist/streams/stream-player/cmp.stream-player.svelte.d.ts +3 -1
  67. package/dist/streams/stream-player/controls.svelte +87 -74
  68. package/dist/streams/stream-player/controls.svelte.d.ts +2 -0
  69. package/dist/streams/stream-player/index.d.ts +2 -0
  70. package/dist/streams/stream-player/index.js +4 -3
  71. package/dist/streams/stream-player/mapper.d.ts +1 -1
  72. package/dist/streams/stream-player/mapper.js +1 -1
  73. package/dist/streams/stream-player/stream-overview.svelte +12 -1
  74. package/dist/streams/stream-player/stream-overview.svelte.d.ts +1 -0
  75. package/dist/streams/stream-player/stream-player-localization.d.ts +1 -3
  76. package/dist/streams/stream-player/stream-player-localization.js +0 -2
  77. package/dist/streams/stream-player/ui-manager.svelte.d.ts +4 -2
  78. package/dist/streams/stream-player/ui-manager.svelte.js +10 -5
  79. package/dist/ui/button/resources/button-theme.svelte +1 -0
  80. package/dist/ui/line-clamp/cmp.line-clamp.svelte +35 -13
  81. package/dist/ui/player/cmp.player-slider.svelte +74 -9
  82. package/dist/ui/progress/cmp.progress.svelte +4 -1
  83. package/dist/ui/seek-bar/cmp.seek-bar.svelte +112 -28
  84. package/dist/ui/seek-bar/cmp.seek-bar.svelte.d.ts +3 -0
  85. package/dist/ui/shadow-dom/index.d.ts +2 -1
  86. package/dist/ui/shadow-dom/index.js +2 -1
  87. package/dist/ui/shadow-dom/{shadow-host.d.ts → modal-shadow-host.d.ts} +1 -1
  88. package/dist/ui/shadow-dom/modal-shadow-host.js +21 -0
  89. package/dist/ui/shadow-dom/shadow-root-service.d.ts +1 -0
  90. package/dist/ui/shadow-dom/shadow-root-service.js +23 -0
  91. package/dist/ui/video/cmp.video.svelte +46 -38
  92. package/dist/ui/video/cmp.video.svelte.d.ts +3 -0
  93. package/dist/ui/video/index.d.ts +1 -0
  94. package/dist/ui/video/index.js +1 -0
  95. package/dist/ui/video/types.d.ts +4 -0
  96. package/dist/ui/video/types.js +5 -0
  97. package/package.json +5 -1
  98. package/dist/short-videos/short-video-viewer/cmp.ad.svelte +0 -140
  99. package/dist/short-videos/short-video-viewer/cmp.product.svelte +0 -168
  100. package/dist/short-videos/short-video-viewer/cmp.product.svelte.d.ts +0 -14
  101. package/dist/short-videos/short-video-viewer/cmp.short-video-details.svelte +0 -125
  102. package/dist/short-videos/short-video-viewer/cmp.short-video-details.svelte.d.ts +0 -14
  103. package/dist/short-videos/short-video-viewer/cmp.social-interactions.svelte +0 -69
  104. package/dist/short-videos/short-video-viewer/cmp.social-interactions.svelte.d.ts +0 -10
  105. package/dist/short-videos/short-video-viewer/description.svelte +0 -53
  106. package/dist/short-videos/short-video-viewer/description.svelte.d.ts +0 -9
  107. package/dist/short-videos/short-video-viewer/short-video-details-localization.d.ts +0 -14
  108. package/dist/short-videos/short-video-viewer/short-video-details-localization.js +0 -17
  109. package/dist/short-videos/short-video-viewer/short-video-product-localization.d.ts +0 -8
  110. package/dist/short-videos/short-videos-player/action-button.svelte +0 -38
  111. package/dist/short-videos/short-videos-player/action-button.svelte.d.ts +0 -10
  112. package/dist/ui/shadow-dom/shadow-host.js +0 -32
@@ -0,0 +1,2 @@
1
+ export { default as ProductCard } from './cmp.product-card.svelte';
2
+ export { mapToProductCard } from './mapper';
@@ -0,0 +1,3 @@
1
+ import type { ProductCardPayloadFragment } from './operations.generated';
2
+ import type { ProductCardModel } from './types';
3
+ export declare const mapToProductCard: (payload: ProductCardPayloadFragment, referenceDate?: string | null) => ProductCardModel;
@@ -0,0 +1,22 @@
1
+ import { getMediaItemImageUrl } from '../../core/media';
2
+ import { shouldUseSalePrice } from '../price-helper';
3
+ export const mapToProductCard = (payload, referenceDate) => {
4
+ const effectiveSalePrice = payload.priceAndAvailability.productSalePrices?.find((x) => shouldUseSalePrice({
5
+ price: payload.priceAndAvailability.price,
6
+ salePrice: x.salePrice,
7
+ effectiveDateFrom: x.salePriceEffectiveDateFrom,
8
+ effectiveDateTo: x.salePriceEffectiveDateTo,
9
+ referenceDate
10
+ }));
11
+ return {
12
+ id: payload.id,
13
+ title: payload.title,
14
+ shortDescription: payload.shortDescription,
15
+ link: payload.link,
16
+ brandName: payload.brand?.name || null,
17
+ image: getMediaItemImageUrl(payload.media[0]),
18
+ currency: payload.priceAndAvailability.currency,
19
+ price: payload.priceAndAvailability.price,
20
+ salePrice: effectiveSalePrice?.salePrice ?? null
21
+ };
22
+ };
@@ -0,0 +1,26 @@
1
+ import type * as SchemaTypes from '../../../gql/types';
2
+ import type { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core';
3
+ export type ProductCardPayloadFragment = {
4
+ id: string;
5
+ title: string;
6
+ shortDescription: string | null;
7
+ link: string | null;
8
+ media: Array<{
9
+ url: string;
10
+ thumbnailUrl: string | null;
11
+ type: SchemaTypes.MediaType;
12
+ }>;
13
+ brand: {
14
+ name: string;
15
+ } | null;
16
+ priceAndAvailability: {
17
+ currency: SchemaTypes.Currency;
18
+ price: number;
19
+ productSalePrices: Array<{
20
+ salePrice: number;
21
+ salePriceEffectiveDateFrom: any | null;
22
+ salePriceEffectiveDateTo: any | null;
23
+ }> | null;
24
+ };
25
+ };
26
+ export declare const ProductCardPayloadFragmentDoc: DocumentNode<ProductCardPayloadFragment, unknown>;
@@ -0,0 +1,59 @@
1
+ export const ProductCardPayloadFragmentDoc = {
2
+ kind: 'Document',
3
+ definitions: [
4
+ {
5
+ kind: 'FragmentDefinition',
6
+ name: { kind: 'Name', value: 'ProductCardPayloadFragment' },
7
+ typeCondition: { kind: 'NamedType', name: { kind: 'Name', value: 'Product' } },
8
+ selectionSet: {
9
+ kind: 'SelectionSet',
10
+ selections: [
11
+ { kind: 'Field', name: { kind: 'Name', value: 'id' } },
12
+ { kind: 'Field', name: { kind: 'Name', value: 'title' } },
13
+ { kind: 'Field', name: { kind: 'Name', value: 'shortDescription' } },
14
+ { kind: 'Field', name: { kind: 'Name', value: 'link' } },
15
+ {
16
+ kind: 'Field',
17
+ name: { kind: 'Name', value: 'media' },
18
+ selectionSet: {
19
+ kind: 'SelectionSet',
20
+ selections: [
21
+ { kind: 'Field', name: { kind: 'Name', value: 'url' } },
22
+ { kind: 'Field', name: { kind: 'Name', value: 'thumbnailUrl' } },
23
+ { kind: 'Field', name: { kind: 'Name', value: 'type' } }
24
+ ]
25
+ }
26
+ },
27
+ {
28
+ kind: 'Field',
29
+ name: { kind: 'Name', value: 'brand' },
30
+ selectionSet: { kind: 'SelectionSet', selections: [{ kind: 'Field', name: { kind: 'Name', value: 'name' } }] }
31
+ },
32
+ {
33
+ kind: 'Field',
34
+ name: { kind: 'Name', value: 'priceAndAvailability' },
35
+ selectionSet: {
36
+ kind: 'SelectionSet',
37
+ selections: [
38
+ { kind: 'Field', name: { kind: 'Name', value: 'currency' } },
39
+ { kind: 'Field', name: { kind: 'Name', value: 'price' } },
40
+ {
41
+ kind: 'Field',
42
+ name: { kind: 'Name', value: 'productSalePrices' },
43
+ selectionSet: {
44
+ kind: 'SelectionSet',
45
+ selections: [
46
+ { kind: 'Field', name: { kind: 'Name', value: 'salePrice' } },
47
+ { kind: 'Field', name: { kind: 'Name', value: 'salePriceEffectiveDateFrom' } },
48
+ { kind: 'Field', name: { kind: 'Name', value: 'salePriceEffectiveDateTo' } }
49
+ ]
50
+ }
51
+ }
52
+ ]
53
+ }
54
+ }
55
+ ]
56
+ }
57
+ }
58
+ ]
59
+ };
@@ -0,0 +1,23 @@
1
+ fragment ProductCardPayloadFragment on Product {
2
+ id
3
+ title
4
+ shortDescription
5
+ link
6
+ media {
7
+ url
8
+ thumbnailUrl
9
+ type
10
+ }
11
+ brand {
12
+ name
13
+ }
14
+ priceAndAvailability {
15
+ currency
16
+ price
17
+ productSalePrices {
18
+ salePrice
19
+ salePriceEffectiveDateFrom
20
+ salePriceEffectiveDateTo
21
+ }
22
+ }
23
+ }
@@ -0,0 +1,8 @@
1
+ import { type Locale } from '../../core/locale';
2
+ export interface IProductCardLocalization {
3
+ beforeNowPrefix?: string | null;
4
+ }
5
+ export declare class ProductCardLocalization {
6
+ beforeNowPrefix: string | null;
7
+ constructor(init: IProductCardLocalization | Locale);
8
+ }
@@ -1,5 +1,5 @@
1
1
  import { isLocale } from '../../core/locale';
2
- export class ShortVideoProductLocalization {
2
+ export class ProductCardLocalization {
3
3
  beforeNowPrefix;
4
4
  constructor(init) {
5
5
  this.beforeNowPrefix = isLocale(init) ? loc.beforeNowPrefix[init] : init?.beforeNowPrefix || loc.beforeNowPrefix.en;
@@ -0,0 +1,12 @@
1
+ import type { Currency } from '../..';
2
+ export type ProductCardModel = {
3
+ id: string;
4
+ title: string;
5
+ shortDescription?: string | null;
6
+ link: string | null;
7
+ image: string | null;
8
+ brandName: string | null;
9
+ price: number;
10
+ currency: Currency;
11
+ salePrice: number | null;
12
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -1,27 +1,21 @@
1
- <script lang="ts">import { default as ShortVideoAdViewer } from './cmp.ad.svelte';
2
- import { default as ShortVideoProductViewer } from './cmp.product.svelte';
1
+ <script lang="ts">import { AdCard } from '../../ads/ad-card';
2
+ import { ProductCard } from '../../products/product-card';
3
3
  import { ShortVideoAttachmentsLocalization } from './short-video-attachments-localization';
4
4
  import {} from './types';
5
- let { shortVideo, localization: localizationInit, on } = $props();
5
+ let { shortVideo, localization: localizationInit = 'en', on } = $props();
6
6
  const localization = $derived(new ShortVideoAttachmentsLocalization(localizationInit));
7
7
  </script>
8
8
 
9
9
  {#if shortVideo.products.length || shortVideo.ad}
10
10
  <div class="short-video-attachments">
11
- {#if shortVideo.products.length}
12
- <div class="short-video-attachments__section-header">{localization.productsSection}</div>
13
- <div class="short-video-attachments__products">
14
- {#each shortVideo.products as product (product.id)}
15
- <ShortVideoProductViewer product={product} localization={localization.productLocalization} on={on} />
16
- {/each}
17
- </div>
11
+ {#if shortVideo.ad}
12
+ <AdCard ad={shortVideo.ad} />
18
13
  {/if}
19
14
 
20
- {#if shortVideo.ad}
21
- <div class="short-video-attachments__section-header">{localization.offersSection}</div>
22
- <div class="short-video-attachments__offer">
23
- <ShortVideoAdViewer ad={shortVideo.ad} />
24
- </div>
15
+ {#if shortVideo.products.length}
16
+ {#each shortVideo.products as product (product.id)}
17
+ <ProductCard product={product} localization={localization.productLocalization} on={on} />
18
+ {/each}
25
19
  {/if}
26
20
  </div>
27
21
  {/if}
@@ -38,31 +32,9 @@ const localization = $derived(new ShortVideoAttachmentsLocalization(localization
38
32
  }
39
33
  }
40
34
  .short-video-attachments {
41
- --_short-video-attachments--margin-vertical: var(--short-video-attachments--margin-vertical, 0);
42
- --_short-video-attachments--spacing-vertical: var(--short-video-attachments--spacing-vertical, 1.25rem);
43
- --_short-video-attachments--spacing-horizontal: var(--short-video-attachments--spacing-horizontal, 1rem);
35
+ --_short-video-attachments--gap: var(--short-video-attachments--gap, 2.75rem);
44
36
  display: flex;
45
37
  flex-direction: column;
46
- gap: var(--_short-video-attachments--spacing-vertical);
47
- padding: var(--_short-video-attachments--margin-vertical) 0;
48
- }
49
- .short-video-attachments__section-header {
50
- color: #d1d5db;
51
- font-size: 1rem;
52
- font-weight: 700;
53
- line-height: 1.2;
54
- display: flex;
55
- justify-content: space-between;
56
- margin-bottom: 0.5rem;
57
- padding: 0.5625rem var(--_short-video-attachments--spacing-horizontal) 0;
58
- }
59
- .short-video-attachments__products {
60
- padding: 0 var(--_short-video-attachments--spacing-horizontal);
61
- display: grid;
62
- grid-template-columns: repeat(2, minmax(0, 1fr));
63
- grid-column-gap: var(--_short-video-attachments--spacing-horizontal);
64
- grid-row-gap: var(--_short-video-attachments--spacing-vertical);
65
- }
66
- .short-video-attachments__offer {
67
- padding: 0 var(--_short-video-attachments--spacing-horizontal);
38
+ gap: var(--_short-video-attachments--gap);
39
+ padding: 0;
68
40
  }</style>
@@ -3,7 +3,7 @@ import { type IShortVideoAttachmentsLocalization } from './short-video-attachmen
3
3
  import { type ShortVideoViewerModel } from './types';
4
4
  type Props = {
5
5
  shortVideo: ShortVideoViewerModel;
6
- localization: IShortVideoAttachmentsLocalization | Locale;
6
+ localization?: IShortVideoAttachmentsLocalization | Locale;
7
7
  on?: {
8
8
  productClick?: (productId: string) => void;
9
9
  };
@@ -0,0 +1,145 @@
1
+ <script lang="ts">var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { Icon } from '../../ui/icon';
11
+ import { MediaVolumeManager } from '../../ui/media-playback';
12
+ import IconHeartFilled from '@fluentui/svg-icons/icons/heart_20_filled.svg?raw';
13
+ import IconHeart from '@fluentui/svg-icons/icons/heart_28_regular.svg?raw';
14
+ import IconShare from '@fluentui/svg-icons/icons/share_28_regular.svg?raw';
15
+ import IconShoppingBag from '@fluentui/svg-icons/icons/shopping_bag_28_regular.svg?raw';
16
+ import IconSpeaker2 from '@fluentui/svg-icons/icons/speaker_2_28_regular.svg?raw';
17
+ import IconSpeakerMute from '@fluentui/svg-icons/icons/speaker_mute_28_regular.svg?raw';
18
+ let { model, socialInteractionsHandler, on } = $props();
19
+ const showSocialInteractions = $derived(!!socialInteractionsHandler && model.enableSocialInteractions);
20
+ let isLikedStore = $state.raw({
21
+ get isLiked() {
22
+ return false;
23
+ }
24
+ });
25
+ const availableActionsCount = $derived.by(() => {
26
+ let actionsCount = 0;
27
+ if (model.products.length || model.ad) {
28
+ actionsCount++;
29
+ }
30
+ if (showSocialInteractions) {
31
+ actionsCount++;
32
+ }
33
+ if (!model.media.isImage) {
34
+ actionsCount++;
35
+ }
36
+ return actionsCount;
37
+ });
38
+ $effect(() => {
39
+ refreshIsLiked();
40
+ });
41
+ const onAttachmentsClicked = () => {
42
+ var _a;
43
+ (_a = on === null || on === void 0 ? void 0 : on.attachmentsClicked) === null || _a === void 0 ? void 0 : _a.call(on);
44
+ };
45
+ const onMuteClicked = () => {
46
+ MediaVolumeManager.isMuted = !MediaVolumeManager.isMuted;
47
+ };
48
+ const onLikeClicked = () => __awaiter(void 0, void 0, void 0, function* () {
49
+ if (!socialInteractionsHandler) {
50
+ return;
51
+ }
52
+ yield socialInteractionsHandler.onToggleLike(model.id);
53
+ });
54
+ const onShareClicked = () => __awaiter(void 0, void 0, void 0, function* () {
55
+ if (!socialInteractionsHandler) {
56
+ return;
57
+ }
58
+ yield socialInteractionsHandler.onShare(model.id);
59
+ });
60
+ const refreshIsLiked = () => __awaiter(void 0, void 0, void 0, function* () {
61
+ if (!socialInteractionsHandler) {
62
+ return;
63
+ }
64
+ isLikedStore = yield socialInteractionsHandler.isLiked(model.id);
65
+ });
66
+ </script>
67
+
68
+ {#if availableActionsCount}
69
+ <div class="short-video-controls" class:short-video-controls--single-action={availableActionsCount === 1}>
70
+ {#if model.products.length || model.ad}
71
+ <button type="button" class="short-video-controls__action" onclick={onAttachmentsClicked}>
72
+ <Icon src={IconShoppingBag} />
73
+ </button>
74
+ {/if}
75
+
76
+ {#if showSocialInteractions}
77
+ <button
78
+ type="button"
79
+ class="short-video-controls__action"
80
+ onclick={onLikeClicked}
81
+ aria-label="none"
82
+ class:short-video-controls__action--liked={isLikedStore.isLiked}>
83
+ <Icon src={isLikedStore.isLiked ? IconHeartFilled : IconHeart} />
84
+ </button>
85
+
86
+ <button type="button" class="short-video-controls__action" onclick={onShareClicked}>
87
+ <Icon src={IconShare} />
88
+ </button>
89
+ {/if}
90
+
91
+ {#if !model.media.isImage}
92
+ <button type="button" class="short-video-controls__action" onclick={onMuteClicked}>
93
+ {#if MediaVolumeManager.isMuted}
94
+ <Icon src={IconSpeakerMute} />
95
+ {:else}
96
+ <Icon src={IconSpeaker2} />
97
+ {/if}
98
+ </button>
99
+ {/if}
100
+ </div>
101
+ {/if}
102
+
103
+ <style>@keyframes fadeIn {
104
+ 0% {
105
+ opacity: 1;
106
+ }
107
+ 50% {
108
+ opacity: 0.4;
109
+ }
110
+ 100% {
111
+ opacity: 1;
112
+ }
113
+ }
114
+ .short-video-controls {
115
+ --_short-video-controls--icon--size: var(--short-video-controls--icon--size, 1.75rem);
116
+ --_short-video-controls--padding-vertical: 1rem;
117
+ --_short-video-controls--padding-horizontal: 0.625rem;
118
+ cursor: pointer;
119
+ display: flex;
120
+ flex-direction: column;
121
+ justify-content: center;
122
+ gap: 1.125rem;
123
+ border-radius: 1.25rem;
124
+ border: 0.0625rem solid #1c1c1c;
125
+ background: rgba(0, 0, 0, 0.6);
126
+ padding: var(--_short-video-controls--padding-vertical) var(--_short-video-controls--padding-horizontal);
127
+ }
128
+ .short-video-controls--single-action {
129
+ padding: var(--_short-video-controls--padding-horizontal);
130
+ border-radius: calc((var(--_short-video-controls--padding-horizontal) * 2 + var(--_short-video-controls--icon--size)) / 2);
131
+ }
132
+ .short-video-controls__action {
133
+ --icon--size: var(--_short-video-controls--icon--size);
134
+ --icon--color: #ffffff;
135
+ display: flex;
136
+ justify-content: center;
137
+ align-items: center;
138
+ }
139
+ .short-video-controls__action--liked {
140
+ --icon--color: #e71d36;
141
+ }
142
+ .short-video-controls__action:hover {
143
+ transform: scale(1.2);
144
+ transition: 0.3s;
145
+ }</style>
@@ -0,0 +1,19 @@
1
+ import type { ShortVideoSocialInteractionsHanlder } from './types';
2
+ type Props = {
3
+ model: {
4
+ id: string;
5
+ enableSocialInteractions: boolean;
6
+ products: unknown[];
7
+ ad: unknown | null;
8
+ media: {
9
+ isImage: boolean;
10
+ };
11
+ };
12
+ socialInteractionsHandler?: ShortVideoSocialInteractionsHanlder;
13
+ on?: {
14
+ attachmentsClicked?: () => void;
15
+ };
16
+ };
17
+ declare const Cmp: import("svelte").Component<Props, {}, "">;
18
+ type Cmp = ReturnType<typeof Cmp>;
19
+ export default Cmp;
@@ -1,10 +1,12 @@
1
1
  <script lang="ts">import { Image } from '../../ui/image';
2
+ import { LineClamp } from '../../ui/line-clamp';
2
3
  import { Video } from '../../ui/video';
3
4
  import { default as AttachmentsInline } from './cmp.attachments-inline.svelte';
4
- import { default as ShortVideoDescription } from './description.svelte';
5
+ import { default as ShortVideoControls } from './cmp.short-video-controls.svelte';
6
+ import { default as ShortVideoHeading } from './cmp.short-video-heading.svelte';
5
7
  import { ShortVideoViewerLocalization } from './short-video-viewer-localization';
6
8
  import { ShortVideoViewerUiManager } from './ui-manager.svelte';
7
- let { model, availableSideSpace = 0, showAttachments = true, autoplay = 'on-appearance', localization: localizationInit, on } = $props();
9
+ let { model, socialInteractionsHandler, availableSideSpace = 0, showAttachments = true, showControls = true, autoplay = 'on-appearance', localization: localizationInit = 'en', on } = $props();
8
10
  const localization = $derived(new ShortVideoViewerLocalization(localizationInit));
9
11
  let actionsPanelRef = $state.raw(null);
10
12
  const uiManager = new ShortVideoViewerUiManager();
@@ -26,13 +28,24 @@ $effect(() => {
26
28
  });
27
29
  $effect(() => {
28
30
  uiManager.updateCanShowAttachments(showAttachments);
31
+ uiManager.updateCanShowControls(showControls);
29
32
  });
30
33
  </script>
31
34
 
32
35
  <div class="short-video-viewer" style={uiManager.globalCssVariables}>
33
36
  <div class="short-video-viewer__media">
34
37
  {#if !model.media.isImage}
35
- <Video controls={false} autoplay={autoplay} src={model.media.url} loop={true} poster={model.media.thumbnailUrl} id={model.id} on={on} />
38
+ <Video
39
+ src={model.media.url}
40
+ poster={model.media.thumbnailUrl}
41
+ controls={false}
42
+ autoplay={autoplay}
43
+ loop={true}
44
+ id={model.id}
45
+ hideSpeaker={true}
46
+ on={{
47
+ progress: on?.progress
48
+ }} />
36
49
  {:else}
37
50
  <Image src={model.media.url} />
38
51
  {/if}
@@ -45,9 +58,21 @@ $effect(() => {
45
58
  {#if uiManager.showAttachments}
46
59
  <AttachmentsInline model={model} />
47
60
  {/if}
61
+ {#if uiManager.showControls}
62
+ <ShortVideoControls model={model} socialInteractionsHandler={socialInteractionsHandler} on={{ attachmentsClicked: uiManager.toggleEnableAttachments }} />
63
+ {/if}
48
64
  </div>
49
65
  <div class="short-video-viewer__description">
50
- <ShortVideoDescription model={model} localization={localization} />
66
+ {#if model.heading}
67
+ <div class="short-video-viewer__heading">
68
+ <ShortVideoHeading model={model.heading} localization={localization} />
69
+ </div>
70
+ {/if}
71
+ <div class="short-video-viewer__text">
72
+ {#if model.text}
73
+ <LineClamp value={model.text} maxLines={2} enableShowMore={true} />
74
+ {/if}
75
+ </div>
51
76
  </div>
52
77
  </div>
53
78
 
@@ -65,8 +90,6 @@ $effect(() => {
65
90
  .short-video-viewer {
66
91
  --_short-video-viewer--actions-panel--top: var(--short-video-viewer--actions-panel--top, 0.9375rem);
67
92
  --_short-video-viewer--actions-panel--bottom: var(--short-video-viewer--actions-panel--bottom, 0.9375rem);
68
- --_short-video-viewer--button--background-color: #f3f4f6;
69
- --_short-video-viewer--button--font-color: #2e2e2e;
70
93
  --video--media-fit: cover;
71
94
  width: 100%;
72
95
  min-width: 100%;
@@ -75,13 +98,6 @@ $effect(() => {
75
98
  min-height: 100%;
76
99
  max-height: 100%;
77
100
  position: relative;
78
- /* Set 'container-type: inline-size;' to reference container*/
79
- }
80
- @container (width < 576px) {
81
- .short-video-viewer {
82
- --_short-video-viewer--button--background-color: #ffffff;
83
- --_short-video-viewer--button--font-color: #2e2e2e;
84
- }
85
101
  }
86
102
  .short-video-viewer__media {
87
103
  height: 100%;
@@ -122,12 +138,22 @@ $effect(() => {
122
138
  }
123
139
  .short-video-viewer__description {
124
140
  position: absolute;
125
- bottom: 0.9375rem;
126
- left: 0.625rem;
127
- right: calc(1.25rem + var(--_short-video-viewer--button--size));
128
- --short-video-viewer--description--font--primary-color: #ffffff;
129
- --short-video-viewer--description--font--secondary-color: #ffffff;
141
+ bottom: 0;
142
+ left: 0;
143
+ right: 0;
144
+ padding: 1.875rem 1.25rem;
145
+ padding-right: calc(1.25rem + var(--_short-video-viewer--button--size));
146
+ background: linear-gradient(0deg, #000 0%, rgba(0, 0, 0, 0) 100%);
147
+ border-radius: 0rem 0.375rem 0.375rem;
148
+ }
149
+ .short-video-viewer__heading {
150
+ --short-video-heading--padding: 0 0 0.875rem 0;
151
+ --short-video-heading--text--color: #ffffff;
152
+ --short-video-heading--meta--color: #ffffff;
130
153
  }
131
- :global([data-theme="dark"]) .short-video-viewer__description {
132
- --short-video-viewer--description--font--primary-color: #ffffff;
154
+ .short-video-viewer__text {
155
+ color: #ffffff;
156
+ font-size: 1.125rem;
157
+ font-weight: 400;
158
+ text-shadow: 0 1px 0 rgba(0, 0, 0, 0.1), 0 1px 3px rgba(0, 0, 0, 0.1), 0 1px 6px rgba(0, 0, 0, 0.05);
133
159
  }</style>
@@ -1,12 +1,14 @@
1
1
  import type { Locale } from '../../core/locale';
2
2
  import { type IShortVideoViewerLocalization } from './short-video-viewer-localization';
3
- import type { ShortVideoViewerModel } from './types';
3
+ import type { ShortVideoSocialInteractionsHanlder, ShortVideoViewerModel } from './types';
4
4
  type Props = {
5
5
  model: ShortVideoViewerModel;
6
+ socialInteractionsHandler?: ShortVideoSocialInteractionsHanlder;
6
7
  availableSideSpace?: number;
7
8
  showAttachments?: boolean;
9
+ showControls?: boolean;
8
10
  autoplay?: true | false | 'on-appearance';
9
- localization: IShortVideoViewerLocalization | Locale;
11
+ localization?: IShortVideoViewerLocalization | Locale;
10
12
  on?: {
11
13
  progress?: (progress: number) => void;
12
14
  };
@@ -1,12 +1,8 @@
1
1
  export { default as ShortVideoViewer } from './cmp.short-video-viewer.svelte';
2
- export { default as ShortVideoAdViewer } from './cmp.ad.svelte';
3
- export { default as ShortVideoProductViewer } from './cmp.product.svelte';
4
- export { default as ShortVideoSocialInteractions } from './cmp.social-interactions.svelte';
2
+ export { default as ShortVideoControls } from './cmp.short-video-controls.svelte';
5
3
  export { default as ShortVideoViewerAttachments } from './cmp.attachments.svelte';
6
4
  export { default as ShortVideoViewerAttachmentsInline } from './cmp.attachments-inline.svelte';
7
- export { default as ShortVideoDetails } from './cmp.short-video-details.svelte';
8
- export type { ShortVideoViewerModel, ShortVideoViewerAdModel, ShortVideoViewerProductModel } from './types';
5
+ export type { ShortVideoViewerModel, ShortVideoSocialInteractionsHanlder, ShortVideoAdCardModel, ShortVideoProductCardModel } from './types';
9
6
  export type { IShortVideoViewerLocalization } from './short-video-viewer-localization';
10
- export type { IShortVideoDetailsLocalization } from './short-video-details-localization';
11
7
  export type { IShortVideoAttachmentsLocalization } from './short-video-attachments-localization';
12
- export { mapShortVideoViewerModel } from './mapper';
8
+ export { mapToShortVideoViewerModel } from './mapper';
@@ -1,8 +1,5 @@
1
1
  export { default as ShortVideoViewer } from './cmp.short-video-viewer.svelte';
2
- export { default as ShortVideoAdViewer } from './cmp.ad.svelte';
3
- export { default as ShortVideoProductViewer } from './cmp.product.svelte';
4
- export { default as ShortVideoSocialInteractions } from './cmp.social-interactions.svelte';
2
+ export { default as ShortVideoControls } from './cmp.short-video-controls.svelte';
5
3
  export { default as ShortVideoViewerAttachments } from './cmp.attachments.svelte';
6
4
  export { default as ShortVideoViewerAttachmentsInline } from './cmp.attachments-inline.svelte';
7
- export { default as ShortVideoDetails } from './cmp.short-video-details.svelte';
8
- export { mapShortVideoViewerModel } from './mapper';
5
+ export { mapToShortVideoViewerModel } from './mapper';
@@ -1,3 +1,3 @@
1
1
  import type { ShortVideoViewerPayloadFragment } from './operations.generated';
2
2
  import type { ShortVideoViewerModel } from './types';
3
- export declare const mapShortVideoViewerModel: (payload: ShortVideoViewerPayloadFragment) => ShortVideoViewerModel;
3
+ export declare const mapToShortVideoViewerModel: (payload: ShortVideoViewerPayloadFragment) => ShortVideoViewerModel;