@rixl/media-solid 0.0.1 → 1.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 ADDED
@@ -0,0 +1,123 @@
1
+ # Rixl Media SDK for Solid
2
+
3
+ Solid video player, image components, and infinite media feeds for Rixl. `@rixl/media-solid` provides typed reactive Solid props, callbacks, refs, and player context over the shared Rixl media UI.
4
+
5
+ [Documentation](https://developers.rixl.com/en/sdk/media-solid) · [npm](https://www.npmjs.com/package/@rixl/media-solid) · [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
+ - Solid reactivity, signal integration, and context-based player scopes.
13
+ - Included player styles; no Tailwind CSS or custom-element compiler configuration is required.
14
+
15
+ ## Install
16
+
17
+ ```sh
18
+ npm install @rixl/media-solid
19
+ ```
20
+
21
+ Requires Solid 1.8 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.
26
+
27
+ ```tsx
28
+ import {createSignal, onMount, Show} from "solid-js";
29
+ import {connect} from "@rixl/media-solid/core";
30
+ import {Video} from "@rixl/media-solid/video";
31
+
32
+ export default function App() {
33
+ const [ready, setReady] = createSignal(false);
34
+ const [error, setError] = createSignal("");
35
+
36
+ onMount(async () => {
37
+ try {
38
+ await connect({baseUrl: "https://api.rixl.com", apiKey: "YOUR_PUBLIC_API_KEY"});
39
+ setReady(true);
40
+ } catch {
41
+ setError("Unable to connect to Rixl.");
42
+ }
43
+ });
44
+
45
+ return (
46
+ <div>
47
+ <Show when={error()}>{(err) => <p role="alert">{err()}</p>}</Show>
48
+ <Show when={ready()} fallback={<p role="status">Loading media…</p>}>
49
+ <Video id="YOUR_VIDEO_ID" muted={true} style={{width: "100%", "aspect-ratio": "16 / 9"}} />
50
+ </Show>
51
+ </div>
52
+ );
53
+ }
54
+ ```
55
+
56
+ Use credentials intended for browser access. If your application already authenticates the shared `@rixl/sdk` client, reuse that connection instead.
57
+
58
+ ## Images and feeds
59
+
60
+ After connecting, import the components you need:
61
+
62
+ ```tsx
63
+ import {createSignal} from "solid-js";
64
+ import {Image} from "@rixl/media-solid/image";
65
+ import {Feed} from "@rixl/media-solid/feed";
66
+
67
+ export function MediaGallery() {
68
+ const [muted, setMuted] = createSignal(true);
69
+
70
+ return (
71
+ <div>
72
+ <Image id="YOUR_IMAGE_ID" alt="Mountain lake at sunrise" style={{width: "100%", "aspect-ratio": "16 / 9"}} />
73
+ <Feed feedId="YOUR_FEED_ID" muted={muted()} onMuteChange={setMuted} style={{height: "36rem"}} />
74
+ </div>
75
+ );
76
+ }
77
+ ```
78
+
79
+ Production media is resolved by `id` or `feedId` through the SDK.
80
+
81
+ ## Events and custom controls
82
+
83
+ Video accepts `onPlay`, `onPause`, `onEnded`, `onPausedChange`, `onLoadingChange`, `onTimeUpdate`, `onLoadedMetadata`, `onVolumeChange`, `onRateChange`, `onQualityChange`, and `onError`. Image accepts `onLoadingChange`; Feed accepts `onMuteChange`.
84
+
85
+ ```tsx
86
+ <Video id="YOUR_VIDEO_ID" onPausedChange={(paused) => console.log("Paused:", paused)} />
87
+ ```
88
+
89
+ Use a `ref` prop to access the underlying Lit element. `<VideoPlayer>` shares a player scope with sibling controls; `usePlayerId()` and `useOptionalPlayerId()` are available from `/video`. Playback actions and state live in `/core`.
90
+
91
+ ```tsx
92
+ import {Video, VideoPlayer, usePlayerId} from "@rixl/media-solid/video";
93
+
94
+ function CustomOverlay() {
95
+ const playerId = usePlayerId();
96
+ return <div class="overlay">Player ID: {playerId}</div>;
97
+ }
98
+
99
+ export function PlayerWithControls() {
100
+ return (
101
+ <VideoPlayer>
102
+ <Video id="YOUR_VIDEO_ID" theme="hideUI" />
103
+ <CustomOverlay />
104
+ </VideoPlayer>
105
+ );
106
+ }
107
+ ```
108
+
109
+ ## Styling, rendering, and imports
110
+
111
+ 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.
112
+
113
+ In a SolidStart app, mount media inside client-only routes or components and initialize the SDK in the browser. Full server-rendered media markup is not provided by this adapter.
114
+
115
+ | Import | Exports |
116
+ | ------------------------- | ----------------------------------------------------------- |
117
+ | `@rixl/media-solid/image` | `Image`, `ImageProps` |
118
+ | `@rixl/media-solid/video` | `Video`, `VideoPlayer`, props, and player-context accessors |
119
+ | `@rixl/media-solid/feed` | `Feed`, `FeedProps` |
120
+ | `@rixl/media-solid/core` | Headless APIs, stores, utilities, and types |
121
+ | `@rixl/media-solid` | Components and Core exports |
122
+
123
+ Subpath imports keep an image-only app free of video, feed, and HLS code. See the [Solid guide](https://developers.rixl.com/en/sdk/media-solid) for integration details.
@@ -0,0 +1,23 @@
1
+ import { FeedPost, FontFamilyKey, Page, PlayerLanguage } from "@rixl/media-core";
2
+ import { JSX } from "@solidjs/web";
3
+ import { RixlFeed } from "@rixl/media-lit/feed";
4
+ import { Component, Ref } from "solid-js";
5
+ export type FeedProps = {
6
+ feedId?: string;
7
+ lang?: PlayerLanguage;
8
+ feedFont?: FontFamilyKey;
9
+ loop?: boolean;
10
+ autoscroll?: boolean;
11
+ muted?: boolean;
12
+ analytics?: boolean;
13
+ analyticsPage?: Page;
14
+ safeAreaTabBar?: number;
15
+ posts?: FeedPost[];
16
+ initialIndex?: number;
17
+ onFetchMore?: () => void | Promise<void>;
18
+ onMuteChange?: (muted: boolean) => void;
19
+ ref?: Ref<RixlFeed>;
20
+ class?: string;
21
+ style?: string | JSX.CSSProperties;
22
+ };
23
+ export declare const Feed: Component<FeedProps>;
@@ -0,0 +1 @@
1
+ import{assignRef as e,bindElementEvents as t,syncElementProps as n}from"../../lib/sync-element.js";import{className as r,effect as i,getOwner as a,readShallow as o,ref as s,style as c,template as l}from"@solidjs/web";import"@rixl/media-lit/feed";import{createEffect as u}from"solid-js";var d=/* @__PURE__ */ l(`<rixl-feed>`,1);function f(e){return{feedId:e.feedId??``,lang:e.lang??`en`,feedFont:e.feedFont,loop:e.loop??!1,autoscroll:e.autoscroll??!1,muted:e.muted,analytics:e.analytics,analyticsPage:e.analyticsPage,safeAreaTabBar:e.safeAreaTabBar,posts:e.posts,initialIndex:e.initialIndex,onFetchMore:e.onFetchMore}}const p=l=>{let p;u(()=>f(l),e=>{p&&n(p,e)}),u(()=>l.onMuteChange,e=>{if(p&&e)return t(p,{"mute-change":t=>{t instanceof CustomEvent&&typeof t.detail?.muted==`boolean`&&e(t.detail.muted)}})});var m=d();return s(()=>t=>{p=t,e(l.ref,t)},m),m._$owner=a(),i(()=>({e:o(l.class),t:o(l.style)}),({e,t},n)=>{r(m,e,n?.e),c(m,t,n?.t)}),m};export{p as Feed};
@@ -0,0 +1,19 @@
1
+ import { ImageData, Page } from "@rixl/media-core";
2
+ import { JSX } from "@solidjs/web";
3
+ import { Component, Ref } from "solid-js";
4
+ import { RixlImage } from "@rixl/media-lit/image";
5
+ export type ImageProps = {
6
+ id?: string;
7
+ imageData?: ImageData;
8
+ alt?: string;
9
+ analytics?: boolean;
10
+ analyticsPage?: Page;
11
+ isCurrent?: boolean;
12
+ feedId?: string;
13
+ postId?: string;
14
+ onLoadingChange?: (isLoading: boolean) => void;
15
+ ref?: Ref<RixlImage>;
16
+ class?: string;
17
+ style?: string | JSX.CSSProperties;
18
+ };
19
+ export declare const Image: Component<ImageProps>;
@@ -0,0 +1 @@
1
+ import{assignRef as e,bindElementEvents as t,syncElementProps as n}from"../../lib/sync-element.js";import{className as r,effect as i,getOwner as a,readShallow as o,ref as s,style as c,template as l}from"@solidjs/web";import{createEffect as u}from"solid-js";import"@rixl/media-lit/image";var d=/* @__PURE__ */ l(`<rixl-image>`,1);function f(e,t){return e===void 0?t?!0:void 0:e}function p(e){return{imageId:e.id,imageData:e.imageData,alt:e.alt,analytics:e.analytics??!0,analyticsPage:e.analyticsPage??`standalone`,isCurrent:f(e.isCurrent,e.id),feedId:e.feedId,postId:e.postId}}const m=l=>{let f;u(()=>p(l),e=>{f&&n(f,e)}),u(()=>l.onLoadingChange,e=>{if(f&&e)return t(f,{"loading-change":t=>{t instanceof CustomEvent&&typeof t.detail==`boolean`&&e(t.detail)}})});var m=d();return s(()=>t=>{f=t,e(l.ref,t)},m),m._$owner=a(),i(()=>({e:o(l.class),t:o(l.style)}),({e,t},n)=>{r(m,e,n?.e),c(m,t,n?.t)}),m};export{m as Image};
@@ -0,0 +1,6 @@
1
+ import { JSX } from "@solidjs/web";
2
+ import { ParentComponent } from "solid-js";
3
+ export type VideoPlayerProps = {
4
+ children?: JSX.Element;
5
+ };
6
+ export declare const VideoPlayer: ParentComponent<VideoPlayerProps>;
@@ -0,0 +1 @@
1
+ import{PlayerScopeContext as e}from"../../lib/player-scope.js";import{createComponent as t}from"@solidjs/web";import"solid-js";const n=n=>{let r=crypto.randomUUID();return t(e,{value:r,get children(){return n.children}})};export{n as VideoPlayer};
@@ -0,0 +1,61 @@
1
+ import { FeedPost, FontFamilyKey, Page, VideoData, VideoHeatmap, VideoLoadState, VideoTheme } from "@rixl/media-core";
2
+ import { JSX } from "@solidjs/web";
3
+ import { Ref } from "solid-js";
4
+ import { RixlVideo } from "@rixl/media-lit/video";
5
+ export type VideoLoadMode = VideoLoadState;
6
+ export type VideoPlanType = "free" | "pro" | "pay-as-you-go" | "custom";
7
+ export type VideoProps = {
8
+ id?: string;
9
+ src?: string;
10
+ videoData?: VideoData;
11
+ autoPlay?: boolean;
12
+ muted?: boolean;
13
+ loop?: boolean;
14
+ playsInline?: boolean;
15
+ poster?: string;
16
+ thumbhash?: string;
17
+ volume?: number;
18
+ progressBar?: boolean;
19
+ heatmap?: boolean;
20
+ chapters?: boolean;
21
+ heatmapData?: VideoHeatmap | null;
22
+ controls?: boolean;
23
+ hideUI?: boolean;
24
+ settingsOpen?: boolean;
25
+ theme?: VideoTheme;
26
+ autoHideMs?: number;
27
+ allowPlayPause?: boolean;
28
+ allowFullscreen?: boolean;
29
+ allowPictureInPicture?: boolean;
30
+ soundDisabled?: boolean;
31
+ resumeProgress?: boolean;
32
+ isCurrent?: boolean;
33
+ isFeed?: boolean;
34
+ loadState?: VideoLoadMode;
35
+ dataPost?: FeedPost;
36
+ feedFont?: FontFamilyKey;
37
+ feedId?: string;
38
+ postId?: string;
39
+ analytics?: boolean;
40
+ analyticsPage?: Page;
41
+ lang?: string;
42
+ planType?: VideoPlanType;
43
+ userId?: string;
44
+ userProperties?: Record<string, string>;
45
+ hotSegments?: boolean;
46
+ onPlay?: (event: Event) => void;
47
+ onPause?: (event: Event) => void;
48
+ onPausedChange?: (isPaused: boolean) => void;
49
+ onEnded?: () => void;
50
+ onTimeUpdate?: (event: Event) => void;
51
+ onLoadedMetadata?: (event: Event) => void;
52
+ onError?: (event: Event) => void;
53
+ onVolumeChange?: (event: Event) => void;
54
+ onLoadingChange?: (isLoading: boolean) => void;
55
+ onRateChange?: (event: Event) => void;
56
+ onQualityChange?: (event: Event) => void;
57
+ ref?: Ref<RixlVideo>;
58
+ children?: JSX.Element;
59
+ class?: string;
60
+ style?: string | JSX.CSSProperties;
61
+ };
@@ -0,0 +1,5 @@
1
+ import { VideoProps } from "./video-props.js";
2
+ import { ParentComponent } from "solid-js";
3
+ import "@rixl/media-lit/video";
4
+ export declare const Video: ParentComponent<VideoProps>;
5
+ export type { VideoProps };
@@ -0,0 +1 @@
1
+ import{PlayerScopeContext as e,useOptionalPlayerId as t}from"../../lib/player-scope.js";import{assignRef as n,bindElementEvents as r,syncElementProps as i}from"../../lib/sync-element.js";import{className as a,createComponent as o,effect as s,getOwner as c,insert as l,readShallow as u,ref as d,style as f,template as p}from"@solidjs/web";import{createEffect as m}from"solid-js";import"@rixl/media-lit/video";var h=/* @__PURE__ */ p(`<rixl-video>`,1);function g(e,t){let{id:n,chapters:r,children:i,ref:a,class:o,style:s,onPlay:c,onPause:l,onPausedChange:u,onEnded:d,onTimeUpdate:f,onLoadedMetadata:p,onError:m,onVolumeChange:h,onLoadingChange:g,onRateChange:_,onQualityChange:v,...y}=e;return{...y,videoId:n,playerId:t,showChapters:r}}function _(e){return{play:e.onPlay,pause:e.onPause,"paused-change":e.onPausedChange?t=>{let n=t.detail;typeof n?.paused==`boolean`&&e.onPausedChange?.(n.paused)}:void 0,ended:e.onEnded?()=>e.onEnded?.():void 0,timeupdate:e.onTimeUpdate,"loaded-metadata":e.onLoadedMetadata,error:e.onError,"volume-change":e.onVolumeChange,"loading-change":e.onLoadingChange?t=>{let n=t.detail;typeof n?.loading==`boolean`&&e.onLoadingChange?.(n.loading)}:void 0,"rate-change":e.onRateChange,"quality-change":e.onQualityChange}}const v=p=>{let v=t()??crypto.randomUUID(),y;m(()=>g(p,v),e=>{y&&i(y,e)}),m(()=>_(p),e=>{if(y)return r(y,e)});var b=h();return d(()=>e=>{y=e,n(p.ref,e)},b),b._$owner=c(),l(b,o(e,{value:v,get children(){return p.children}})),s(()=>({e:u(p.class),t:u(p.style)}),({e,t},n)=>{a(b,e,n?.e),f(b,t,n?.t)}),b};export{v as Video};
package/dist/core.d.ts ADDED
@@ -0,0 +1 @@
1
+ export * from "@rixl/media-core";
package/dist/core.js ADDED
@@ -0,0 +1 @@
1
+ export*from"@rixl/media-core";
package/dist/feed.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ import { Feed, FeedProps } from "./components/feed/feed.js";
2
+ export { Feed, type FeedProps };
package/dist/feed.js ADDED
@@ -0,0 +1 @@
1
+ export{Feed}from"./components/feed/feed.js";
@@ -0,0 +1,2 @@
1
+ import { Image, ImageProps } from "./components/image/image.js";
2
+ export { Image, type ImageProps };
package/dist/image.js ADDED
@@ -0,0 +1 @@
1
+ export{Image}from"./components/image/image.js";
@@ -0,0 +1,11 @@
1
+ import { Feed, FeedProps } from "./components/feed/feed.js";
2
+ import "./feed.js";
3
+ import { Image, ImageProps } from "./components/image/image.js";
4
+ import "./image.js";
5
+ import { VideoLoadMode, VideoPlanType, VideoProps } from "./components/video/video-props.js";
6
+ import { Video } from "./components/video/video.js";
7
+ import { VideoPlayer, VideoPlayerProps } from "./components/video/video-player.js";
8
+ import { PlayerScopeContext, PlayerScopeContextType, useOptionalPlayerId, usePlayerId } from "./lib/player-scope.js";
9
+ import "./video.js";
10
+ export * from "@rixl/media-core";
11
+ export { Feed, type FeedProps, Image, type ImageProps, PlayerScopeContext, type PlayerScopeContextType, Video, type VideoLoadMode, type VideoPlanType, VideoPlayer, type VideoPlayerProps, type VideoProps, useOptionalPlayerId, usePlayerId };
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ import{Feed as e}from"./components/feed/feed.js";import{Image as t}from"./components/image/image.js";import{PlayerScopeContext as n,useOptionalPlayerId as r,usePlayerId as i}from"./lib/player-scope.js";import{Video as a}from"./components/video/video.js";import{VideoPlayer as o}from"./components/video/video-player.js";export*from"@rixl/media-core";export{e as Feed,t as Image,n as PlayerScopeContext,a as Video,o as VideoPlayer,r as useOptionalPlayerId,i as usePlayerId};
@@ -0,0 +1,8 @@
1
+ import { UUID } from "@rixl/media-core";
2
+ import { Context } from "solid-js";
3
+ export type PlayerScopeContextType = Context<UUID | null> & {
4
+ Provider: Context<UUID | null>;
5
+ };
6
+ export declare const PlayerScopeContext: PlayerScopeContextType;
7
+ export declare function useOptionalPlayerId(): UUID | null;
8
+ export declare function usePlayerId(): UUID;
@@ -0,0 +1,6 @@
1
+ import{createContext as e,useContext as t}from"solid-js";const n=e(null);n.Provider=n;const r=n;function i(e){return`${e}() must be used inside <Video> or <VideoPlayer>.\n\nFix:
2
+
3
+ <VideoPlayer>
4
+ <Video id="..." theme="hideUI" />
5
+ <YourControls />
6
+ </VideoPlayer>`}function a(){return t(r)}function o(){let e=a();if(!e)throw Error(i(`usePlayerId`));return e}export{r as PlayerScopeContext,a as useOptionalPlayerId,o as usePlayerId};
@@ -0,0 +1 @@
1
+ function e(e,t){for(let[n,r]of Object.entries(t))r!==void 0&&Reflect.get(e,n)!==r&&Reflect.set(e,n,r)}function t(e,t){let n=[];for(let[r,i]of Object.entries(t))i&&(e.addEventListener(r,i),n.push([r,i]));return function(){for(let[t,r]of n)e.removeEventListener(t,r)}}function n(e,t){if(typeof e==`function`)e(t);else if(Array.isArray(e))for(let n of e)typeof n==`function`&&n(t);else typeof e==`object`&&e&&`current`in e&&(e.current=t)}export{n as assignRef,t as bindElementEvents,e as syncElementProps};
@@ -0,0 +1,5 @@
1
+ import { Video } from "./components/video/video.js";
2
+ import { VideoPlayer, VideoPlayerProps } from "./components/video/video-player.js";
3
+ import { VideoLoadMode, VideoPlanType, VideoProps } from "./components/video/video-props.js";
4
+ import { PlayerScopeContext, PlayerScopeContextType, useOptionalPlayerId, usePlayerId } from "./lib/player-scope.js";
5
+ export { PlayerScopeContext, type PlayerScopeContextType, Video, type VideoLoadMode, type VideoPlanType, VideoPlayer, type VideoPlayerProps, type VideoProps, useOptionalPlayerId, usePlayerId };
package/dist/video.js ADDED
@@ -0,0 +1 @@
1
+ import{Video as e}from"./components/video/video.js";import{VideoPlayer as t}from"./components/video/video-player.js";import{PlayerScopeContext as n,useOptionalPlayerId as r,usePlayerId as i}from"./lib/player-scope.js";export{n as PlayerScopeContext,e as Video,t as VideoPlayer,r as useOptionalPlayerId,i as usePlayerId};
package/package.json CHANGED
@@ -1,13 +1,56 @@
1
1
  {
2
2
  "name": "@rixl/media-solid",
3
- "version": "0.0.1",
4
- "description": "Solid components for Rixl Media SDK",
5
- "main": "index.js",
3
+ "version": "1.1.1",
4
+ "description": "Solid video player, image components, and infinite media feeds for Rixl, with reactive props, events, and player context.",
5
+ "keywords": [
6
+ "feed",
7
+ "hls",
8
+ "image",
9
+ "infinite-scroll",
10
+ "media-sdk",
11
+ "rixl",
12
+ "solid",
13
+ "solidjs",
14
+ "typescript",
15
+ "video",
16
+ "video-player"
17
+ ],
18
+ "homepage": "https://developers.rixl.com/en/sdk/media-solid",
19
+ "license": "SEE LICENSE IN LICENSE.md",
20
+ "author": "Rixl Inc.",
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "https://github.com/rixlhq/mediasdk.git",
24
+ "directory": "packages/solid"
25
+ },
26
+ "files": [
27
+ "dist"
28
+ ],
29
+ "type": "module",
30
+ "sideEffects": false,
31
+ "types": "dist/index.d.ts",
32
+ "exports": {
33
+ ".": "./dist/index.js",
34
+ "./core": "./dist/core.js",
35
+ "./image": "./dist/image.js",
36
+ "./video": "./dist/video.js",
37
+ "./feed": "./dist/feed.js",
38
+ "./package.json": "./package.json"
39
+ },
40
+ "publishConfig": {
41
+ "access": "public"
42
+ },
6
43
  "scripts": {
7
- "test": "echo \"Error: no test specified\" && exit 1"
44
+ "dev": "vp pack --watch",
45
+ "pack": "vp pack",
46
+ "clean": "rimraf dist node_modules"
47
+ },
48
+ "dependencies": {
49
+ "@rixl/media-core": "1.1.1",
50
+ "@rixl/media-lit": "1.1.1"
8
51
  },
9
- "keywords": [],
10
- "author": "",
11
- "license": "ISC",
12
- "type": "commonjs"
52
+ "peerDependencies": {
53
+ "@solidjs/web": ">=2.0.0-rc.0",
54
+ "solid-js": ">=2.0.0-rc.0"
55
+ }
13
56
  }