@rixl/media-vue 1.0.2 → 1.1.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.
- package/README.md +98 -14
- package/dist/components/feed/feed.js +1 -93
- package/dist/components/image/image.js +1 -71
- package/dist/components/video/video-player.js +1 -14
- package/dist/components/video/video-props.js +1 -82
- package/dist/components/video/video.js +1 -70
- package/dist/core.js +1 -1
- package/dist/feed.js +1 -3
- package/dist/image.js +1 -3
- package/dist/index.js +1 -9
- package/dist/lib/element-props.js +1 -10
- package/dist/lib/player-scope.js +2 -21
- package/dist/video.js +1 -5
- package/package.json +10 -9
package/README.md
CHANGED
|
@@ -1,36 +1,120 @@
|
|
|
1
1
|
# Rixl Media SDK for Vue
|
|
2
2
|
|
|
3
|
-
Vue 3
|
|
3
|
+
Vue 3 video player, image components, and infinite media feeds for Rixl. `@rixl/media-vue` provides typed Vue props, events, refs, and player context over the shared Rixl media UI.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
[Documentation](https://developers.rixl.com/en/sdk/media-vue) · [npm](https://www.npmjs.com/package/@rixl/media-vue) · [Dashboard](https://dash.rixl.com)
|
|
6
|
+
|
|
7
|
+
## What you get
|
|
8
|
+
|
|
9
|
+
- Adaptive HLS playback, captions, quality selection, fullscreen, and picture-in-picture.
|
|
10
|
+
- Images with lazy loading and ThumbHash placeholders when available.
|
|
11
|
+
- Vertical media feeds with pagination, looping, and automatic advancement.
|
|
12
|
+
- Vue events and `v-model:muted` support for feeds.
|
|
13
|
+
- Included player styles; no Tailwind CSS or custom-element compiler configuration is required.
|
|
14
|
+
|
|
15
|
+
## Install
|
|
6
16
|
|
|
7
17
|
```sh
|
|
8
18
|
npm install @rixl/media-vue
|
|
9
19
|
```
|
|
10
20
|
|
|
11
|
-
|
|
21
|
+
Requires Vue 3.3 or later. Core and Lit are included as dependencies.
|
|
22
|
+
|
|
23
|
+
## Quick start
|
|
24
|
+
|
|
25
|
+
Wait for the SDK connection before rendering media. Replace the API key and media ID with your Rixl values.
|
|
12
26
|
|
|
13
27
|
```vue
|
|
14
28
|
<script setup lang="ts">
|
|
15
|
-
import {onMounted} from "vue";
|
|
29
|
+
import {onMounted, ref} from "vue";
|
|
16
30
|
import {connect} from "@rixl/media-vue/core";
|
|
17
|
-
import {
|
|
31
|
+
import {Video} from "@rixl/media-vue/video";
|
|
32
|
+
|
|
33
|
+
const ready = ref(false);
|
|
34
|
+
const error = ref("");
|
|
18
35
|
|
|
19
36
|
onMounted(async () => {
|
|
20
|
-
|
|
37
|
+
try {
|
|
38
|
+
await connect({baseUrl: "https://api.rixl.com", apiKey: "YOUR_PUBLIC_API_KEY"});
|
|
39
|
+
ready.value = true;
|
|
40
|
+
} catch {
|
|
41
|
+
error.value = "Unable to connect to Rixl.";
|
|
42
|
+
}
|
|
21
43
|
});
|
|
22
44
|
</script>
|
|
23
45
|
|
|
24
46
|
<template>
|
|
25
|
-
<
|
|
26
|
-
<Video
|
|
27
|
-
<
|
|
47
|
+
<p v-if="error" role="alert">{{ error }}</p>
|
|
48
|
+
<Video v-else-if="ready" id="YOUR_VIDEO_ID" :muted="true" class="player" />
|
|
49
|
+
<p v-else role="status">Loading media…</p>
|
|
50
|
+
</template>
|
|
51
|
+
|
|
52
|
+
<style scoped>
|
|
53
|
+
.player {
|
|
54
|
+
display: block;
|
|
55
|
+
width: 100%;
|
|
56
|
+
aspect-ratio: 16 / 9;
|
|
57
|
+
}
|
|
58
|
+
</style>
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Use credentials intended for browser access. If your application already authenticates the shared `@rixl/sdk` client, reuse that connection instead.
|
|
62
|
+
|
|
63
|
+
## Images and feeds
|
|
64
|
+
|
|
65
|
+
After connecting, import the components you need:
|
|
66
|
+
|
|
67
|
+
```vue
|
|
68
|
+
<script setup lang="ts">
|
|
69
|
+
import {ref} from "vue";
|
|
70
|
+
import {Image} from "@rixl/media-vue/image";
|
|
71
|
+
import {Feed} from "@rixl/media-vue/feed";
|
|
72
|
+
|
|
73
|
+
const muted = ref(true);
|
|
74
|
+
</script>
|
|
75
|
+
|
|
76
|
+
<template>
|
|
77
|
+
<Image id="YOUR_IMAGE_ID" alt="Mountain lake at sunrise" class="image" />
|
|
78
|
+
<Feed feedId="YOUR_FEED_ID" v-model:muted="muted" class="feed" />
|
|
28
79
|
</template>
|
|
80
|
+
|
|
81
|
+
<style scoped>
|
|
82
|
+
.image {
|
|
83
|
+
display: block;
|
|
84
|
+
width: 100%;
|
|
85
|
+
aspect-ratio: 16 / 9;
|
|
86
|
+
}
|
|
87
|
+
.feed {
|
|
88
|
+
display: block;
|
|
89
|
+
height: 36rem;
|
|
90
|
+
}
|
|
91
|
+
</style>
|
|
29
92
|
```
|
|
30
93
|
|
|
31
|
-
|
|
94
|
+
Production media is resolved by `id` or `feedId` through the SDK.
|
|
95
|
+
|
|
96
|
+
## Events and custom controls
|
|
97
|
+
|
|
98
|
+
Video emits `play`, `pause`, `ended`, `pausedChange`, `loadingChange`, `timeUpdate`, `loadedMetadata`, `volumeChange`, `rateChange`, `qualityChange`, and `error`. Image emits `loadingChange`; Feed emits `muteChange` and `update:muted`.
|
|
99
|
+
|
|
100
|
+
```vue
|
|
101
|
+
<Video id="YOUR_VIDEO_ID" @paused-change="(paused) => console.log(paused)" />
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Use a component template ref to access its exposed `element`, the underlying Lit element. `<VideoPlayer>` shares a player scope with sibling controls; `usePlayerId()` and `useOptionalPlayerId()` are available from `/video` during setup. Playback actions and state live in `/core`.
|
|
105
|
+
|
|
106
|
+
## Styling, rendering, and imports
|
|
107
|
+
|
|
108
|
+
The wrappers include Lit's styles inside shadow DOM. Your `class` and `style` affect the host layout; internal player controls are configured through component props.
|
|
109
|
+
|
|
110
|
+
The examples target browser rendering. In a Nuxt app, mount media inside a client-only boundary and initialize the SDK there. Full server-rendered media markup is not provided by this adapter.
|
|
111
|
+
|
|
112
|
+
| Import | Exports |
|
|
113
|
+
| ----------------------- | ------------------------------------------------------------- |
|
|
114
|
+
| `@rixl/media-vue/image` | `Image`, `ImageProps` |
|
|
115
|
+
| `@rixl/media-vue/video` | `Video`, `VideoPlayer`, props, and player-context composables |
|
|
116
|
+
| `@rixl/media-vue/feed` | `Feed`, `FeedProps` |
|
|
117
|
+
| `@rixl/media-vue/core` | Headless APIs, stores, utilities, and types |
|
|
118
|
+
| `@rixl/media-vue` | Components and Core exports |
|
|
32
119
|
|
|
33
|
-
|
|
34
|
-
- `@rixl/media-vue/image` — `<Image>` component
|
|
35
|
-
- `@rixl/media-vue/video` — `<Video>` and `<VideoPlayer>` components
|
|
36
|
-
- `@rixl/media-vue/feed` — `<Feed>` component
|
|
120
|
+
Subpath imports keep an image-only app free of video, feed, and HLS code. See the [Vue guide](https://developers.rixl.com/en/sdk/media-vue) for integration details.
|
|
@@ -1,93 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import "@rixl/media-lit/feed";
|
|
3
|
-
import { defineComponent, h, ref } from "vue";
|
|
4
|
-
|
|
5
|
-
// src/components/feed/feed.ts
|
|
6
|
-
const Feed = defineComponent({
|
|
7
|
-
name: "RixlFeed",
|
|
8
|
-
props: {
|
|
9
|
-
feedId: {
|
|
10
|
-
type: String,
|
|
11
|
-
default: ""
|
|
12
|
-
},
|
|
13
|
-
lang: {
|
|
14
|
-
type: String,
|
|
15
|
-
default: "en"
|
|
16
|
-
},
|
|
17
|
-
feedFont: {
|
|
18
|
-
type: String,
|
|
19
|
-
default: void 0
|
|
20
|
-
},
|
|
21
|
-
loop: {
|
|
22
|
-
type: Boolean,
|
|
23
|
-
default: false
|
|
24
|
-
},
|
|
25
|
-
autoscroll: {
|
|
26
|
-
type: Boolean,
|
|
27
|
-
default: false
|
|
28
|
-
},
|
|
29
|
-
muted: {
|
|
30
|
-
type: Boolean,
|
|
31
|
-
default: void 0
|
|
32
|
-
},
|
|
33
|
-
analytics: {
|
|
34
|
-
type: Boolean,
|
|
35
|
-
default: void 0
|
|
36
|
-
},
|
|
37
|
-
analyticsPage: {
|
|
38
|
-
type: String,
|
|
39
|
-
default: void 0
|
|
40
|
-
},
|
|
41
|
-
safeAreaTabBar: {
|
|
42
|
-
type: Number,
|
|
43
|
-
default: void 0
|
|
44
|
-
},
|
|
45
|
-
posts: {
|
|
46
|
-
type: Array,
|
|
47
|
-
default: void 0
|
|
48
|
-
},
|
|
49
|
-
initialIndex: {
|
|
50
|
-
type: Number,
|
|
51
|
-
default: void 0
|
|
52
|
-
},
|
|
53
|
-
onFetchMore: {
|
|
54
|
-
type: Function,
|
|
55
|
-
default: void 0
|
|
56
|
-
}
|
|
57
|
-
},
|
|
58
|
-
emits: {
|
|
59
|
-
muteChange: (_muted) => true,
|
|
60
|
-
"update:muted": (_muted) => true
|
|
61
|
-
},
|
|
62
|
-
setup(props, { attrs, emit, expose }) {
|
|
63
|
-
const element = ref(null);
|
|
64
|
-
expose({ element });
|
|
65
|
-
function handleMuteChange(event) {
|
|
66
|
-
if (event instanceof CustomEvent && typeof event.detail?.muted === "boolean") {
|
|
67
|
-
emit("muteChange", event.detail.muted);
|
|
68
|
-
emit("update:muted", event.detail.muted);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
return () => h("rixl-feed", {
|
|
72
|
-
...attrs,
|
|
73
|
-
ref: element,
|
|
74
|
-
...omitUndefined({
|
|
75
|
-
feedId: props.feedId,
|
|
76
|
-
lang: props.lang,
|
|
77
|
-
feedFont: props.feedFont,
|
|
78
|
-
loop: props.loop,
|
|
79
|
-
autoscroll: props.autoscroll,
|
|
80
|
-
muted: props.muted,
|
|
81
|
-
analytics: props.analytics,
|
|
82
|
-
analyticsPage: props.analyticsPage,
|
|
83
|
-
safeAreaTabBar: props.safeAreaTabBar,
|
|
84
|
-
posts: props.posts,
|
|
85
|
-
initialIndex: props.initialIndex,
|
|
86
|
-
onFetchMore: props.onFetchMore
|
|
87
|
-
}),
|
|
88
|
-
"onMute-change": handleMuteChange
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
export { Feed };
|
|
1
|
+
import{omitUndefined as e}from"../../lib/element-props.js";import"@rixl/media-lit/feed";import{defineComponent as t,h as n,ref as r}from"vue";const i=t({name:`RixlFeed`,props:{feedId:{type:String,default:``},lang:{type:String,default:`en`},feedFont:{type:String,default:void 0},loop:{type:Boolean,default:!1},autoscroll:{type:Boolean,default:!1},muted:{type:Boolean,default:void 0},analytics:{type:Boolean,default:void 0},analyticsPage:{type:String,default:void 0},safeAreaTabBar:{type:Number,default:void 0},posts:{type:Array,default:void 0},initialIndex:{type:Number,default:void 0},onFetchMore:{type:Function,default:void 0}},emits:{muteChange:e=>!0,"update:muted":e=>!0},setup(t,{attrs:i,emit:a,expose:o}){let s=r(null);o({element:s});function c(e){e instanceof CustomEvent&&typeof e.detail?.muted==`boolean`&&(a(`muteChange`,e.detail.muted),a(`update:muted`,e.detail.muted))}return()=>n(`rixl-feed`,{...i,ref:s,...e({feedId:t.feedId,lang:t.lang,feedFont:t.feedFont,loop:t.loop,autoscroll:t.autoscroll,muted:t.muted,analytics:t.analytics,analyticsPage:t.analyticsPage,safeAreaTabBar:t.safeAreaTabBar,posts:t.posts,initialIndex:t.initialIndex,onFetchMore:t.onFetchMore}),"onMute-change":c})}});export{i as Feed};
|
|
@@ -1,71 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { defineComponent, h, ref } from "vue";
|
|
3
|
-
import "@rixl/media-lit/image";
|
|
4
|
-
|
|
5
|
-
// src/components/image/image.ts
|
|
6
|
-
function resolveIsCurrent(isCurrent, id) {
|
|
7
|
-
if (isCurrent !== void 0) return isCurrent;
|
|
8
|
-
return id ? true : void 0;
|
|
9
|
-
}
|
|
10
|
-
const Image = defineComponent({
|
|
11
|
-
name: "RixlImage",
|
|
12
|
-
props: {
|
|
13
|
-
id: {
|
|
14
|
-
type: String,
|
|
15
|
-
default: void 0
|
|
16
|
-
},
|
|
17
|
-
imageData: {
|
|
18
|
-
type: Object,
|
|
19
|
-
default: void 0
|
|
20
|
-
},
|
|
21
|
-
alt: {
|
|
22
|
-
type: String,
|
|
23
|
-
default: void 0
|
|
24
|
-
},
|
|
25
|
-
analytics: {
|
|
26
|
-
type: Boolean,
|
|
27
|
-
default: true
|
|
28
|
-
},
|
|
29
|
-
analyticsPage: {
|
|
30
|
-
type: String,
|
|
31
|
-
default: "standalone"
|
|
32
|
-
},
|
|
33
|
-
isCurrent: {
|
|
34
|
-
type: Boolean,
|
|
35
|
-
default: void 0
|
|
36
|
-
},
|
|
37
|
-
feedId: {
|
|
38
|
-
type: String,
|
|
39
|
-
default: void 0
|
|
40
|
-
},
|
|
41
|
-
postId: {
|
|
42
|
-
type: String,
|
|
43
|
-
default: void 0
|
|
44
|
-
}
|
|
45
|
-
},
|
|
46
|
-
emits: { loadingChange: (_isLoading) => true },
|
|
47
|
-
setup(props, { attrs, emit, expose }) {
|
|
48
|
-
const element = ref(null);
|
|
49
|
-
expose({ element });
|
|
50
|
-
function handleLoadingChange(event) {
|
|
51
|
-
if (event instanceof CustomEvent && typeof event.detail === "boolean") emit("loadingChange", event.detail);
|
|
52
|
-
}
|
|
53
|
-
return () => h("rixl-image", {
|
|
54
|
-
...attrs,
|
|
55
|
-
ref: element,
|
|
56
|
-
...omitUndefined({
|
|
57
|
-
imageId: props.id,
|
|
58
|
-
imageData: props.imageData,
|
|
59
|
-
alt: props.alt,
|
|
60
|
-
analytics: props.analytics,
|
|
61
|
-
analyticsPage: props.analyticsPage,
|
|
62
|
-
isCurrent: resolveIsCurrent(props.isCurrent, props.id),
|
|
63
|
-
feedId: props.feedId,
|
|
64
|
-
postId: props.postId
|
|
65
|
-
}),
|
|
66
|
-
"onLoading-change": handleLoadingChange
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
export { Image };
|
|
1
|
+
import{omitUndefined as e}from"../../lib/element-props.js";import{defineComponent as t,h as n,ref as r}from"vue";import"@rixl/media-lit/image";function i(e,t){return e===void 0?t?!0:void 0:e}const a=t({name:`RixlImage`,props:{id:{type:String,default:void 0},imageData:{type:Object,default:void 0},alt:{type:String,default:void 0},analytics:{type:Boolean,default:!0},analyticsPage:{type:String,default:`standalone`},isCurrent:{type:Boolean,default:void 0},feedId:{type:String,default:void 0},postId:{type:String,default:void 0}},emits:{loadingChange:e=>!0},setup(t,{attrs:a,emit:o,expose:s}){let c=r(null);s({element:c});function l(e){e instanceof CustomEvent&&typeof e.detail==`boolean`&&o(`loadingChange`,e.detail)}return()=>n(`rixl-image`,{...a,ref:c,...e({imageId:t.id,imageData:t.imageData,alt:t.alt,analytics:t.analytics,analyticsPage:t.analyticsPage,isCurrent:i(t.isCurrent,t.id),feedId:t.feedId,postId:t.postId}),"onLoading-change":l})}});export{a as Image};
|
|
@@ -1,14 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { defineComponent } from "vue";
|
|
3
|
-
|
|
4
|
-
// src/components/video/video-player.ts
|
|
5
|
-
const VideoPlayer = defineComponent({
|
|
6
|
-
name: "RixlVideoPlayer",
|
|
7
|
-
setup(_props, { slots }) {
|
|
8
|
-
const playerId = crypto.randomUUID();
|
|
9
|
-
providePlayerScope(playerId);
|
|
10
|
-
return () => slots.default?.() ?? null;
|
|
11
|
-
}
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
export { VideoPlayer };
|
|
1
|
+
import{providePlayerScope as e}from"../../lib/player-scope.js";import{defineComponent as t}from"vue";const n=t({name:`RixlVideoPlayer`,setup(t,{slots:n}){let r=crypto.randomUUID();return e(r),()=>n.default?.()??null}});export{n as VideoPlayer};
|
|
@@ -1,82 +1 @@
|
|
|
1
|
-
|
|
2
|
-
const optionalBoolean = {
|
|
3
|
-
type: Boolean,
|
|
4
|
-
default: void 0
|
|
5
|
-
};
|
|
6
|
-
const optionalString = {
|
|
7
|
-
type: String,
|
|
8
|
-
default: void 0
|
|
9
|
-
};
|
|
10
|
-
const optionalNumber = {
|
|
11
|
-
type: Number,
|
|
12
|
-
default: void 0
|
|
13
|
-
};
|
|
14
|
-
const videoPropDefinitions = {
|
|
15
|
-
id: optionalString,
|
|
16
|
-
src: optionalString,
|
|
17
|
-
videoData: {
|
|
18
|
-
type: Object,
|
|
19
|
-
default: void 0
|
|
20
|
-
},
|
|
21
|
-
autoPlay: optionalBoolean,
|
|
22
|
-
muted: optionalBoolean,
|
|
23
|
-
loop: optionalBoolean,
|
|
24
|
-
playsInline: optionalBoolean,
|
|
25
|
-
poster: optionalString,
|
|
26
|
-
thumbhash: optionalString,
|
|
27
|
-
volume: optionalNumber,
|
|
28
|
-
progressBar: optionalBoolean,
|
|
29
|
-
heatmap: optionalBoolean,
|
|
30
|
-
chapters: optionalBoolean,
|
|
31
|
-
heatmapData: {
|
|
32
|
-
type: Object,
|
|
33
|
-
default: void 0
|
|
34
|
-
},
|
|
35
|
-
controls: optionalBoolean,
|
|
36
|
-
hideUI: optionalBoolean,
|
|
37
|
-
settingsOpen: optionalBoolean,
|
|
38
|
-
theme: {
|
|
39
|
-
type: String,
|
|
40
|
-
default: void 0
|
|
41
|
-
},
|
|
42
|
-
autoHideMs: optionalNumber,
|
|
43
|
-
allowPlayPause: optionalBoolean,
|
|
44
|
-
allowFullscreen: optionalBoolean,
|
|
45
|
-
allowPictureInPicture: optionalBoolean,
|
|
46
|
-
soundDisabled: optionalBoolean,
|
|
47
|
-
resumeProgress: optionalBoolean,
|
|
48
|
-
isCurrent: optionalBoolean,
|
|
49
|
-
isFeed: optionalBoolean,
|
|
50
|
-
loadState: {
|
|
51
|
-
type: String,
|
|
52
|
-
default: void 0
|
|
53
|
-
},
|
|
54
|
-
dataPost: {
|
|
55
|
-
type: Object,
|
|
56
|
-
default: void 0
|
|
57
|
-
},
|
|
58
|
-
feedFont: {
|
|
59
|
-
type: String,
|
|
60
|
-
default: void 0
|
|
61
|
-
},
|
|
62
|
-
feedId: optionalString,
|
|
63
|
-
postId: optionalString,
|
|
64
|
-
analytics: optionalBoolean,
|
|
65
|
-
analyticsPage: {
|
|
66
|
-
type: String,
|
|
67
|
-
default: void 0
|
|
68
|
-
},
|
|
69
|
-
lang: optionalString,
|
|
70
|
-
planType: {
|
|
71
|
-
type: String,
|
|
72
|
-
default: void 0
|
|
73
|
-
},
|
|
74
|
-
userId: optionalString,
|
|
75
|
-
userProperties: {
|
|
76
|
-
type: Object,
|
|
77
|
-
default: void 0
|
|
78
|
-
},
|
|
79
|
-
hotSegments: optionalBoolean
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
export { videoPropDefinitions };
|
|
1
|
+
const e={type:Boolean,default:void 0},t={type:String,default:void 0},n={type:Number,default:void 0},r={id:t,src:t,videoData:{type:Object,default:void 0},autoPlay:e,muted:e,loop:e,playsInline:e,poster:t,thumbhash:t,volume:n,progressBar:e,heatmap:e,chapters:e,heatmapData:{type:Object,default:void 0},controls:e,hideUI:e,settingsOpen:e,theme:{type:String,default:void 0},autoHideMs:n,allowPlayPause:e,allowFullscreen:e,allowPictureInPicture:e,soundDisabled:e,resumeProgress:e,isCurrent:e,isFeed:e,loadState:{type:String,default:void 0},dataPost:{type:Object,default:void 0},feedFont:{type:String,default:void 0},feedId:t,postId:t,analytics:e,analyticsPage:{type:String,default:void 0},lang:t,planType:{type:String,default:void 0},userId:t,userProperties:{type:Object,default:void 0},hotSegments:e};export{r as videoPropDefinitions};
|
|
@@ -1,70 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { providePlayerScope, useOptionalPlayerId } from "../../lib/player-scope.js";
|
|
3
|
-
import { videoPropDefinitions } from "./video-props.js";
|
|
4
|
-
import { defineComponent, h, ref } from "vue";
|
|
5
|
-
import "@rixl/media-lit/video";
|
|
6
|
-
|
|
7
|
-
// src/components/video/video.ts
|
|
8
|
-
const videoEmits = {
|
|
9
|
-
play: (_event) => true,
|
|
10
|
-
pause: (_event) => true,
|
|
11
|
-
pausedChange: (_isPaused) => true,
|
|
12
|
-
ended: () => true,
|
|
13
|
-
timeUpdate: (_event) => true,
|
|
14
|
-
loadedMetadata: (_event) => true,
|
|
15
|
-
error: (_event) => true,
|
|
16
|
-
volumeChange: (_event) => true,
|
|
17
|
-
loadingChange: (_isLoading) => true,
|
|
18
|
-
rateChange: (_event) => true,
|
|
19
|
-
qualityChange: (_event) => true
|
|
20
|
-
};
|
|
21
|
-
function buildVideoEventListeners(emit) {
|
|
22
|
-
return {
|
|
23
|
-
onPlay: (event) => emit("play", event),
|
|
24
|
-
onPause: (event) => emit("pause", event),
|
|
25
|
-
"onPaused-change": (event) => {
|
|
26
|
-
const detail = event.detail;
|
|
27
|
-
emit("pausedChange", detail.paused);
|
|
28
|
-
},
|
|
29
|
-
onEnded: () => emit("ended"),
|
|
30
|
-
onTimeupdate: (event) => emit("timeUpdate", event),
|
|
31
|
-
"onLoaded-metadata": (event) => emit("loadedMetadata", event),
|
|
32
|
-
onError: (event) => emit("error", event),
|
|
33
|
-
"onVolume-change": (event) => emit("volumeChange", event),
|
|
34
|
-
"onLoading-change": (event) => {
|
|
35
|
-
const detail = event.detail;
|
|
36
|
-
emit("loadingChange", detail.loading);
|
|
37
|
-
},
|
|
38
|
-
"onRate-change": (event) => emit("rateChange", event),
|
|
39
|
-
"onQuality-change": (event) => emit("qualityChange", event)
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
function mapVideoElementProps(props, playerId) {
|
|
43
|
-
const { id, chapters, ...rest } = props;
|
|
44
|
-
return omitUndefined({
|
|
45
|
-
...rest,
|
|
46
|
-
videoId: id,
|
|
47
|
-
playerId,
|
|
48
|
-
showChapters: chapters
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
const Video = defineComponent({
|
|
52
|
-
name: "RixlVideo",
|
|
53
|
-
props: videoPropDefinitions,
|
|
54
|
-
emits: videoEmits,
|
|
55
|
-
setup(props, { attrs, emit, expose, slots }) {
|
|
56
|
-
const playerId = useOptionalPlayerId() ?? crypto.randomUUID();
|
|
57
|
-
providePlayerScope(playerId);
|
|
58
|
-
const element = ref(null);
|
|
59
|
-
expose({ element });
|
|
60
|
-
const listeners = buildVideoEventListeners(emit);
|
|
61
|
-
return () => h("rixl-video", {
|
|
62
|
-
...attrs,
|
|
63
|
-
ref: element,
|
|
64
|
-
...mapVideoElementProps(props, playerId),
|
|
65
|
-
...listeners
|
|
66
|
-
}, slots.default?.());
|
|
67
|
-
}
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
export { Video, videoEmits };
|
|
1
|
+
import{omitUndefined as e}from"../../lib/element-props.js";import{providePlayerScope as t,useOptionalPlayerId as n}from"../../lib/player-scope.js";import{videoPropDefinitions as r}from"./video-props.js";import{defineComponent as i,h as a,ref as o}from"vue";import"@rixl/media-lit/video";const s={play:e=>!0,pause:e=>!0,pausedChange:e=>!0,ended:()=>!0,timeUpdate:e=>!0,loadedMetadata:e=>!0,error:e=>!0,volumeChange:e=>!0,loadingChange:e=>!0,rateChange:e=>!0,qualityChange:e=>!0};function c(e){return{onPlay:t=>e(`play`,t),onPause:t=>e(`pause`,t),"onPaused-change":t=>{let n=t.detail;e(`pausedChange`,n.paused)},onEnded:()=>e(`ended`),onTimeupdate:t=>e(`timeUpdate`,t),"onLoaded-metadata":t=>e(`loadedMetadata`,t),onError:t=>e(`error`,t),"onVolume-change":t=>e(`volumeChange`,t),"onLoading-change":t=>{let n=t.detail;e(`loadingChange`,n.loading)},"onRate-change":t=>e(`rateChange`,t),"onQuality-change":t=>e(`qualityChange`,t)}}function l(t,n){let{id:r,chapters:i,...a}=t;return e({...a,videoId:r,playerId:n,showChapters:i})}const u=i({name:`RixlVideo`,props:r,emits:s,setup(e,{attrs:r,emit:i,expose:s,slots:u}){let d=n()??crypto.randomUUID();t(d);let f=o(null);s({element:f});let p=c(i);return()=>a(`rixl-video`,{...r,ref:f,...l(e,d),...p},u.default?.())}});export{u as Video,s as videoEmits};
|
package/dist/core.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export*from"@rixl/media-core";
|
package/dist/feed.js
CHANGED
package/dist/image.js
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,9 +1 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Image } from "./components/image/image.js";
|
|
3
|
-
import { Video } from "./components/video/video.js";
|
|
4
|
-
import { VideoPlayer } from "./components/video/video-player.js";
|
|
5
|
-
import { useOptionalPlayerId, usePlayerId } from "./lib/player-scope.js";
|
|
6
|
-
|
|
7
|
-
export * from "@rixl/media-core"
|
|
8
|
-
|
|
9
|
-
export { Feed, Image, Video, VideoPlayer, useOptionalPlayerId, usePlayerId };
|
|
1
|
+
import{Feed as e}from"./components/feed/feed.js";import{Image as t}from"./components/image/image.js";import{Video as n}from"./components/video/video.js";import{VideoPlayer as r}from"./components/video/video-player.js";import{useOptionalPlayerId as i,usePlayerId as a}from"./lib/player-scope.js";export*from"@rixl/media-core";export{e as Feed,t as Image,n as Video,r as VideoPlayer,i as useOptionalPlayerId,a as usePlayerId};
|
|
@@ -1,10 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
// src/lib/element-props.ts
|
|
4
|
-
function omitUndefined(record) {
|
|
5
|
-
const result = {};
|
|
6
|
-
for (const [key, value] of Object.entries(record)) if (value !== void 0) result[key] = typeof value === "object" && value !== null ? toRaw(value) : value;
|
|
7
|
-
return result;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export { omitUndefined };
|
|
1
|
+
import{toRaw as e}from"vue";function t(t){let n={};for(let[r,i]of Object.entries(t))i!==void 0&&(n[r]=typeof i==`object`&&i?e(i):i);return n}export{t as omitUndefined};
|
package/dist/lib/player-scope.js
CHANGED
|
@@ -1,25 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
// src/lib/player-scope.ts
|
|
4
|
-
const PLAYER_SCOPE_KEY = Symbol("rixl-player-scope");
|
|
5
|
-
function getOutOfScopeErrorMessage(fnName) {
|
|
6
|
-
return `${fnName}() must be used inside <Video> or <VideoPlayer>.\n\nFix:
|
|
1
|
+
import{inject as e,provide as t}from"vue";const n=Symbol(`rixl-player-scope`);function r(e){return`${e}() must be used inside <Video> or <VideoPlayer>.\n\nFix:
|
|
7
2
|
|
|
8
3
|
<VideoPlayer>
|
|
9
4
|
<Video id="..." theme="hideUI" />
|
|
10
5
|
<YourControls />
|
|
11
|
-
</VideoPlayer
|
|
12
|
-
}
|
|
13
|
-
function providePlayerScope(playerId) {
|
|
14
|
-
provide(PLAYER_SCOPE_KEY, playerId);
|
|
15
|
-
}
|
|
16
|
-
function useOptionalPlayerId() {
|
|
17
|
-
return inject(PLAYER_SCOPE_KEY, null);
|
|
18
|
-
}
|
|
19
|
-
function usePlayerId() {
|
|
20
|
-
const playerId = useOptionalPlayerId();
|
|
21
|
-
if (!playerId) throw new Error(getOutOfScopeErrorMessage("usePlayerId"));
|
|
22
|
-
return playerId;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export { providePlayerScope, useOptionalPlayerId, usePlayerId };
|
|
6
|
+
</VideoPlayer>`}function i(e){t(n,e)}function a(){return e(n,null)}function o(){let e=a();if(!e)throw Error(r(`usePlayerId`));return e}export{i as providePlayerScope,a as useOptionalPlayerId,o as usePlayerId};
|
package/dist/video.js
CHANGED
|
@@ -1,5 +1 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { VideoPlayer } from "./components/video/video-player.js";
|
|
3
|
-
import { useOptionalPlayerId, usePlayerId } from "./lib/player-scope.js";
|
|
4
|
-
|
|
5
|
-
export { Video, VideoPlayer, useOptionalPlayerId, usePlayerId };
|
|
1
|
+
import{Video as e}from"./components/video/video.js";import{VideoPlayer as t}from"./components/video/video-player.js";import{useOptionalPlayerId as n,usePlayerId as r}from"./lib/player-scope.js";export{e as Video,t as VideoPlayer,n as useOptionalPlayerId,r as usePlayerId};
|
package/package.json
CHANGED
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rixl/media-vue",
|
|
3
|
-
"version": "1.0
|
|
4
|
-
"description": "Vue 3
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "Vue 3 video player, image components, and infinite media feeds for Rixl, with TypeScript props, events, and player context.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"feed",
|
|
7
7
|
"hls",
|
|
8
8
|
"image",
|
|
9
|
-
"
|
|
9
|
+
"infinite-scroll",
|
|
10
|
+
"media-sdk",
|
|
10
11
|
"rixl",
|
|
11
|
-
"
|
|
12
|
+
"typescript",
|
|
12
13
|
"video",
|
|
14
|
+
"video-player",
|
|
13
15
|
"vue",
|
|
14
|
-
"vue3"
|
|
15
|
-
"web"
|
|
16
|
+
"vue3"
|
|
16
17
|
],
|
|
17
|
-
"homepage": "https://rixl.com",
|
|
18
|
+
"homepage": "https://developers.rixl.com/en/sdk/media-vue",
|
|
18
19
|
"license": "SEE LICENSE IN LICENSE.md",
|
|
19
20
|
"author": "Rixl Inc.",
|
|
20
21
|
"repository": {
|
|
@@ -45,8 +46,8 @@
|
|
|
45
46
|
"clean": "rimraf dist node_modules"
|
|
46
47
|
},
|
|
47
48
|
"dependencies": {
|
|
48
|
-
"@rixl/media-core": "1.0
|
|
49
|
-
"@rixl/media-lit": "1.0
|
|
49
|
+
"@rixl/media-core": "1.1.0",
|
|
50
|
+
"@rixl/media-lit": "1.1.0"
|
|
50
51
|
},
|
|
51
52
|
"peerDependencies": {
|
|
52
53
|
"vue": ">=3.3.0"
|