@karnstack/kino 0.1.0 → 0.1.1
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.
- package/README.md +10 -0
- package/dist/{control-bar-DWzMIb23.js → control-bar-DrAeqaap.js} +18 -8
- package/dist/index.d.ts +7 -0
- package/dist/index.js +1 -1
- package/dist/mux.d.ts +3 -1
- package/dist/mux.js +7 -3
- package/dist/styles.css +12 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -57,6 +57,16 @@ Give the player a sized container. It fills `100%` width and height of its paren
|
|
|
57
57
|
|
|
58
58
|
kino is auth-agnostic. For signed playback you mint the `playback`, `thumbnail`, and `storyboard` tokens server-side and hand them to the player through the `tokens` prop. The player never holds a signing key and never talks to your auth layer; it only appends the tokens you give it to the media, thumbnail, and storyboard URLs. For public playback you can omit `tokens` entirely.
|
|
59
59
|
|
|
60
|
+
### Blur-up placeholder
|
|
61
|
+
|
|
62
|
+
Before the poster and first frame load, the video box is empty. Pass a small `placeholder` (a base64 data URI or a URL) and kino paints it behind the video as a blur-up; the sharp poster covers it once decoded, and it reappears briefly across source swaps.
|
|
63
|
+
|
|
64
|
+
```tsx
|
|
65
|
+
<MuxPlayer playbackId="..." placeholder={blurDataUrl} />
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
The poster itself stays the signed Mux thumbnail (kino derives it from `playbackId` + the `thumbnail` token), so `placeholder` is purely the instant low-res layer underneath.
|
|
69
|
+
|
|
60
70
|
## Theming
|
|
61
71
|
|
|
62
72
|
The quickest knob is the `accentColor` prop, which drives the scrubber fill, active menu items, and range controls.
|
|
@@ -403,7 +403,7 @@ function useIsCompact() {
|
|
|
403
403
|
return useContext(CompactContext);
|
|
404
404
|
}
|
|
405
405
|
const ControlsVisibilityContext = createContext(null);
|
|
406
|
-
function Player({ provider, accentColor, theme, className, children }) {
|
|
406
|
+
function Player({ provider, accentColor, theme, className, placeholder, children }) {
|
|
407
407
|
const wrapperRef = useRef(null);
|
|
408
408
|
const videoHostRef = useRef(null);
|
|
409
409
|
const hoveredRef = useRef(false);
|
|
@@ -496,13 +496,23 @@ function Player({ provider, accentColor, theme, className, children }) {
|
|
|
496
496
|
className: ["kino", className].filter(Boolean).join(" "),
|
|
497
497
|
style,
|
|
498
498
|
tabIndex: 0,
|
|
499
|
-
children: [
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
499
|
+
children: [
|
|
500
|
+
placeholder && /* @__PURE__ */ jsx("img", {
|
|
501
|
+
className: "kino-placeholder",
|
|
502
|
+
src: placeholder,
|
|
503
|
+
alt: "",
|
|
504
|
+
"aria-hidden": "true",
|
|
505
|
+
draggable: false
|
|
506
|
+
}),
|
|
507
|
+
/* @__PURE__ */ jsx("div", {
|
|
508
|
+
ref: videoHostRef,
|
|
509
|
+
className: "kino-video-host"
|
|
510
|
+
}),
|
|
511
|
+
/* @__PURE__ */ jsx(PlayerChrome, {
|
|
512
|
+
compact,
|
|
513
|
+
children
|
|
514
|
+
})
|
|
515
|
+
]
|
|
506
516
|
})
|
|
507
517
|
})
|
|
508
518
|
});
|
package/dist/index.d.ts
CHANGED
|
@@ -21,6 +21,12 @@ type PlayerProps = {
|
|
|
21
21
|
accentColor?: string;
|
|
22
22
|
theme?: Record<string, string>;
|
|
23
23
|
className?: string;
|
|
24
|
+
/**
|
|
25
|
+
* Low-res still (data URI or URL) painted behind the video while the poster
|
|
26
|
+
* and first frame load — a blur-up. The sharp poster covers it once decoded,
|
|
27
|
+
* so it only shows during the initial load and across source swaps.
|
|
28
|
+
*/
|
|
29
|
+
placeholder?: string;
|
|
24
30
|
children?: ReactNode;
|
|
25
31
|
};
|
|
26
32
|
declare function Player({
|
|
@@ -28,6 +34,7 @@ declare function Player({
|
|
|
28
34
|
accentColor,
|
|
29
35
|
theme,
|
|
30
36
|
className,
|
|
37
|
+
placeholder,
|
|
31
38
|
children
|
|
32
39
|
}: PlayerProps): import("react").JSX.Element;
|
|
33
40
|
declare namespace Player {
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { _ as usePlayer, a as SkipBackButton, c as Captions, d as Player, f as useControlsVisible, g as useMediaSelector, h as PlayerContext, i as PlayPauseButton, l as IdleOverlay, m as useWrapperRef, n as FullscreenButton, o as SkipForwardButton, p as useIsCompact, r as PipButton, s as VolumeControl, t as ControlBar, u as Scrubber, v as usePlayerActions, y as formatTime } from "./control-bar-
|
|
1
|
+
import { _ as usePlayer, a as SkipBackButton, c as Captions, d as Player, f as useControlsVisible, g as useMediaSelector, h as PlayerContext, i as PlayPauseButton, l as IdleOverlay, m as useWrapperRef, n as FullscreenButton, o as SkipForwardButton, p as useIsCompact, r as PipButton, s as VolumeControl, t as ControlBar, u as Scrubber, v as usePlayerActions, y as formatTime } from "./control-bar-DrAeqaap.js";
|
|
2
2
|
export { Captions, ControlBar, FullscreenButton, IdleOverlay, PipButton, PlayPauseButton, Player, PlayerContext, Scrubber, SkipBackButton, SkipForwardButton, VolumeControl, formatTime, useControlsVisible, useIsCompact, useMediaSelector, usePlayer, usePlayerActions, useWrapperRef };
|
package/dist/mux.d.ts
CHANGED
|
@@ -24,13 +24,15 @@ declare function createMuxProvider(opts: MuxProviderOptions): Provider;
|
|
|
24
24
|
type MuxPlayerProps = MuxProviderOptions & {
|
|
25
25
|
accentColor?: string;
|
|
26
26
|
theme?: Record<string, string>;
|
|
27
|
-
className?: string;
|
|
27
|
+
className?: string; /** Blur-up still painted behind the video until the poster/first frame loads. */
|
|
28
|
+
placeholder?: string;
|
|
28
29
|
children?: ReactNode;
|
|
29
30
|
};
|
|
30
31
|
declare function MuxPlayer({
|
|
31
32
|
accentColor,
|
|
32
33
|
theme,
|
|
33
34
|
className,
|
|
35
|
+
placeholder,
|
|
34
36
|
children,
|
|
35
37
|
...opts
|
|
36
38
|
}: MuxPlayerProps): import("react").JSX.Element;
|
package/dist/mux.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as Captions, d as Player, l as IdleOverlay, t as ControlBar } from "./control-bar-
|
|
1
|
+
import { c as Captions, d as Player, l as IdleOverlay, t as ControlBar } from "./control-bar-DrAeqaap.js";
|
|
2
2
|
import { useEffect, useRef } from "react";
|
|
3
3
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
4
|
import "@mux/mux-video";
|
|
@@ -275,7 +275,9 @@ function createMuxProvider(opts) {
|
|
|
275
275
|
if (el) el.currentTime = t;
|
|
276
276
|
},
|
|
277
277
|
setRate: (r) => {
|
|
278
|
-
if (el)
|
|
278
|
+
if (!el) return;
|
|
279
|
+
el.playbackRate = r;
|
|
280
|
+
el.defaultPlaybackRate = r;
|
|
279
281
|
},
|
|
280
282
|
setVolume: (v) => {
|
|
281
283
|
if (el) el.volume = Math.min(1, Math.max(0, v));
|
|
@@ -330,6 +332,7 @@ function createMuxProvider(opts) {
|
|
|
330
332
|
el.poster = opts.poster ?? buildImageUrl(opts.playbackId, "thumbnail", opts.tokens?.thumbnail);
|
|
331
333
|
if (opts.autoPlay) el.autoplay = true;
|
|
332
334
|
el.playbackRate = state.rate;
|
|
335
|
+
el.defaultPlaybackRate = state.rate;
|
|
333
336
|
if (opts.envKey) el.envKey = opts.envKey;
|
|
334
337
|
if (opts.metadata) el.metadata = {
|
|
335
338
|
video_id: opts.metadata.videoId,
|
|
@@ -399,7 +402,7 @@ function createMuxProvider(opts) {
|
|
|
399
402
|
}
|
|
400
403
|
//#endregion
|
|
401
404
|
//#region src/mux/mux-player.tsx
|
|
402
|
-
function MuxPlayer({ accentColor, theme, className, children, ...opts }) {
|
|
405
|
+
function MuxPlayer({ accentColor, theme, className, placeholder, children, ...opts }) {
|
|
403
406
|
const providerRef = useRef(null);
|
|
404
407
|
if (providerRef.current === null) providerRef.current = createMuxProvider(opts);
|
|
405
408
|
const provider = providerRef.current;
|
|
@@ -427,6 +430,7 @@ function MuxPlayer({ accentColor, theme, className, children, ...opts }) {
|
|
|
427
430
|
accentColor,
|
|
428
431
|
theme,
|
|
429
432
|
className,
|
|
433
|
+
placeholder,
|
|
430
434
|
children: [
|
|
431
435
|
/* @__PURE__ */ jsx(IdleOverlay, {}),
|
|
432
436
|
/* @__PURE__ */ jsx(Captions, {}),
|
package/dist/styles.css
CHANGED
|
@@ -34,6 +34,18 @@
|
|
|
34
34
|
width: 100%;
|
|
35
35
|
height: 100%;
|
|
36
36
|
}
|
|
37
|
+
.kino .kino-placeholder {
|
|
38
|
+
position: absolute;
|
|
39
|
+
inset: 0;
|
|
40
|
+
width: 100%;
|
|
41
|
+
height: 100%;
|
|
42
|
+
object-fit: cover;
|
|
43
|
+
/* Same level as the video host but earlier in the DOM, so the video element
|
|
44
|
+
(and its sharp poster, once decoded) paints over this blur-up. */
|
|
45
|
+
z-index: 0;
|
|
46
|
+
pointer-events: none;
|
|
47
|
+
user-select: none;
|
|
48
|
+
}
|
|
37
49
|
.kino .kino-video-host {
|
|
38
50
|
position: absolute;
|
|
39
51
|
inset: 0;
|