@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
@@ -1,6 +1,7 @@
1
1
  <script lang="ts">var _a, _b;
2
+ import { slideHorizontally } from '../../core/transitions';
2
3
  import { ShortVideoViewerAttachmentsInline, ShortVideoViewerAttachments } from '../../short-videos/short-video-viewer';
3
- import { ShortVideoSocialInteractions } from '../../short-videos/short-video-viewer/index.js';
4
+ import { ShortVideoControls } from '../../short-videos/short-video-viewer/index.js';
4
5
  import { StreamElementType } from '../layout/enums';
5
6
  import { mapToShortVideoViewerModel } from '../layout/models';
6
7
  import { Icon } from '../../ui/icon';
@@ -8,7 +9,7 @@ import { StreamPlayerLocalization } from './stream-player-localization';
8
9
  import IconChevronDown from '@fluentui/svg-icons/icons/chevron_down_28_regular.svg?raw';
9
10
  import IconChevronUp from '@fluentui/svg-icons/icons/chevron_up_28_regular.svg?raw';
10
11
  import IconDismiss from '@fluentui/svg-icons/icons/dismiss_28_regular.svg?raw';
11
- let { buffer, uiManager, localization, on } = $props();
12
+ let { buffer, uiManager, shortVideoSocialInteractionsHandler, localization, on } = $props();
12
13
  const shortVideo = $derived(((_a = buffer.current) === null || _a === void 0 ? void 0 : _a.type) === 'short-video' && ((_b = buffer.current) === null || _b === void 0 ? void 0 : _b.shortVideo) ? mapToShortVideoViewerModel(buffer.current.shortVideo) : null);
13
14
  const singleWebViewPage = $derived.by(() => {
14
15
  var _a;
@@ -45,42 +46,51 @@ const changeShowShortVideoAttachments = () => {
45
46
  };
46
47
  </script>
47
48
 
48
- <div class="stream-player-controls">
49
- <div class="stream-player-controls__left">
50
- {#if shortVideo && uiManager.shortVideoDetailsCollapsed && !uiManager.showShortVideoOverlay}
51
- <div class="stream-player-controls__short-video-overlay">
52
- {#if uiManager.showShortVideoAttachments}
53
- <div class="stream-player-controls__short-video-attachments-inline">
54
- <ShortVideoViewerAttachmentsInline model={shortVideo} />
55
- </div>
56
- {/if}
57
- <ShortVideoSocialInteractions model={shortVideo} on={{ attachmentsClicked: changeShowShortVideoAttachments }} />
49
+ {#if uiManager.viewInitialized && !uiManager.showShortVideoOverlay}
50
+ <div class="stream-player-controls">
51
+ <div class="stream-player-controls__left">
52
+ {#if shortVideo}
53
+ <div class="stream-player-controls__short-video-hub">
54
+ {#if uiManager.showShortVideoAttachments}
55
+ <div class="stream-player-controls__short-video-attachments-inline">
56
+ <ShortVideoViewerAttachmentsInline model={shortVideo} />
57
+ </div>
58
+ {/if}
59
+ <ShortVideoControls
60
+ model={shortVideo}
61
+ socialInteractionsHandler={shortVideoSocialInteractionsHandler}
62
+ on={{ attachmentsClicked: changeShowShortVideoAttachments }} />
63
+ </div>
64
+ {/if}
65
+ <div class="stream-player-controls__navigation-buttons" class:stream-player-controls__navigation-buttons--single-web-view-page={singleWebViewPage}>
66
+ <button type="button" class="navigation-button" disabled={!buffer.canLoadPrevious} onclick={buffer.loadPrevious}>
67
+ <span class="navigation-button__icon">
68
+ <Icon src={IconChevronUp} />
69
+ </span>
70
+ </button>
71
+ <button type="button" class="navigation-button" disabled={!buffer.canLoadNext} onclick={buffer.loadNext}>
72
+ <span class="navigation-button__icon">
73
+ <Icon src={IconChevronDown} />
74
+ </span>
75
+ </button>
58
76
  </div>
59
- {/if}
60
- <div class="stream-player-controls__navigation-buttons" class:stream-player-controls__navigation-buttons--single-web-view-page={singleWebViewPage}>
61
- <button type="button" class="navigation-button" disabled={!buffer.canLoadPrevious} onclick={buffer.loadPrevious}>
62
- <Icon src={IconChevronUp} />
63
- </button>
64
- <button type="button" class="navigation-button" disabled={!buffer.canLoadNext} onclick={buffer.loadNext}>
65
- <Icon src={IconChevronDown} />
66
- </button>
77
+ </div>
78
+ <div class="stream-player-controls__right">
79
+ {#if shortVideo && uiManager.showShortVideoAttachments}
80
+ <div class="stream-player-controls__short-video-attachments" transition:slideHorizontally|local>
81
+ <ShortVideoViewerAttachments
82
+ shortVideo={shortVideo}
83
+ localization={localization.shortVideoAttachmentsLocalization}
84
+ on={{
85
+ productClick: on.productClick
86
+ }} />
87
+ </div>
88
+ {/if}
67
89
  </div>
68
90
  </div>
69
- <div class="stream-player-controls__right">
70
- {#if shortVideo && shortVideo.products && uiManager.showShortVideoAttachments}
71
- <div class="stream-player-controls__short-video-attachments">
72
- <ShortVideoViewerAttachments
73
- shortVideo={shortVideo}
74
- localization={localization.shortVideoAttachmentsLocalization}
75
- on={{
76
- productClick: on.productClick
77
- }} />
78
- </div>
79
- {/if}
80
- </div>
81
- </div>
91
+ {/if}
82
92
 
83
- <button type="button" class="close-button" onclick={on.closePlayer} class:close-button--left={uiManager.overviewCollapsed}>
93
+ <button type="button" class="close-button" onclick={on.closePlayer}>
84
94
  <Icon src={IconDismiss} />
85
95
  </button>
86
96
 
@@ -95,34 +105,6 @@ const changeShowShortVideoAttachments = () => {
95
105
  opacity: 1;
96
106
  }
97
107
  }
98
- .close-button {
99
- position: absolute;
100
- top: 0.9375rem;
101
- left: 15.1875rem;
102
- z-index: 1;
103
- width: var(--stream-player--button--size);
104
- min-width: var(--stream-player--button--size);
105
- max-width: var(--stream-player--button--size);
106
- height: var(--stream-player--button--size);
107
- min-height: var(--stream-player--button--size);
108
- max-height: var(--stream-player--button--size);
109
- background-color: rgba(0, 0, 0, 0.6);
110
- border: 0.0625rem solid #1c1c1e;
111
- border-radius: 50%;
112
- text-align: center;
113
- --icon--color: #ffffff;
114
- /* Set 'container-type: inline-size;' to reference container*/
115
- }
116
- .close-button--left {
117
- left: 0.625rem;
118
- }
119
- @container (width < 576px) {
120
- .close-button {
121
- left: unset;
122
- right: 0.625rem;
123
- }
124
- }
125
-
126
108
  .stream-player-controls {
127
109
  position: absolute;
128
110
  top: 0;
@@ -131,7 +113,6 @@ const changeShowShortVideoAttachments = () => {
131
113
  width: var(--stream-player--sidebar--available-space);
132
114
  display: flex;
133
115
  justify-content: space-between;
134
- gap: 2.5rem;
135
116
  padding: var(--stream-player--controls--offset-vertical) var(--stream-player--controls--offset-horizontal);
136
117
  container-type: inline-size;
137
118
  }
@@ -148,14 +129,8 @@ const changeShowShortVideoAttachments = () => {
148
129
  justify-content: space-between;
149
130
  align-items: flex-end;
150
131
  flex-direction: column;
151
- /* Set 'container-type: inline-size;' to reference container*/
152
132
  }
153
- @container (width < 9.375rem) {
154
- .stream-player-controls__right {
155
- display: none;
156
- }
157
- }
158
- .stream-player-controls__short-video-overlay {
133
+ .stream-player-controls__short-video-hub {
159
134
  gap: 2.5rem;
160
135
  display: flex;
161
136
  flex: 1;
@@ -163,6 +138,7 @@ const changeShowShortVideoAttachments = () => {
163
138
  flex-direction: column;
164
139
  align-items: flex-start;
165
140
  justify-content: flex-end;
141
+ --short-video-controls--icon--size: var(--stream-player--icon--size);
166
142
  }
167
143
  .stream-player-controls__short-video-attachments-inline {
168
144
  display: none;
@@ -215,15 +191,44 @@ const changeShowShortVideoAttachments = () => {
215
191
  flex-direction: column;
216
192
  gap: 1rem;
217
193
  z-index: 1;
194
+ }
195
+
196
+ .close-button {
197
+ width: var(--stream-player--button--size);
198
+ min-width: var(--stream-player--button--size);
199
+ max-width: var(--stream-player--button--size);
200
+ height: var(--stream-player--button--size);
201
+ min-height: var(--stream-player--button--size);
202
+ max-height: var(--stream-player--button--size);
203
+ background-color: rgba(0, 0, 0, 0.6);
204
+ border: 0.0625rem solid #1c1c1c;
205
+ border-radius: 50%;
206
+ text-align: center;
207
+ --icon--color: #ffffff;
208
+ --icon--size: var(--stream-player--icon--size);
209
+ position: absolute;
210
+ top: 0.9375rem;
211
+ left: calc(var(--stream-player--overview--width) + 0.625rem);
212
+ z-index: 1;
218
213
  /* Set 'container-type: inline-size;' to reference container*/
219
214
  }
220
- @container (width < 6.25rem) {
221
- .stream-player-controls__navigation-buttons {
222
- visibility: hidden;
215
+ .close-button:disabled {
216
+ opacity: 0.5;
217
+ cursor: default;
218
+ }
219
+ .close-button:hover {
220
+ background-color: rgba(0, 0, 0, 0.9);
221
+ transition: background-color 0.5s;
222
+ }
223
+ @container (width < 576px) {
224
+ .close-button {
225
+ left: unset;
226
+ right: 0.625rem;
223
227
  }
224
228
  }
225
229
 
226
230
  .navigation-button {
231
+ --_icon-scale: 1;
227
232
  width: var(--stream-player--button--size);
228
233
  min-width: var(--stream-player--button--size);
229
234
  max-width: var(--stream-player--button--size);
@@ -231,7 +236,7 @@ const changeShowShortVideoAttachments = () => {
231
236
  min-height: var(--stream-player--button--size);
232
237
  max-height: var(--stream-player--button--size);
233
238
  background-color: rgba(0, 0, 0, 0.6);
234
- border: 0.0625rem solid #1c1c1e;
239
+ border: 0.0625rem solid #1c1c1c;
235
240
  border-radius: 50%;
236
241
  text-align: center;
237
242
  --icon--color: #ffffff;
@@ -240,4 +245,12 @@ const changeShowShortVideoAttachments = () => {
240
245
  .navigation-button:disabled {
241
246
  opacity: 0.5;
242
247
  cursor: default;
248
+ }
249
+ .navigation-button:hover:not(:disabled) {
250
+ --_icon-scale: 1.2;
251
+ }
252
+ .navigation-button__icon {
253
+ display: block;
254
+ transform: scale(var(--_icon-scale));
255
+ transition: 0.3s;
243
256
  }</style>
@@ -1,9 +1,11 @@
1
+ import { type ShortVideoSocialInteractionsHanlder } from '../../short-videos/short-video-viewer';
1
2
  import type { StreamPlayerBuffer } from './stream-player-buffer.svelte';
2
3
  import { StreamPlayerLocalization } from './stream-player-localization';
3
4
  import type { StreamPlayerUiManager } from './ui-manager.svelte';
4
5
  type Props = {
5
6
  buffer: StreamPlayerBuffer;
6
7
  uiManager: StreamPlayerUiManager;
8
+ shortVideoSocialInteractionsHandler?: ShortVideoSocialInteractionsHanlder;
7
9
  localization: StreamPlayerLocalization;
8
10
  on: {
9
11
  closePlayer: () => void;
@@ -1,3 +1,4 @@
1
+ import type { ShortVideoSocialInteractionsHanlder } from '../../short-videos/short-video-viewer';
1
2
  import type { IStreamPlayerLocalization } from './stream-player-localization';
2
3
  export type { IStreamPlayerLocalization };
3
4
  /**
@@ -28,6 +29,7 @@ export declare const openStreamPlayer: (init: {
28
29
  graphqlOrigin?: string;
29
30
  localization?: IStreamPlayerLocalization | "en" | "no";
30
31
  showStreamsCloudWatermark?: boolean;
32
+ shortVideoSocialInteractionsHandler?: ShortVideoSocialInteractionsHanlder;
31
33
  initiator?: string;
32
34
  on?: {
33
35
  streamActivated?: (data: {
@@ -1,5 +1,5 @@
1
1
  import { getLocale } from '../../core/locale';
2
- import { ShadowHost } from '../../ui/shadow-dom';
2
+ import { ModalShadowHost } from '../../ui/shadow-dom';
3
3
  import { default as StreamPlayer } from './cmp.stream-player.svelte';
4
4
  import { AppEventsTracker } from '@streamscloud/streams-analytics-collector';
5
5
  import { mount, unmount } from 'svelte';
@@ -27,8 +27,8 @@ import { mount, unmount } from 'svelte';
27
27
  * ```
28
28
  */
29
29
  export const openStreamPlayer = (init) => {
30
- const { streamId, graphqlOrigin, localization, showStreamsCloudWatermark, initiator } = init;
31
- const shadowHost = new ShadowHost();
30
+ const { streamId, graphqlOrigin, localization, showStreamsCloudWatermark, shortVideoSocialInteractionsHandler, initiator } = init;
31
+ const shadowHost = new ModalShadowHost();
32
32
  const mounted = mount(StreamPlayer, {
33
33
  target: shadowHost.shadowRoot,
34
34
  props: {
@@ -36,6 +36,7 @@ export const openStreamPlayer = (init) => {
36
36
  graphqlOrigin,
37
37
  localization: getLocale(localization),
38
38
  showStreamsCloudWatermark,
39
+ shortVideoSocialInteractionsHandler,
39
40
  initiator,
40
41
  on: {
41
42
  streamActivated: (data) => {
@@ -1,3 +1,3 @@
1
1
  import type { StreamPlayerPayloadFragment } from './operations.generated';
2
2
  import type { StreamPlayerModel } from './types';
3
- export declare const mapStreamPlayerModel: (payload: StreamPlayerPayloadFragment) => StreamPlayerModel;
3
+ export declare const mapToStreamPlayerModel: (payload: StreamPlayerPayloadFragment) => StreamPlayerModel;
@@ -1,4 +1,4 @@
1
- export const mapStreamPlayerModel = (payload) => {
1
+ export const mapToStreamPlayerModel = (payload) => {
2
2
  const headerDataProvider = payload.availableFrom ?? payload.ownerProfile;
3
3
  return {
4
4
  id: payload.id,
@@ -8,10 +8,21 @@ import { TimeAgo } from '../../ui/time-ago';
8
8
  import { StreamPlayerLocalization } from './stream-player-localization';
9
9
  import IconPanelLeftText from '@fluentui/svg-icons/icons/panel_left_text_20_regular.svg?raw';
10
10
  let { model, buffer, activePageId, on, uiManager, localization } = $props();
11
+ const overviewAttached = (node) => {
12
+ const resizeObserver = new ResizeObserver(() => {
13
+ on.widthChanged(node.clientWidth);
14
+ });
15
+ resizeObserver.observe(node);
16
+ return {
17
+ destroy() {
18
+ resizeObserver.disconnect();
19
+ }
20
+ };
21
+ };
11
22
  </script>
12
23
 
13
24
  {#if !uiManager.overviewCollapsed}
14
- <div class="stream-overview" transition:slideHorizontally|local>
25
+ <div class="stream-overview" transition:slideHorizontally|local use:overviewAttached>
15
26
  <div class="stream-overview-info">
16
27
  <div class="stream-overview-owner">
17
28
  <div class="stream-overview-owner__image">
@@ -10,6 +10,7 @@ type Props = {
10
10
  localization: StreamPlayerLocalization;
11
11
  on: {
12
12
  setCurrentItem: (index: number) => void;
13
+ widthChanged: (width: number) => void;
13
14
  };
14
15
  };
15
16
  declare const StreamOverview: import("svelte").Component<Props, {}, "">;
@@ -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,20 @@
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;
6
+ viewInitialized: boolean;
7
7
  showShortVideoOverlay: boolean;
8
8
  private readonly buttonSize;
9
+ private readonly iconSize;
9
10
  private readonly controlsOffsetHorizontal;
10
11
  private readonly controlsOffsetVertical;
11
- private readonly iconSize;
12
12
  private viewTotalWidth;
13
13
  private mainViewColumnWidth;
14
+ private overviewWidth;
14
15
  updateDimensions: (dimensions: {
15
16
  viewTotalWidth: number;
16
17
  mainViewColumnWidth: number;
17
18
  }) => void;
19
+ updateOverviewWidth: (width: number) => void;
18
20
  }
@@ -1,27 +1,32 @@
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
+ viewInitialized = $derived.by(() => !!this.viewTotalWidth && !!this.mainViewColumnWidth);
17
+ showShortVideoOverlay = $derived.by(() => this.viewInitialized && (this.viewTotalWidth - this.mainViewColumnWidth) / 2 <= 85);
17
18
  buttonSize = 48;
19
+ iconSize = 28;
18
20
  controlsOffsetHorizontal = 28;
19
21
  controlsOffsetVertical = 28;
20
- iconSize = 28;
21
22
  viewTotalWidth = $state(0);
22
23
  mainViewColumnWidth = $state(0);
24
+ overviewWidth = $state(0);
23
25
  updateDimensions = (dimensions) => {
24
26
  this.viewTotalWidth = dimensions.viewTotalWidth;
25
27
  this.mainViewColumnWidth = dimensions.mainViewColumnWidth;
26
28
  };
29
+ updateOverviewWidth = (width) => {
30
+ this.overviewWidth = width;
31
+ };
27
32
  }
@@ -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
  }
@@ -51,20 +51,25 @@ const toggleShowMore = () => {
51
51
  </script>
52
52
 
53
53
  <div class="line-clamp" bind:this={element}>
54
- <div class="line-clamp__wrapper" bind:this={clampWrapperRef}>
55
- {#if children}
56
- {@render children()}
57
- {:else if value}
58
- {@html value}
54
+ <div class="line-clamp__wrapper-container">
55
+ <div class="line-clamp__wrapper" bind:this={clampWrapperRef}>
56
+ {#if children}
57
+ {@render children()}
58
+ {:else if value}
59
+ {@html value}
60
+ {/if}
61
+ </div>
62
+
63
+ {#if enableShowMore && isTruncated && !showingAllText}
64
+ <button type="button" class="line-clamp__show-more-button line-clamp__show-more-button--inline" onclick={toggleShowMore}>
65
+ {localization.showMore}
66
+ </button>
59
67
  {/if}
60
68
  </div>
61
- {#if enableShowMore && (isTruncated || showingAllText)}
69
+
70
+ {#if enableShowMore && showingAllText}
62
71
  <button type="button" class="line-clamp__show-more-button" onclick={toggleShowMore}>
63
- {#if showingAllText}
64
- {localization.showLess}
65
- {:else}
66
- {localization.showMore}
67
- {/if}
72
+ {localization.showLess}
68
73
  </button>
69
74
  {/if}
70
75
  </div>
@@ -75,6 +80,9 @@ const toggleShowMore = () => {
75
80
  display: flex;
76
81
  flex-direction: column;
77
82
  }
83
+ .line-clamp__wrapper-container {
84
+ position: relative;
85
+ }
78
86
  .line-clamp__wrapper {
79
87
  display: -webkit-box;
80
88
  overflow: hidden;
@@ -83,7 +91,21 @@ const toggleShowMore = () => {
83
91
  -webkit-box-orient: vertical;
84
92
  }
85
93
  .line-clamp__show-more-button {
86
- margin-top: 0.5em;
87
94
  font-size: 0.9em;
88
- opacity: 0.8;
95
+ font-style: italic;
96
+ }
97
+ .line-clamp__show-more-button--inline {
98
+ position: absolute;
99
+ bottom: 0;
100
+ right: 0;
101
+ padding-left: 1em;
102
+ backdrop-filter: blur(2px);
103
+ }
104
+ .line-clamp__show-more-button--inline::after {
105
+ content: "...";
106
+ position: absolute;
107
+ left: 0;
108
+ }
109
+ .line-clamp__show-more-button:not(.line-clamp__show-more-button--inline) {
110
+ margin-top: 0.5em;
89
111
  }</style>
@@ -1,5 +1,4 @@
1
- <script lang="ts">import { Utils } from '../../core/utils';
2
- import { isScrollingPrevented } from './prevent-slider-scroll';
1
+ <script lang="ts">import { isScrollingPrevented } from './prevent-slider-scroll';
3
2
  import { onDestroy, onMount, untrack } from 'svelte';
4
3
  let { buffer, on, children } = $props();
5
4
  let slidesRef;
@@ -90,7 +89,28 @@ onMount(() => {
90
89
  }
91
90
  reset();
92
91
  });
93
- slidesRef.addEventListener('wheel', Utils.throttle((e) => {
92
+ let waveDetector = {
93
+ events: [],
94
+ direction: 0,
95
+ peakReached: false,
96
+ lastPeak: 0,
97
+ waveStartTime: 0
98
+ };
99
+ let isAnimatingWheel = false;
100
+ const triggerAnimation = (direction) => {
101
+ isAnimatingWheel = true;
102
+ if (direction > 0 && buffer.canLoadNext) {
103
+ buffer.loadNext();
104
+ }
105
+ else if (direction < 0 && buffer.canLoadPrevious) {
106
+ buffer.loadPrevious();
107
+ }
108
+ setTimeout(() => {
109
+ isAnimatingWheel = false;
110
+ }, buffer.animationDuration + 100);
111
+ };
112
+ slidesRef.addEventListener('wheel', (e) => {
113
+ e.preventDefault();
94
114
  const checkCanHandleWheel = (node) => {
95
115
  while (node && node !== slidesRef) {
96
116
  if (isScrollingPrevented(node)) {
@@ -103,13 +123,55 @@ onMount(() => {
103
123
  if (!checkCanHandleWheel(e.target)) {
104
124
  return;
105
125
  }
106
- if (e.deltaY > 0 && buffer.canLoadNext) {
107
- buffer.loadNext();
126
+ const now = Date.now();
127
+ const absDelta = Math.abs(e.deltaY);
128
+ const direction = Math.sign(e.deltaY);
129
+ // Mouse - large stable values, trigger immediately
130
+ if (absDelta >= 10 && !isAnimatingWheel) {
131
+ const lastEvent = waveDetector.events[waveDetector.events.length - 1];
132
+ const timeSinceLastEvent = lastEvent ? now - lastEvent.time : 1000;
133
+ // If enough time has passed since the last event - it's a mouse
134
+ if (timeSinceLastEvent > 100) {
135
+ triggerAnimation(direction);
136
+ waveDetector = { events: [], direction: 0, peakReached: false, lastPeak: 0, waveStartTime: 0 };
137
+ return;
138
+ }
108
139
  }
109
- if (e.deltaY < 0 && buffer.canLoadPrevious) {
110
- buffer.loadPrevious();
140
+ // Touchpad - small, variable values, need to analyze the wave
141
+ // New wave if: direction changed or a lot of time has passed
142
+ if (direction !== waveDetector.direction || (waveDetector.waveStartTime && now - waveDetector.waveStartTime > 1500)) {
143
+ // Finalize the previous wave if it existed
144
+ if (waveDetector.peakReached && !isAnimatingWheel) {
145
+ triggerAnimation(waveDetector.direction);
146
+ }
147
+ // Start a new wave
148
+ waveDetector = {
149
+ events: [{ delta: absDelta, time: now }],
150
+ direction: direction,
151
+ peakReached: false,
152
+ lastPeak: absDelta,
153
+ waveStartTime: now
154
+ };
155
+ return;
156
+ }
157
+ // Continue the current wave
158
+ waveDetector.events.push({ delta: absDelta, time: now });
159
+ // Determine the phase of the wave
160
+ if (absDelta > waveDetector.lastPeak) {
161
+ // The wave is growing
162
+ waveDetector.lastPeak = absDelta;
163
+ waveDetector.peakReached = absDelta >= 5; // The minimum peak to consider a valid wave
111
164
  }
112
- }, buffer.animationDuration + 250));
165
+ else if (absDelta < waveDetector.lastPeak * 0.5) {
166
+ // The wave has dropped significantly - consider the gesture complete
167
+ if (waveDetector.peakReached && !isAnimatingWheel) {
168
+ triggerAnimation(waveDetector.direction);
169
+ waveDetector = { events: [], direction: 0, peakReached: false, lastPeak: 0, waveStartTime: 0 };
170
+ }
171
+ }
172
+ // Cleanup old events
173
+ waveDetector.events = waveDetector.events.filter((evt) => now - evt.time < 2000);
174
+ });
113
175
  slidesRef.addEventListener('transitionend', (e) => {
114
176
  if (e.target !== slidesRef) {
115
177
  return;
@@ -142,7 +204,10 @@ const styles = $derived.by(() => {
142
204
  <div class="player-slider__slides" bind:this={slidesRef} style={styles}>
143
205
  {#each buffer.loaded as item, index (item)}
144
206
  <div class="player-slider__slide">
145
- {@render children({ item, active: index === activeIndex })}
207
+ {#if index >= activeIndex - 1 && index <= activeIndex + 1}
208
+ <!-- Only render the active slide and its immediate neighbors for performance -->
209
+ {@render children({ item, active: index === activeIndex })}
210
+ {/if}
146
211
  </div>
147
212
  {/each}
148
213
  </div>
@@ -22,10 +22,13 @@
22
22
  --_progress--height: var(--progress--height, 0.25em);
23
23
  --_progress--back-color: var(--progress--back-color, #b0b0b0);
24
24
  --_progress--front-color: var(--progress--front-color, #ffffff);
25
+ --_progress--box-shadow: var(--progress--box-shadow, 0 2px 3px rgba(0, 0, 0, 0.25) inset);
26
+ --_progress--border-radius: var(--progress--border-radius, 0);
25
27
  width: 100%;
26
28
  background: var(--_progress--back-color);
27
29
  height: var(--_progress--height);
28
- box-shadow: 0 2px 3px rgba(0, 0, 0, 0.25) inset;
30
+ box-shadow: var(--_progress--box-shadow);
31
+ border-radius: var(--_progress--border-radius);
29
32
  }
30
33
  .progress__value {
31
34
  background: var(--_progress--front-color);