@streamscloud/kit 0.10.7-1781475571897 → 0.10.7-1781507721211

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.
@@ -4,14 +4,13 @@ import { PlaybackManager } from '../media-playback';
4
4
  import { Carousel } from '../player/carousel';
5
5
  import { ProportionalContainer } from '../proportional-container';
6
6
  import { SeekBar } from '../seek-bar';
7
- import { default as VideoPlayer } from './cmp.video-player.svelte';
7
+ import VideoPlayer from './video-player.svelte';
8
8
  import IconImageOff from '@fluentui/svg-icons/icons/image_off_20_regular.svg?raw';
9
9
  const { items, aspectRatio = 'vertical', objectFit = 'contain', showSeekBar = true, duration } = $props();
10
10
  let currentIndex = $state(0);
11
11
  let currentTime = $state(0);
12
12
  let mediaDuration = $state(NaN);
13
13
  let activePlayerId = $state.raw(null);
14
- const hasPlayable = $derived(items.some((item) => item.playable));
15
14
  const isCurrentPlayable = $derived(items[currentIndex]?.playable === true);
16
15
  const progress = $derived(mediaDuration ? currentTime / mediaDuration : 0);
17
16
  const onPlayerTimeUpdate = (t) => (currentTime = t);
@@ -52,6 +51,7 @@ const onCarouselIndexChanged = (index) => {
52
51
  {#if items[0].playable}
53
52
  <VideoPlayer
54
53
  src={items[0].url}
54
+ poster={items[0].cover}
55
55
  active={true}
56
56
  on={{ timeUpdate: onPlayerTimeUpdate, durationChange: onPlayerDurationChange, activate: onPlayerActivate }} />
57
57
  {:else}
@@ -65,6 +65,7 @@ const onCarouselIndexChanged = (index) => {
65
65
  {#if item.playable}
66
66
  <VideoPlayer
67
67
  src={item.url}
68
+ poster={item.cover}
68
69
  active={item === items[currentIndex]}
69
70
  on={{ timeUpdate: onPlayerTimeUpdate, durationChange: onPlayerDurationChange, activate: onPlayerActivate }} />
70
71
  {:else}
@@ -82,7 +83,7 @@ const onCarouselIndexChanged = (index) => {
82
83
  </ProportionalContainer>
83
84
  </div>
84
85
 
85
- {#if showSeekBar && hasPlayable}
86
+ {#if showSeekBar}
86
87
  <div class="seek-bar-section">
87
88
  <div class="seek-bar-section__content">
88
89
  <div class="seek-bar-section__bar" class:seek-bar-section__bar--hidden={!isCurrentPlayable}>
@@ -95,9 +96,9 @@ const onCarouselIndexChanged = (index) => {
95
96
  <!--
96
97
  @component
97
98
  Media slot for `GridCard`. Renders an empty placeholder, a single `Image` / `VideoPlayer`, or
98
- a `Carousel` of mixed image / video items. Seek-bar appears below the media when any item is
99
- playable; in a carousel it's hidden via `visibility: hidden` when the current slide is an
100
- image (preserves card height). Optional `duration` overlay renders bottom-right.
99
+ a `Carousel` of mixed image / video items. Seek-bar renders below the media whenever `showSeekBar`
100
+ (default true); the bar itself is hidden via `visibility: hidden` when the current item isn't
101
+ playable (preserves card height). Optional `duration` overlay renders bottom-right.
101
102
 
102
103
  ### CSS Custom Properties
103
104
  | Property | Description | Default |
@@ -2,6 +2,8 @@ import type { AspectRatio, ObjectFit } from './types';
2
2
  export type MediaItem = {
3
3
  url: string;
4
4
  playable?: boolean;
5
+ /** Poster shown for a playable item before playback; falls back to the video's first frame. */
6
+ cover?: string;
5
7
  };
6
8
  type Props = {
7
9
  items: MediaItem[];
@@ -16,9 +18,9 @@ type Props = {
16
18
  };
17
19
  /**
18
20
  * Media slot for `GridCard`. Renders an empty placeholder, a single `Image` / `VideoPlayer`, or
19
- * a `Carousel` of mixed image / video items. Seek-bar appears below the media when any item is
20
- * playable; in a carousel it's hidden via `visibility: hidden` when the current slide is an
21
- * image (preserves card height). Optional `duration` overlay renders bottom-right.
21
+ * a `Carousel` of mixed image / video items. Seek-bar renders below the media whenever `showSeekBar`
22
+ * (default true); the bar itself is hidden via `visibility: hidden` when the current item isn't
23
+ * playable (preserves card height). Optional `duration` overlay renders bottom-right.
22
24
  *
23
25
  * ### CSS Custom Properties
24
26
  * | Property | Description | Default |
@@ -3,8 +3,8 @@ export {};
3
3
  </script>
4
4
 
5
5
  <div class="grid-card-field" class:grid-card-field--multiline={multiline} class:grid-card-field--vertical={vertical}>
6
- <span class="grid-card-field__label">{label}</span>
7
- <div class="grid-card-field__content">
6
+ <span class="grid-card-field__label" class:grid-card-field__label--vertical={vertical}>{label}</span>
7
+ <div class="grid-card-field__content" class:grid-card-field__content--multiline={multiline} class:grid-card-field__content--vertical={vertical}>
8
8
  {@render children()}
9
9
  </div>
10
10
  </div>
@@ -43,9 +43,6 @@ content; set `vertical` to stack the label above the content (escapes the subgri
43
43
  grid-row-gap: 0.25rem;
44
44
  padding: var(--_gcf--padding-block) var(--_gcf--padding-inline);
45
45
  }
46
- .grid-card-field--vertical .grid-card-field__label, .grid-card-field--vertical .grid-card-field__content {
47
- padding: 0;
48
- }
49
46
  .grid-card-field__label {
50
47
  font-size: 0.625rem;
51
48
  color: var(--sc-kit--color--text--secondary);
@@ -54,8 +51,19 @@ content; set `vertical` to stack the label above the content (escapes the subgri
54
51
  white-space: nowrap;
55
52
  line-height: var(--sc-kit--leading--tight);
56
53
  }
54
+ .grid-card-field__label--vertical {
55
+ padding: 0;
56
+ }
57
57
  .grid-card-field__content {
58
+ display: flex;
59
+ align-items: center;
58
60
  padding-block: var(--_gcf--padding-block);
59
61
  padding-inline-end: var(--_gcf--padding-inline);
60
62
  min-width: 0;
63
+ }
64
+ .grid-card-field__content--multiline {
65
+ align-items: flex-start;
66
+ }
67
+ .grid-card-field__content--vertical {
68
+ padding: 0;
61
69
  }</style>
@@ -4,7 +4,7 @@ import { PlaybackManager } from '../media-playback';
4
4
  import IconPause from '@fluentui/svg-icons/icons/pause_20_regular.svg?raw';
5
5
  import IconPlay from '@fluentui/svg-icons/icons/play_20_regular.svg?raw';
6
6
  import { untrack } from 'svelte';
7
- const { src, active, on } = $props();
7
+ const { src, poster, active, on } = $props();
8
8
  const id = randomNanoid();
9
9
  let videoEl = $state(null);
10
10
  let currentTime = $state(0);
@@ -115,6 +115,7 @@ export const seekTo = (time) => {
115
115
  <video
116
116
  bind:this={videoEl}
117
117
  src={src}
118
+ poster={poster}
118
119
  controls={false}
119
120
  preload="auto"
120
121
  ontimeupdate={onTimeUpdate}
@@ -1,5 +1,7 @@
1
1
  type Props = {
2
2
  src: string;
3
+ /** Poster image shown before playback; falls back to the video's first frame when omitted. */
4
+ poster?: string;
3
5
  /**
4
6
  * When `true`, the player re-publishes its current `currentTime` / `duration` upward via
5
7
  * `on.timeUpdate` / `on.durationChange` so the parent can read this slide's state on
@@ -19,8 +21,8 @@ type Props = {
19
21
  * with the global `PlaybackManager` so only one player can play at a time. Exposes `seekTo(t)`
20
22
  * via `bind:this` for parent seek-bar sync. Not exported standalone — use `GridCardMedia`.
21
23
  */
22
- declare const Cmp: import("svelte").Component<Props, {
24
+ declare const VideoPlayer: import("svelte").Component<Props, {
23
25
  seekTo: (time: number) => void;
24
26
  }, "">;
25
- type Cmp = ReturnType<typeof Cmp>;
26
- export default Cmp;
27
+ type VideoPlayer = ReturnType<typeof VideoPlayer>;
28
+ export default VideoPlayer;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@streamscloud/kit",
3
- "version": "0.10.7-1781475571897",
3
+ "version": "0.10.7-1781507721211",
4
4
  "author": "StreamsCloud",
5
5
  "repository": {
6
6
  "type": "git",