@streamscloud/embeddable 3.4.2 → 4.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 (98) hide show
  1. package/dist/ads/ad-card/cmp.ad-card.svelte +193 -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 +13 -0
  7. package/dist/ads/ad-card/operations.generated.d.ts +23 -0
  8. package/dist/ads/ad-card/operations.generated.js +47 -0
  9. package/dist/ads/ad-card/operations.graphql +20 -0
  10. package/dist/ads/ad-card/types.d.ts +17 -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 +218 -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 +134 -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 +45 -20
  33. package/dist/short-videos/short-video-viewer/cmp.short-video-viewer.svelte.d.ts +1 -0
  34. package/dist/short-videos/short-video-viewer/index.d.ts +2 -6
  35. package/dist/short-videos/short-video-viewer/index.js +1 -4
  36. package/dist/short-videos/short-video-viewer/mapper.js +12 -42
  37. package/dist/short-videos/short-video-viewer/operations.generated.d.ts +5 -8
  38. package/dist/short-videos/short-video-viewer/operations.generated.js +98 -94
  39. package/dist/short-videos/short-video-viewer/operations.graphql +2 -42
  40. package/dist/short-videos/short-video-viewer/short-video-attachments-localization.d.ts +3 -7
  41. package/dist/short-videos/short-video-viewer/short-video-attachments-localization.js +0 -14
  42. package/dist/short-videos/short-video-viewer/short-video-viewer-localization.d.ts +3 -3
  43. package/dist/short-videos/short-video-viewer/types.d.ts +9 -28
  44. package/dist/short-videos/short-video-viewer/types.js +1 -1
  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 +14 -1
  47. package/dist/short-videos/short-videos-player/cmp.short-videos-player.svelte +23 -163
  48. package/dist/short-videos/short-videos-player/cmp.short-videos-player.svelte.d.ts +3 -2
  49. package/dist/short-videos/short-videos-player/controls.svelte +110 -127
  50. package/dist/short-videos/short-videos-player/controls.svelte.d.ts +2 -1
  51. package/dist/short-videos/short-videos-player/index.d.ts +2 -0
  52. package/dist/short-videos/short-videos-player/index.js +6 -3
  53. package/dist/short-videos/short-videos-player/operations.generated.d.ts +5 -8
  54. package/dist/short-videos/short-videos-player/operations.generated.js +77 -73
  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 +198 -0
  58. package/dist/short-videos/short-videos-player/short-videos-player-view.svelte.d.ts +14 -0
  59. package/dist/short-videos/short-videos-player/types.d.ts +2 -0
  60. package/dist/short-videos/short-videos-player/ui-manager.svelte.d.ts +3 -3
  61. package/dist/short-videos/short-videos-player/ui-manager.svelte.js +8 -8
  62. package/dist/streams/layout/element-views/price-element-view.svelte +5 -4
  63. package/dist/streams/layout/models/mapper.js +8 -17
  64. package/dist/streams/stream-player/cmp.stream-player.svelte +18 -5
  65. package/dist/streams/stream-player/cmp.stream-player.svelte.d.ts +1 -1
  66. package/dist/streams/stream-player/controls.svelte +66 -73
  67. package/dist/streams/stream-player/index.js +2 -2
  68. package/dist/streams/stream-player/stream-overview.svelte +12 -1
  69. package/dist/streams/stream-player/stream-overview.svelte.d.ts +1 -0
  70. package/dist/streams/stream-player/stream-player-localization.d.ts +1 -3
  71. package/dist/streams/stream-player/stream-player-localization.js +0 -2
  72. package/dist/streams/stream-player/ui-manager.svelte.d.ts +3 -2
  73. package/dist/streams/stream-player/ui-manager.svelte.js +9 -5
  74. package/dist/ui/button/resources/button-theme.svelte +1 -0
  75. package/dist/ui/shadow-dom/index.d.ts +2 -1
  76. package/dist/ui/shadow-dom/index.js +2 -1
  77. package/dist/ui/shadow-dom/{shadow-host.d.ts → modal-shadow-host.d.ts} +1 -1
  78. package/dist/ui/shadow-dom/modal-shadow-host.js +21 -0
  79. package/dist/ui/shadow-dom/shadow-root-service.d.ts +1 -0
  80. package/dist/ui/shadow-dom/shadow-root-service.js +23 -0
  81. package/dist/ui/video/cmp.video.svelte +2 -2
  82. package/dist/ui/video/cmp.video.svelte.d.ts +1 -0
  83. package/package.json +1 -1
  84. package/dist/short-videos/short-video-viewer/cmp.ad.svelte +0 -140
  85. package/dist/short-videos/short-video-viewer/cmp.product.svelte +0 -168
  86. package/dist/short-videos/short-video-viewer/cmp.product.svelte.d.ts +0 -14
  87. package/dist/short-videos/short-video-viewer/cmp.short-video-details.svelte +0 -125
  88. package/dist/short-videos/short-video-viewer/cmp.short-video-details.svelte.d.ts +0 -14
  89. package/dist/short-videos/short-video-viewer/cmp.social-interactions.svelte +0 -69
  90. package/dist/short-videos/short-video-viewer/cmp.social-interactions.svelte.d.ts +0 -10
  91. package/dist/short-videos/short-video-viewer/description.svelte +0 -53
  92. package/dist/short-videos/short-video-viewer/description.svelte.d.ts +0 -9
  93. package/dist/short-videos/short-video-viewer/short-video-details-localization.d.ts +0 -14
  94. package/dist/short-videos/short-video-viewer/short-video-details-localization.js +0 -17
  95. package/dist/short-videos/short-video-viewer/short-video-product-localization.d.ts +0 -8
  96. package/dist/short-videos/short-videos-player/action-button.svelte +0 -38
  97. package/dist/short-videos/short-videos-player/action-button.svelte.d.ts +0 -10
  98. package/dist/ui/shadow-dom/shadow-host.js +0 -32
@@ -1,5 +1,5 @@
1
1
  import { type Locale } from '../../core/locale';
2
- import type { IShortVideoAttachmentsLocalization, IShortVideoDetailsLocalization, IShortVideoViewerLocalization } from '../../short-videos/short-video-viewer';
2
+ import type { IShortVideoAttachmentsLocalization, IShortVideoViewerLocalization } from '../../short-videos/short-video-viewer';
3
3
  import type { IStreamPageViewerLocalization } from '../stream-page-viewer';
4
4
  import type { ISwipeIndicatorLocalization } from '../../ui/swipe-indicator';
5
5
  import type { ITimeAgoLocalization } from '../../ui/time-ago';
@@ -9,7 +9,6 @@ export interface IStreamPlayerLocalization {
9
9
  timeAgoLocalization?: ITimeAgoLocalization | Locale;
10
10
  streamPageViewerLocalization?: IStreamPageViewerLocalization | Locale;
11
11
  shortVideoAttachmentsLocalization?: IShortVideoAttachmentsLocalization | Locale;
12
- shortVideoDetailsLocalization?: IShortVideoDetailsLocalization | Locale;
13
12
  shortVideoViewerLocalization?: IShortVideoViewerLocalization | Locale;
14
13
  swipeIndicatorLocalization?: ISwipeIndicatorLocalization | Locale;
15
14
  }
@@ -19,7 +18,6 @@ export declare class StreamPlayerLocalization {
19
18
  timeAgoLocalization: ITimeAgoLocalization | Locale;
20
19
  streamPageViewerLocalization: IStreamPageViewerLocalization | Locale;
21
20
  shortVideoAttachmentsLocalization: IShortVideoAttachmentsLocalization | Locale;
22
- shortVideoDetailsLocalization: IShortVideoDetailsLocalization | Locale;
23
21
  shortVideoViewerLocalization: IShortVideoViewerLocalization | Locale;
24
22
  swipeIndicatorLocalization: ISwipeIndicatorLocalization | Locale;
25
23
  constructor(init: IStreamPlayerLocalization | Locale);
@@ -5,7 +5,6 @@ export class StreamPlayerLocalization {
5
5
  timeAgoLocalization;
6
6
  streamPageViewerLocalization;
7
7
  shortVideoAttachmentsLocalization;
8
- shortVideoDetailsLocalization;
9
8
  shortVideoViewerLocalization;
10
9
  swipeIndicatorLocalization;
11
10
  constructor(init) {
@@ -14,7 +13,6 @@ export class StreamPlayerLocalization {
14
13
  this.timeAgoLocalization = isLocale(init) ? init : init.timeAgoLocalization || 'en';
15
14
  this.streamPageViewerLocalization = isLocale(init) ? init : init.streamPageViewerLocalization || 'en';
16
15
  this.shortVideoAttachmentsLocalization = isLocale(init) ? init : init.shortVideoAttachmentsLocalization || 'en';
17
- this.shortVideoDetailsLocalization = isLocale(init) ? init : init.shortVideoDetailsLocalization || 'en';
18
16
  this.shortVideoViewerLocalization = isLocale(init) ? init : init.shortVideoViewerLocalization || 'en';
19
17
  this.swipeIndicatorLocalization = isLocale(init) ? init : init.swipeIndicatorLocalization || 'en';
20
18
  }
@@ -1,18 +1,19 @@
1
1
  export declare class StreamPlayerUiManager {
2
2
  overviewCollapsed: boolean;
3
- shortVideoDetailsCollapsed: boolean;
4
3
  showShortVideoAttachments: boolean;
5
4
  globalCssVariables: string;
6
5
  isMobileView: boolean;
7
6
  showShortVideoOverlay: boolean;
8
7
  private readonly buttonSize;
8
+ private readonly iconSize;
9
9
  private readonly controlsOffsetHorizontal;
10
10
  private readonly controlsOffsetVertical;
11
- private readonly iconSize;
12
11
  private viewTotalWidth;
13
12
  private mainViewColumnWidth;
13
+ private overviewWidth;
14
14
  updateDimensions: (dimensions: {
15
15
  viewTotalWidth: number;
16
16
  mainViewColumnWidth: number;
17
17
  }) => void;
18
+ updateOverviewWidth: (width: number) => void;
18
19
  }
@@ -1,27 +1,31 @@
1
1
  export class StreamPlayerUiManager {
2
2
  overviewCollapsed = $state(false);
3
- shortVideoDetailsCollapsed = $state(true);
4
3
  showShortVideoAttachments = $state(true);
5
4
  globalCssVariables = $derived.by(() => {
6
5
  const values = [
7
6
  `--stream-player--button--size: ${this.buttonSize}px`,
7
+ `--stream-player--icon--size: ${this.iconSize}px`,
8
8
  `--stream-player--controls--offset-horizontal: ${this.controlsOffsetHorizontal}px`,
9
9
  `--stream-player--controls--offset-vertical: ${this.controlsOffsetVertical}px`,
10
- `--stream-player--sidebar--available-space: ${(this.viewTotalWidth - this.mainViewColumnWidth) / 2}px`,
11
- `--stream-player--icon--size: ${this.iconSize}px`
10
+ `--stream-player--overview--width: ${this.overviewWidth}px`,
11
+ `--stream-player--sidebar--available-space: ${(this.viewTotalWidth - this.mainViewColumnWidth) / 2}px`
12
12
  ];
13
13
  return values.join(';');
14
14
  });
15
15
  isMobileView = $derived.by(() => this.viewTotalWidth <= 576);
16
- showShortVideoOverlay = $derived.by(() => (this.viewTotalWidth - this.mainViewColumnWidth) / 2 <= 70);
16
+ showShortVideoOverlay = $derived.by(() => (this.viewTotalWidth - this.mainViewColumnWidth) / 2 <= 85);
17
17
  buttonSize = 48;
18
+ iconSize = 28;
18
19
  controlsOffsetHorizontal = 28;
19
20
  controlsOffsetVertical = 28;
20
- iconSize = 28;
21
21
  viewTotalWidth = $state(0);
22
22
  mainViewColumnWidth = $state(0);
23
+ overviewWidth = $state(0);
23
24
  updateDimensions = (dimensions) => {
24
25
  this.viewTotalWidth = dimensions.viewTotalWidth;
25
26
  this.mainViewColumnWidth = dimensions.mainViewColumnWidth;
26
27
  };
28
+ updateOverviewWidth = (width) => {
29
+ this.overviewWidth = width;
30
+ };
27
31
  }
@@ -36,6 +36,7 @@ let { style = undefined, size = ButtonSize.Standard, children } = $props();
36
36
  }
37
37
  }
38
38
  .button-theme {
39
+ display: contents;
39
40
  /*Style*/
40
41
  /*Size*/
41
42
  }
@@ -1 +1,2 @@
1
- export { ShadowHost } from './shadow-host';
1
+ export { ModalShadowHost } from './modal-shadow-host';
2
+ export { createShadowRoot } from './shadow-root-service';
@@ -1 +1,2 @@
1
- export { ShadowHost } from './shadow-host';
1
+ export { ModalShadowHost } from './modal-shadow-host';
2
+ export { createShadowRoot } from './shadow-root-service';
@@ -1,4 +1,4 @@
1
- export declare class ShadowHost {
1
+ export declare class ModalShadowHost {
2
2
  shadowRoot: ShadowRoot;
3
3
  private host;
4
4
  constructor();
@@ -0,0 +1,21 @@
1
+ import { createShadowRoot } from './shadow-root-service';
2
+ export class ModalShadowHost {
3
+ shadowRoot;
4
+ host;
5
+ constructor() {
6
+ const host = document.createElement('div');
7
+ this.host = host;
8
+ this.shadowRoot = createShadowRoot(host);
9
+ host.style.position = 'fixed';
10
+ host.style.inset = '0';
11
+ host.style.zIndex = '9999';
12
+ }
13
+ attachToBody() {
14
+ document.getElementsByTagName('html')[0].style.overflow = 'hidden';
15
+ document.body.appendChild(this.host);
16
+ }
17
+ remove() {
18
+ this.host.remove();
19
+ document.getElementsByTagName('html')[0].style.overflow = '';
20
+ }
21
+ }
@@ -0,0 +1 @@
1
+ export declare const createShadowRoot: (host: HTMLElement) => ShadowRoot;
@@ -0,0 +1,23 @@
1
+ import normalize from './_normalize.scss?raw';
2
+ import reset from './_reset.scss?raw';
3
+ export const createShadowRoot = (host) => {
4
+ prepareShadowRootHost(host);
5
+ const shadowRoot = host.attachShadow({ mode: 'open' });
6
+ const link = document.createElement('link');
7
+ link.rel = 'stylesheet';
8
+ link.href = 'https://fonts.googleapis.com/css2?family=Inter:wght@300..700&display=swap';
9
+ shadowRoot.appendChild(link);
10
+ const styleElement = document.createElement('style');
11
+ styleElement.textContent = normalize + reset;
12
+ shadowRoot.appendChild(styleElement);
13
+ return shadowRoot;
14
+ };
15
+ const prepareShadowRootHost = (host) => {
16
+ host.style.all = 'unset';
17
+ host.style.lineHeight = '1.15';
18
+ host.style.font = '16px Inter, sans-serif, arial';
19
+ host.style.fontWeight = '400';
20
+ host.style.margin = '0';
21
+ host.style.boxSizing = 'border-box';
22
+ host.style.textAlign = 'initial';
23
+ };
@@ -18,7 +18,7 @@ import IconSpeaker from '@fluentui/svg-icons/icons/speaker_2_20_regular.svg?raw'
18
18
  import IconSpeakerMute from '@fluentui/svg-icons/icons/speaker_mute_20_regular.svg?raw';
19
19
  import { onDestroy, onMount, untrack } from 'svelte';
20
20
  import { slide } from 'svelte/transition';
21
- let { src, poster, id = randomNanoid(), controls = true, autoplay = false, loop = false, inert = false, intersectionContainer, on } = $props();
21
+ let { src, poster, id = randomNanoid(), controls = true, autoplay = false, loop = false, inert = false, hideSpeaker = false, intersectionContainer, on } = $props();
22
22
  onMount(() => {
23
23
  var _a;
24
24
  PlaybackManager.registerMountedPlayer(id, {
@@ -270,7 +270,7 @@ const handleSeek = (percent) => {
270
270
  <Icon src={IconPause} color={IconColor.White} />
271
271
  </button>
272
272
  {/if}
273
- {#if showControlsOnHover || MediaVolumeManager.isMuted}
273
+ {#if (showControlsOnHover || MediaVolumeManager.isMuted) && !hideSpeaker}
274
274
  <button type="button" aria-label={MediaVolumeManager.isMuted ? 'mute' : 'unmute'} class="video__mute-button" onclick={toggleMute}>
275
275
  {#if MediaVolumeManager.isMuted}
276
276
  <Icon src={IconSpeakerMute} color={IconColor.White} />
@@ -7,6 +7,7 @@ type Props = {
7
7
  loop?: boolean;
8
8
  intersectionContainer?: HTMLElement;
9
9
  inert?: boolean;
10
+ hideSpeaker?: boolean;
10
11
  on?: {
11
12
  loaded?: (data: {
12
13
  id: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@streamscloud/embeddable",
3
- "version": "3.4.2",
3
+ "version": "4.0.0",
4
4
  "author": "StreamsCloud",
5
5
  "repository": "https://github.com/StreamsCloud/streamscloud-frontend-packages.git",
6
6
  "type": "module",
@@ -1,140 +0,0 @@
1
- <script lang="ts">import { Image } from '../../ui/image';
2
- import { LineClamp } from '../../ui/line-clamp';
3
- import { ProportionalContainer } from '../../ui/proportional-container';
4
- let { ad } = $props();
5
- </script>
6
-
7
- <div class="ad">
8
- <ProportionalContainer ratio={234 / 277}>
9
- <Image src={ad.image} alt={ad.title} />
10
- </ProportionalContainer>
11
- <div class="ad__info">
12
- {#if ad.title}
13
- <div class="ad__title">{ad.title}</div>
14
- {/if}
15
- {#if ad.description}
16
- <div class="ad__description">
17
- <LineClamp value={ad.description} maxLines={2} />
18
- </div>
19
- {/if}
20
- {#if ad.price && ad.currency}
21
- <div class="ad__price">{ad.currency} {ad.price}</div>
22
- {/if}
23
- {#if ad.ctaButton}
24
- <div class="ad__button">
25
- <a
26
- href={ad.ctaButton.url}
27
- target="_blank"
28
- class="short-video-ad-viewer__link"
29
- style="background-color: {ad.ctaButton.background}; color: {ad.ctaButton.textColor}; border: {ad.ctaButton
30
- .border}; text-decoration: none; padding: 0.5em 1em; border-radius: 0.25em; display: inline-block;">
31
- {ad.ctaButton.text}
32
- </a>
33
- </div>
34
- {/if}
35
- </div>
36
- </div>
37
-
38
- <style>@keyframes fadeIn {
39
- 0% {
40
- opacity: 1;
41
- }
42
- 50% {
43
- opacity: 0.4;
44
- }
45
- 100% {
46
- opacity: 1;
47
- }
48
- }
49
- .ad {
50
- --image--border-radius: 0.25rem;
51
- --image--object-fit: fit;
52
- --image--width: auto;
53
- --image--height: auto;
54
- width: 100%;
55
- height: max-content;
56
- display: flex;
57
- flex-direction: column;
58
- position: relative;
59
- container-type: inline-size;
60
- aspect-ratio: 9/16;
61
- background-color: #fafafa;
62
- border: 0.038125rem solid #999999;
63
- border-radius: 0.5rem;
64
- padding: 0.75rem 0.75rem 1.125rem;
65
- justify-content: space-between;
66
- /* Set 'container-type: inline-size;' to reference container*/
67
- }
68
- @container (width < 230px) {
69
- .ad {
70
- padding: 0.5rem 0.5rem 0.75rem;
71
- }
72
- }
73
- .ad__info {
74
- display: flex;
75
- flex-direction: column;
76
- gap: 0.375rem;
77
- margin-top: 0.1875rem;
78
- /* Set 'container-type: inline-size;' to reference container*/
79
- }
80
- @container (width < 230px) {
81
- .ad__info {
82
- gap: 0.25rem;
83
- margin-top: 0.125rem;
84
- }
85
- }
86
- .ad__title {
87
- font-weight: 700;
88
- font-size: 1.125rem;
89
- line-height: 1.375rem;
90
- min-height: 1.375rem;
91
- color: #000000;
92
- /* Set 'container-type: inline-size;' to reference container*/
93
- }
94
- @container (width < 230px) {
95
- .ad__title {
96
- font-size: 0.75rem;
97
- line-height: 0.875rem;
98
- min-height: 0.875rem;
99
- }
100
- }
101
- .ad__description {
102
- font-weight: 400;
103
- color: #6b7280;
104
- font-size: 0.9375rem;
105
- line-height: 1.375rem;
106
- min-height: 1.375rem;
107
- /* Set 'container-type: inline-size;' to reference container*/
108
- }
109
- @container (width < 230px) {
110
- .ad__description {
111
- font-size: 0.625rem;
112
- line-height: 0.875rem;
113
- min-height: 0.875rem;
114
- }
115
- }
116
- .ad__price {
117
- font-size: 1.875rem;
118
- font-weight: 700;
119
- text-align: right;
120
- min-height: 3.53125rem;
121
- color: #000000;
122
- /* Set 'container-type: inline-size;' to reference container*/
123
- }
124
- @container (width < 230px) {
125
- .ad__price {
126
- font-size: 1.25rem;
127
- min-height: 2.40625rem;
128
- }
129
- }
130
- .ad__button {
131
- display: flex;
132
- justify-content: center;
133
- margin-top: auto;
134
- width: 100%;
135
- }
136
- :global([data-theme="dark"]) .ad {
137
- background-color: #121212;
138
- color: #ffffff;
139
- border-color: #1e1e1e;
140
- }</style>
@@ -1,168 +0,0 @@
1
- <script lang="ts">import { toPriceRepresentation } from '../../products/price-helper';
2
- import { ImageRounded } from '../../ui/image';
3
- import { ProportionalContainer } from '../../ui/proportional-container';
4
- import { ShortVideoProductLocalization } from './short-video-product-localization';
5
- let { product, fitToContainer = false, localization: localizationInit, on } = $props();
6
- const localization = $derived(new ShortVideoProductLocalization(localizationInit));
7
- const handleProductClick = (event) => {
8
- if (!product.link) {
9
- return;
10
- }
11
- event.preventDefault();
12
- event.stopPropagation();
13
- if (on === null || on === void 0 ? void 0 : on.productClick) {
14
- on.productClick(product.id);
15
- }
16
- window.open(product.link, '_blank', 'noopener noreferrer');
17
- };
18
- </script>
19
-
20
- <div class="short-video-product-viewer">
21
- {#if fitToContainer}
22
- <div class="short-video-product-viewer__image">
23
- <ImageRounded src={product.image} noBorders={true} />
24
- </div>
25
- {:else}
26
- <ProportionalContainer ratio={4 / 5}>
27
- <ImageRounded src={product.image} noBorders={true} />
28
- </ProportionalContainer>
29
- {/if}
30
- <div class="short-video-product-viewer__name">{product.title}</div>
31
- <div class="short-video-product-viewer__price">
32
- <div class="product-price">
33
- {#if !product.salePrice}
34
- <div class="product-price__price">{toPriceRepresentation(product.price, product.currency)}</div>
35
- {:else}
36
- <div class="product-price__before-price">
37
- {#if localization.beforeNowPrefix}
38
- {localization.beforeNowPrefix}
39
- {/if}
40
- {toPriceRepresentation(product.price, product.currency)}
41
- </div>
42
- <div class="product-price__price product-price__price--sale">
43
- {toPriceRepresentation(product.salePrice, product.currency)}
44
- </div>
45
- {/if}
46
- </div>
47
- </div>
48
-
49
- {#if product.link}
50
- <a href={product.link} onclick={handleProductClick} target="_blank" rel="noopener noreferrer" class="short-video-product-viewer__link" aria-label="none"
51
- >&nbsp;</a>
52
- {/if}
53
- </div>
54
-
55
- <style>@keyframes fadeIn {
56
- 0% {
57
- opacity: 1;
58
- }
59
- 50% {
60
- opacity: 0.4;
61
- }
62
- 100% {
63
- opacity: 1;
64
- }
65
- }
66
- .short-video-product-viewer {
67
- width: 100%;
68
- height: auto;
69
- position: relative;
70
- display: flex;
71
- flex-direction: column;
72
- container-type: inline-size;
73
- --image--object-fit: contain;
74
- --image--rounded--outer--border-radius: 0.25em;
75
- --image--rounded--inner--border-color: transparent;
76
- --image--rounded--outer--border-color: transparent;
77
- }
78
- .short-video-product-viewer__image {
79
- flex: 1;
80
- min-height: 0;
81
- }
82
- .short-video-product-viewer__name {
83
- width: 100%;
84
- font-weight: 500;
85
- font-size: 0.9375rem;
86
- color: #ffffff;
87
- margin-top: 0.5rem;
88
- padding: 0 0.3125rem;
89
- text-align: center;
90
- text-overflow: ellipsis;
91
- width: 100%;
92
- white-space: nowrap;
93
- overflow: hidden;
94
- /* Set 'container-type: inline-size;' to reference container*/
95
- }
96
- @container (width < 300px) {
97
- .short-video-product-viewer__name {
98
- font-size: 0.75rem;
99
- margin-top: 0.3125rem;
100
- padding: 0 0.25rem;
101
- }
102
- }
103
- .short-video-product-viewer__price {
104
- padding-top: 0.3125rem;
105
- margin-top: auto;
106
- /* Set 'container-type: inline-size;' to reference container*/
107
- }
108
- @container (width < 300px) {
109
- .short-video-product-viewer__price {
110
- padding-top: 0.25rem;
111
- }
112
- }
113
- .short-video-product-viewer__link {
114
- position: absolute;
115
- top: 0;
116
- left: 0;
117
- width: 100%;
118
- height: 100%;
119
- }
120
-
121
- .product-price {
122
- width: 100%;
123
- display: flex;
124
- flex-direction: column;
125
- gap: 0.4375rem;
126
- /* Set 'container-type: inline-size;' to reference container*/
127
- }
128
- @container (width < 300px) {
129
- .product-price {
130
- gap: 0.3125rem;
131
- }
132
- }
133
- .product-price__before-price {
134
- width: 100%;
135
- color: #e5e7eb;
136
- text-decoration: line-through;
137
- font-size: 0.75rem;
138
- font-weight: 500;
139
- text-align: center;
140
- text-overflow: ellipsis;
141
- width: 100%;
142
- white-space: nowrap;
143
- overflow: hidden;
144
- /* Set 'container-type: inline-size;' to reference container*/
145
- }
146
- @container (width < 300px) {
147
- .product-price__before-price {
148
- font-size: 0.625em;
149
- }
150
- }
151
- .product-price__price {
152
- width: 100%;
153
- font-size: 1.0625em;
154
- color: #ffffff;
155
- font-weight: 800;
156
- margin-top: auto;
157
- text-align: center;
158
- text-overflow: ellipsis;
159
- width: 100%;
160
- white-space: nowrap;
161
- overflow: hidden;
162
- /* Set 'container-type: inline-size;' to reference container*/
163
- }
164
- @container (width < 300px) {
165
- .product-price__price {
166
- font-size: 0.9375em;
167
- }
168
- }</style>
@@ -1,14 +0,0 @@
1
- import type { Locale } from '../../core/locale';
2
- import { type IShortVideoProductLocalization } from './short-video-product-localization';
3
- import type { ShortVideoViewerProductModel } from './types';
4
- type Props = {
5
- product: ShortVideoViewerProductModel;
6
- fitToContainer?: boolean;
7
- localization: IShortVideoProductLocalization | Locale;
8
- on?: {
9
- productClick?: (productId: string) => void;
10
- };
11
- };
12
- declare const Cmp: import("svelte").Component<Props, {}, "">;
13
- type Cmp = ReturnType<typeof Cmp>;
14
- export default Cmp;
@@ -1,125 +0,0 @@
1
- <script lang="ts">import { slideHorizontally } from '../../core/transitions';
2
- import { default as ShortVideoAttachments } from './cmp.attachments.svelte';
3
- import { default as ShortVideoHeading } from './cmp.short-video-heading.svelte';
4
- import { ShortVideoDetailsLocalization } from './short-video-details-localization';
5
- import {} from './types';
6
- let { shortVideo, collapsed, localization: localizationInit, on } = $props();
7
- const localization = $derived(new ShortVideoDetailsLocalization(localizationInit));
8
- </script>
9
-
10
- {#if !collapsed}
11
- <div class="short-video-details" transition:slideHorizontally|local data-theme="dark">
12
- <div class="short-video-details__sliding-container">
13
- <div class="short-video-details__content">
14
- {#if shortVideo.heading}
15
- <div class="short-video-details__heading">
16
- <ShortVideoHeading
17
- model={shortVideo.heading}
18
- localization={{ viewsCount: localization.viewsCount, timeAgoLocalization: localization.timeAgoLocalization }} />
19
- </div>
20
- {/if}
21
- {#if shortVideo.text}
22
- <p class="short-video-details__text">
23
- {shortVideo.text}
24
- </p>
25
- {/if}
26
- </div>
27
-
28
- <div class="short-video-details__section-splitter"></div>
29
-
30
- <ShortVideoAttachments shortVideo={shortVideo} localization={localization.attachmentsLocalization} on={on} />
31
- </div>
32
- </div>
33
- {/if}
34
-
35
- <style>@keyframes fadeIn {
36
- 0% {
37
- opacity: 1;
38
- }
39
- 50% {
40
- opacity: 0.4;
41
- }
42
- 100% {
43
- opacity: 1;
44
- }
45
- }
46
- .short-video-details {
47
- --_short-video-details--padding-horizontal: 1rem;
48
- --short-video-attachments--margin-vertical: 1.25rem;
49
- --short-video-attachments--spacing-horizontal: var(--_short-video-details--padding-horizontal);
50
- background: #1c1c1c;
51
- height: 100%;
52
- min-height: 100%;
53
- max-height: 100%;
54
- width: 25rem;
55
- min-width: 25rem;
56
- max-width: 25rem;
57
- display: flex;
58
- flex-direction: column;
59
- min-height: 0;
60
- padding-bottom: 0.9375rem;
61
- overflow: auto;
62
- scrollbar-color: transparent transparent;
63
- scrollbar-width: thin;
64
- --custom-scrollbar-color: #999999;
65
- position: absolute;
66
- top: 0;
67
- right: 0;
68
- height: 100%;
69
- z-index: 1;
70
- /* Set 'container-type: inline-size;' to reference container*/
71
- }
72
- .short-video-details::-webkit-scrollbar {
73
- width: 3px;
74
- height: 3px;
75
- background: var(--custom-scrollbar-background, transparent);
76
- visibility: hidden;
77
- }
78
- .short-video-details::-webkit-scrollbar-thumb {
79
- background: transparent;
80
- }
81
- .short-video-details:hover {
82
- scrollbar-color: var(--custom-scrollbar-color, #7d7d7d) var(--custom-scrollbar-background, transparent);
83
- scrollbar-width: thin;
84
- }
85
- .short-video-details:hover::-webkit-scrollbar {
86
- width: 3px;
87
- height: 3px;
88
- background: var(--custom-scrollbar-background, transparent);
89
- visibility: hidden;
90
- }
91
- .short-video-details:hover::-webkit-scrollbar-thumb {
92
- background: var(--custom-scrollbar-color, #7d7d7d);
93
- }
94
- .short-video-details__sliding-container {
95
- flex: 1;
96
- display: flex;
97
- flex-direction: column;
98
- min-height: 0;
99
- }
100
- @container (width < 576px) {
101
- .short-video-details {
102
- width: 100%;
103
- min-width: 100%;
104
- max-width: 100%;
105
- }
106
- }
107
- .short-video-details__content {
108
- padding: 1.5rem var(--_short-video-details--padding-horizontal) 0.875rem;
109
- margin-bottom: 0.875rem;
110
- }
111
- .short-video-details__heading {
112
- --short-video-heading--padding: 0 1.875rem 1.25rem 0;
113
- }
114
- .short-video-details__text {
115
- color: #d1d5db;
116
- font-size: 0.9375rem;
117
- line-height: 1.125rem;
118
- font-weight: 400;
119
- white-space: pre-line;
120
- word-break: break-word;
121
- margin-bottom: 0.4375rem;
122
- }
123
- .short-video-details__section-splitter {
124
- border-bottom: 1px solid #4b5563;
125
- }</style>
@@ -1,14 +0,0 @@
1
- import type { Locale } from '../../core/locale';
2
- import { type IShortVideoDetailsLocalization } from './short-video-details-localization';
3
- import { type ShortVideoViewerModel } from './types';
4
- type Props = {
5
- shortVideo: ShortVideoViewerModel;
6
- collapsed: boolean;
7
- localization: IShortVideoDetailsLocalization | Locale;
8
- on?: {
9
- productClick?: (productId: string) => void;
10
- };
11
- };
12
- declare const Cmp: import("svelte").Component<Props, {}, "">;
13
- type Cmp = ReturnType<typeof Cmp>;
14
- export default Cmp;