@jaaq/jaaq-sdk-js 1.0.0 → 1.0.1-dev-8b8d9e4-20251211
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 +753 -49
- package/dist/embed/embed.html +270 -0
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/jaaq-sdk.min.js +1 -1
- package/dist/jaaq-sdk.min.js.map +1 -1
- package/dist/ui/index.cjs +784 -0
- package/dist/ui/index.cjs.map +1 -0
- package/dist/ui/index.d.ts +272 -0
- package/dist/ui/index.mjs +781 -0
- package/dist/ui/index.mjs.map +1 -0
- package/dist/ui/jaaq-ui-bundled.min.js +2 -0
- package/dist/ui/jaaq-ui-bundled.min.js.map +1 -0
- package/dist/ui/jaaq-ui.min.js +2 -0
- package/dist/ui/jaaq-ui.min.js.map +1 -0
- package/dist/ui/react/index.cjs +1009 -0
- package/dist/ui/react/index.cjs.map +1 -0
- package/dist/ui/react/index.d.ts +142 -0
- package/dist/ui/react/index.mjs +989 -0
- package/dist/ui/react/index.mjs.map +1 -0
- package/dist/ui/react/jaaq-ui-react.min.js +2 -0
- package/dist/ui/react/jaaq-ui-react.min.js.map +1 -0
- package/dist/ui/webcomponents/index.cjs +919 -0
- package/dist/ui/webcomponents/index.cjs.map +1 -0
- package/dist/ui/webcomponents/index.d.ts +271 -0
- package/dist/ui/webcomponents/index.mjs +915 -0
- package/dist/ui/webcomponents/index.mjs.map +1 -0
- package/dist/ui/webcomponents/jaaq-webcomponents-bundled.min.js +2 -0
- package/dist/ui/webcomponents/jaaq-webcomponents-bundled.min.js.map +1 -0
- package/dist/ui/webcomponents/jaaq-webcomponents.min.js +2 -0
- package/dist/ui/webcomponents/jaaq-webcomponents.min.js.map +1 -0
- package/package.json +40 -1
package/README.md
CHANGED
|
@@ -49,83 +49,770 @@ const video = await client.videos.getById('video-id');
|
|
|
49
49
|
const collections = await client.collections.list();
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
-
|
|
52
|
+
## UI Components
|
|
53
|
+
|
|
54
|
+
The SDK includes ready-to-use embeddable video player components with custom controls, HLS support, and modern design.
|
|
55
|
+
|
|
56
|
+
**Architecture:** The SDK uses a layered approach:
|
|
57
|
+
|
|
58
|
+
- **Web Components** (`<jaaq-video-player>`) - Primary, framework-agnostic implementation
|
|
59
|
+
- **React Component** - Thin wrapper around web component with React-friendly API
|
|
60
|
+
- **Vanilla Player** - Internal implementation used by web components
|
|
61
|
+
|
|
62
|
+
**Recommended:** Use web components for all new integrations. They work everywhere (React, Vue, Angular, vanilla JS) and provide the best developer experience.
|
|
63
|
+
|
|
64
|
+
### Web Components (Recommended)
|
|
65
|
+
|
|
66
|
+
Web components are the primary way to use the video player. They work in any framework or vanilla JavaScript.
|
|
67
|
+
|
|
68
|
+
See the [Web Components section](#web-components-native-custom-elements) below for installation, usage examples, and full API documentation.
|
|
69
|
+
|
|
70
|
+
### React Video Player
|
|
71
|
+
|
|
72
|
+
The React component is a thin wrapper around the web component, providing React-friendly props and callbacks.
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
npm install @jaaq/jaaq-sdk-js
|
|
76
|
+
```
|
|
53
77
|
|
|
54
78
|
```typescript
|
|
55
|
-
import {
|
|
56
|
-
import { createJaaqClient } from "@jaaq/jaaq-sdk-js";
|
|
79
|
+
import { VideoPlayer } from '@jaaq/jaaq-sdk-js/ui/react';
|
|
57
80
|
|
|
58
|
-
|
|
59
|
-
|
|
81
|
+
function App() {
|
|
82
|
+
return (
|
|
83
|
+
<VideoPlayer
|
|
84
|
+
videoId="your-video-id"
|
|
85
|
+
apiKey="your-api-key"
|
|
86
|
+
clientId="your-client-id"
|
|
87
|
+
autoplay={false}
|
|
88
|
+
showInfo={true}
|
|
89
|
+
onPlay={() => console.log('Playing')}
|
|
90
|
+
onPause={() => console.log('Paused')}
|
|
91
|
+
onError={(error) => console.error(error)}
|
|
92
|
+
onLoaded={(video) => console.log('Loaded:', video)}
|
|
93
|
+
/>
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
**Or use the web component directly in React:**
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
import '@jaaq/jaaq-sdk-js/ui/webcomponents';
|
|
102
|
+
import type { JaaqVideoPlayerElement } from '@jaaq/jaaq-sdk-js/ui/webcomponents';
|
|
103
|
+
|
|
104
|
+
function App() {
|
|
105
|
+
const playerRef = useRef<JaaqVideoPlayerElement>(null);
|
|
106
|
+
|
|
107
|
+
return (
|
|
108
|
+
<jaaq-video-player
|
|
109
|
+
ref={playerRef}
|
|
110
|
+
video-id="your-video-id"
|
|
111
|
+
api-key="your-api-key"
|
|
112
|
+
client-id="your-client-id"
|
|
113
|
+
autoplay="false"
|
|
114
|
+
/>
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
#### React Player Props
|
|
120
|
+
|
|
121
|
+
| Prop | Type | Required | Default | Description |
|
|
122
|
+
| -------------------- | --------------------------- | ----------- | ----------- | ----------------------------------------------- |
|
|
123
|
+
| `videoId` | `string` | Yes | - | Video ID to load |
|
|
124
|
+
| `apiKey` | `string` | Conditional | - | API key (required if no client) |
|
|
125
|
+
| `clientId` | `string` | Conditional | - | Client ID (required if no client) |
|
|
126
|
+
| `client` | `JaaqClient` | Conditional | - | Existing SDK client instance |
|
|
127
|
+
| `baseUrl` | `string` | No | API default | Custom API base URL |
|
|
128
|
+
| `autoplay` | `boolean` | No | `false` | Auto-play video on load |
|
|
129
|
+
| `width` | `string` | No | `'100%'` | Player width |
|
|
130
|
+
| `height` | `string` | No | `'auto'` | Player height |
|
|
131
|
+
| `className` | `string` | No | `''` | Additional CSS class |
|
|
132
|
+
| `showInfo` | `boolean` | No | `false` | Show video metadata below player |
|
|
133
|
+
| `onPlay` | `() => void` | No | - | Called when video starts playing |
|
|
134
|
+
| `onPause` | `() => void` | No | - | Called when video pauses |
|
|
135
|
+
| `onError` | `(error: Error) => void` | No | - | Called on error |
|
|
136
|
+
| `onLoaded` | `(video: VideoDTO) => void` | No | - | Called when video loads |
|
|
137
|
+
| `onTimeUpdate` | `(time: number) => void` | No | - | Called on time update (current time in seconds) |
|
|
138
|
+
| `onVolumeChange` | `(volume: number) => void` | No | - | Called on volume change (0-1) |
|
|
139
|
+
| `onEnded` | `() => void` | No | - | Called when video finishes |
|
|
140
|
+
| `onFullscreenChange` | `(isFull: boolean) => void` | No | - | Called on fullscreen state change |
|
|
141
|
+
|
|
142
|
+
**Ref Methods:**
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
const playerRef = useRef<VideoPlayerHandle>(null);
|
|
146
|
+
|
|
147
|
+
playerRef.current?.play();
|
|
148
|
+
playerRef.current?.pause();
|
|
149
|
+
playerRef.current?.setVolume(0.5);
|
|
150
|
+
playerRef.current?.toggleMute();
|
|
151
|
+
playerRef.current?.seek(30);
|
|
152
|
+
playerRef.current?.getState();
|
|
153
|
+
playerRef.current?.destroy();
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Web Components (Native Custom Elements)
|
|
157
|
+
|
|
158
|
+
The SDK provides a native web component `<jaaq-video-player>` with Shadow DOM encapsulation. Perfect for framework-agnostic applications or when you need style isolation.
|
|
159
|
+
|
|
160
|
+
#### Installation & Registration
|
|
161
|
+
|
|
162
|
+
**For ES modules (npm/import):**
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
npm install @jaaq/jaaq-sdk-js hls.js
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
**Auto-registration (default)** - Components register automatically when imported:
|
|
169
|
+
|
|
170
|
+
```javascript
|
|
171
|
+
import '@jaaq/jaaq-sdk-js/ui/webcomponents';
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
**For browser/CDN (no build step):**
|
|
175
|
+
|
|
176
|
+
Use the bundled version (includes hls.js, auto-registers):
|
|
177
|
+
|
|
178
|
+
```html
|
|
179
|
+
<script src="https://cdn.jaaq.app/jaaq-sdk-js/latest/ui/webcomponents/jaaq-webcomponents-bundled.min.js"></script>
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
**Manual registration** (for advanced use cases):
|
|
183
|
+
|
|
184
|
+
```javascript
|
|
185
|
+
import { registerJaaqComponents } from '@jaaq/jaaq-sdk-js/ui/webcomponents';
|
|
60
186
|
|
|
61
|
-
|
|
62
|
-
|
|
187
|
+
registerJaaqComponents();
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
To disable auto-registration with the bundled script:
|
|
191
|
+
|
|
192
|
+
```html
|
|
193
|
+
<script src="..." data-auto-register="false"></script>
|
|
194
|
+
<script>
|
|
195
|
+
JaaqWebComponents.registerJaaqComponents();
|
|
196
|
+
</script>
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
#### Declarative Usage
|
|
200
|
+
|
|
201
|
+
```html
|
|
202
|
+
<!DOCTYPE html>
|
|
203
|
+
<html>
|
|
204
|
+
<head>
|
|
205
|
+
<script src="https://cdn.jaaq.app/jaaq-sdk-js/latest/ui/webcomponents/jaaq-webcomponents-bundled.min.js"></script>
|
|
206
|
+
</head>
|
|
207
|
+
<body>
|
|
208
|
+
<jaaq-video-player video-id="your-video-id" api-key="your-api-key" client-id="your-client-id" autoplay="false" width="100%">
|
|
209
|
+
</jaaq-video-player>
|
|
210
|
+
</body>
|
|
211
|
+
</html>
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
#### Programmatic Usage
|
|
215
|
+
|
|
216
|
+
```html
|
|
217
|
+
<script type="module">
|
|
218
|
+
import '@jaaq/jaaq-sdk-js/ui/webcomponents';
|
|
219
|
+
|
|
220
|
+
const player = document.createElement('jaaq-video-player');
|
|
221
|
+
player.setAttribute('video-id', 'your-video-id');
|
|
222
|
+
player.setAttribute('api-key', 'your-api-key');
|
|
223
|
+
player.setAttribute('client-id', 'your-client-id');
|
|
224
|
+
|
|
225
|
+
player.addEventListener('jaaq:loaded', (e) => {
|
|
226
|
+
console.log('Video loaded:', e.detail);
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
player.addEventListener('jaaq:play', () => {
|
|
230
|
+
console.log('Playing');
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
player.addEventListener('jaaq:error', (e) => {
|
|
234
|
+
console.error('Error:', e.detail);
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
document.body.appendChild(player);
|
|
238
|
+
</script>
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
#### Web Component Attributes
|
|
242
|
+
|
|
243
|
+
| Attribute | Type | Required | Default | Description |
|
|
244
|
+
| ----------- | --------- | ----------- | ----------- | ------------------------------------------ |
|
|
245
|
+
| `video-id` | `string` | Yes | - | Video ID to load |
|
|
246
|
+
| `api-key` | `string` | Conditional | - | API key (required if no client property) |
|
|
247
|
+
| `client-id` | `string` | Conditional | - | Client ID (required if no client property) |
|
|
248
|
+
| `base-url` | `string` | No | API default | Custom API base URL |
|
|
249
|
+
| `autoplay` | `boolean` | No | `false` | Auto-play video on load |
|
|
250
|
+
| `width` | `string` | No | `'100%'` | Player width |
|
|
251
|
+
| `height` | `string` | No | `'auto'` | Player height |
|
|
252
|
+
|
|
253
|
+
#### Web Component Properties & Methods
|
|
254
|
+
|
|
255
|
+
```javascript
|
|
256
|
+
const player = document.querySelector('jaaq-video-player');
|
|
257
|
+
|
|
258
|
+
player.client = existingJaaqClient;
|
|
259
|
+
|
|
260
|
+
player.play();
|
|
261
|
+
player.pause();
|
|
262
|
+
player.setVolume(0.5);
|
|
263
|
+
player.toggleMute();
|
|
264
|
+
player.seek(30);
|
|
265
|
+
const state = player.getState();
|
|
266
|
+
player.destroy();
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
#### Web Component Custom Events
|
|
270
|
+
|
|
271
|
+
All events are prefixed with `jaaq:` and use the standard `CustomEvent` API:
|
|
272
|
+
|
|
273
|
+
```javascript
|
|
274
|
+
player.addEventListener('jaaq:play', () => {});
|
|
275
|
+
player.addEventListener('jaaq:pause', () => {});
|
|
276
|
+
player.addEventListener('jaaq:timeupdate', (e) => {
|
|
277
|
+
console.log('Current time:', e.detail);
|
|
278
|
+
});
|
|
279
|
+
player.addEventListener('jaaq:volumechange', (e) => {
|
|
280
|
+
console.log('Volume:', e.detail);
|
|
281
|
+
});
|
|
282
|
+
player.addEventListener('jaaq:ended', () => {});
|
|
283
|
+
player.addEventListener('jaaq:error', (e) => {
|
|
284
|
+
console.error('Error:', e.detail);
|
|
285
|
+
});
|
|
286
|
+
player.addEventListener('jaaq:loaded', (e) => {
|
|
287
|
+
console.log('Video:', e.detail);
|
|
288
|
+
});
|
|
289
|
+
player.addEventListener('jaaq:fullscreenchange', (e) => {
|
|
290
|
+
console.log('Fullscreen:', e.detail);
|
|
291
|
+
});
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
#### Using Web Components in React
|
|
295
|
+
|
|
296
|
+
Web components work seamlessly with React. Import the component registration and use it as a JSX element:
|
|
297
|
+
|
|
298
|
+
```tsx
|
|
299
|
+
import { useEffect, useRef } from 'react';
|
|
300
|
+
import '@jaaq/jaaq-sdk-js/ui/webcomponents';
|
|
301
|
+
import type { JaaqVideoPlayerElement } from '@jaaq/jaaq-sdk-js/ui/webcomponents';
|
|
302
|
+
|
|
303
|
+
function VideoComponent() {
|
|
304
|
+
const playerRef = useRef<JaaqVideoPlayerElement>(null);
|
|
63
305
|
|
|
64
306
|
useEffect(() => {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
307
|
+
const player = playerRef.current;
|
|
308
|
+
if (!player) return;
|
|
309
|
+
|
|
310
|
+
const handlePlay = () => console.log('Playing');
|
|
311
|
+
const handleLoaded = (e: Event) => {
|
|
312
|
+
console.log('Loaded:', (e as CustomEvent).detail);
|
|
313
|
+
};
|
|
314
|
+
|
|
315
|
+
player.addEventListener('jaaq:play', handlePlay);
|
|
316
|
+
player.addEventListener('jaaq:loaded', handleLoaded);
|
|
317
|
+
|
|
318
|
+
return () => {
|
|
319
|
+
player.removeEventListener('jaaq:play', handlePlay);
|
|
320
|
+
player.removeEventListener('jaaq:loaded', handleLoaded);
|
|
321
|
+
};
|
|
322
|
+
}, []);
|
|
323
|
+
|
|
324
|
+
return (
|
|
325
|
+
<jaaq-video-player
|
|
326
|
+
ref={playerRef}
|
|
327
|
+
video-id="your-video-id"
|
|
328
|
+
api-key="your-api-key"
|
|
329
|
+
client-id="your-client-id"
|
|
330
|
+
autoplay="false"
|
|
331
|
+
width="100%"
|
|
332
|
+
/>
|
|
333
|
+
);
|
|
334
|
+
}
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
Programmatic control in React:
|
|
338
|
+
|
|
339
|
+
```tsx
|
|
340
|
+
playerRef.current?.play();
|
|
341
|
+
playerRef.current?.pause();
|
|
342
|
+
playerRef.current?.setVolume(0.5);
|
|
343
|
+
const state = playerRef.current?.getState();
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
#### Why Use Web Components?
|
|
347
|
+
|
|
348
|
+
- 🔒 **Shadow DOM** - Style encapsulation, no CSS conflicts
|
|
349
|
+
- 🌐 **Framework-agnostic** - Works with React, Vue, Angular, vanilla JS, any framework
|
|
350
|
+
- 📦 **Standards-based** - W3C Custom Elements API, no framework overhead
|
|
351
|
+
- ♿ **Declarative** - Use as simple HTML elements
|
|
352
|
+
- 🎯 **Clean API** - Attributes for configuration, properties for objects
|
|
353
|
+
- 🔧 **Single implementation** - One codebase maintained in one place
|
|
354
|
+
- 🚀 **Future-proof** - Native browser standard, here to stay
|
|
355
|
+
|
|
356
|
+
### UI Features
|
|
357
|
+
|
|
358
|
+
All video players include:
|
|
359
|
+
|
|
360
|
+
- ▶️ Custom video controls (play/pause, progress bar, volume, fullscreen)
|
|
361
|
+
- 🎬 HLS streaming support (adaptive bitrate with hls.js)
|
|
362
|
+
- 📹 MP4 playback support
|
|
363
|
+
- 🎨 Modern, responsive design
|
|
364
|
+
- ⚡ Loading states and error handling
|
|
365
|
+
- 📊 Event system for tracking player state
|
|
366
|
+
- 📱 Mobile-friendly touch controls
|
|
367
|
+
|
|
368
|
+
## CDN Usage (No Build Step)
|
|
369
|
+
|
|
370
|
+
Use JAAQ SDK directly in the browser without npm or build tools. All files are available from our CDN:
|
|
371
|
+
|
|
372
|
+
**Base URL:** `https://cdn.jaaq.app/jaaq-sdk-js/latest/`
|
|
373
|
+
|
|
374
|
+
### Web Components (Recommended)
|
|
375
|
+
|
|
376
|
+
The easiest way to embed video players. Bundled version includes hls.js:
|
|
377
|
+
|
|
378
|
+
```html
|
|
379
|
+
<!DOCTYPE html>
|
|
380
|
+
<html>
|
|
381
|
+
<head>
|
|
382
|
+
<script src="https://cdn.jaaq.app/jaaq-sdk-js/latest/ui/webcomponents/jaaq-webcomponents-bundled.min.js"></script>
|
|
383
|
+
</head>
|
|
384
|
+
<body>
|
|
385
|
+
<jaaq-video-player video-id="your-video-id" api-key="your-api-key" client-id="your-client-id"> </jaaq-video-player>
|
|
386
|
+
</body>
|
|
387
|
+
</html>
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
See [Web Components section](#web-components-native-custom-elements) for full documentation.
|
|
391
|
+
|
|
392
|
+
### Vanilla UI Player
|
|
393
|
+
|
|
394
|
+
For programmatic control with the vanilla JavaScript player:
|
|
395
|
+
|
|
396
|
+
```html
|
|
397
|
+
<!DOCTYPE html>
|
|
398
|
+
<html>
|
|
399
|
+
<head>
|
|
400
|
+
<script src="https://cdn.jaaq.app/jaaq-sdk-js/latest/ui/jaaq-ui-bundled.min.js"></script>
|
|
401
|
+
</head>
|
|
402
|
+
<body>
|
|
403
|
+
<div id="player-container"></div>
|
|
404
|
+
<script>
|
|
405
|
+
const container = document.getElementById('player-container');
|
|
406
|
+
const player = new JaaqUI.JaaqVideoPlayer(container, {
|
|
407
|
+
apiKey: 'your-api-key',
|
|
408
|
+
clientId: 'your-client-id',
|
|
409
|
+
videoId: 'your-video-id',
|
|
410
|
+
autoplay: false,
|
|
69
411
|
});
|
|
70
|
-
const resp = await client.videos.getById(id);
|
|
71
|
-
const url = resp.video.videoUrl;
|
|
72
|
-
videoRef.current.src = url;
|
|
73
|
-
})();
|
|
74
|
-
}, [id]);
|
|
75
412
|
|
|
413
|
+
player.on('loaded', (video) => console.log('Video loaded:', video));
|
|
414
|
+
player.on('play', () => console.log('Playing'));
|
|
415
|
+
</script>
|
|
416
|
+
</body>
|
|
417
|
+
</html>
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
See [Vanilla UI Player Configuration](#vanilla-ui-player-configuration) for all options.
|
|
421
|
+
|
|
422
|
+
### Core SDK
|
|
423
|
+
|
|
424
|
+
Use the core SDK for API access without UI components:
|
|
425
|
+
|
|
426
|
+
```html
|
|
427
|
+
<!DOCTYPE html>
|
|
428
|
+
<html>
|
|
429
|
+
<head>
|
|
430
|
+
<script src="https://cdn.jaaq.app/jaaq-sdk-js/latest/jaaq-sdk.min.js"></script>
|
|
431
|
+
</head>
|
|
432
|
+
<body>
|
|
433
|
+
<script>
|
|
434
|
+
const client = JaaqSDK.createJaaqClient({
|
|
435
|
+
apiKey: 'your-api-key',
|
|
436
|
+
clientId: 'your-client-id',
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
async function loadVideo() {
|
|
440
|
+
const response = await client.videos.getById('video-id');
|
|
441
|
+
console.log('Video:', response.video);
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
loadVideo();
|
|
445
|
+
</script>
|
|
446
|
+
</body>
|
|
447
|
+
</html>
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
### React Components (UMD)
|
|
451
|
+
|
|
452
|
+
Use React components from CDN without npm:
|
|
453
|
+
|
|
454
|
+
```html
|
|
455
|
+
<!DOCTYPE html>
|
|
456
|
+
<html>
|
|
457
|
+
<head>
|
|
458
|
+
<script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
|
|
459
|
+
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
|
|
460
|
+
<script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
|
|
461
|
+
<script src="https://cdn.jaaq.app/jaaq-sdk-js/latest/ui/react/jaaq-ui-react.min.js"></script>
|
|
462
|
+
</head>
|
|
463
|
+
<body>
|
|
464
|
+
<div id="root"></div>
|
|
465
|
+
<script>
|
|
466
|
+
const { VideoPlayer } = JaaqUIReact;
|
|
467
|
+
const root = ReactDOM.createRoot(document.getElementById('root'));
|
|
468
|
+
|
|
469
|
+
root.render(
|
|
470
|
+
React.createElement(VideoPlayer, {
|
|
471
|
+
videoId: 'your-video-id',
|
|
472
|
+
apiKey: 'your-api-key',
|
|
473
|
+
clientId: 'your-client-id',
|
|
474
|
+
autoplay: false,
|
|
475
|
+
}),
|
|
476
|
+
);
|
|
477
|
+
</script>
|
|
478
|
+
</body>
|
|
479
|
+
</html>
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
See [React Video Player](#react-video-player) for component props and examples.
|
|
483
|
+
|
|
484
|
+
### Embed via Iframe
|
|
485
|
+
|
|
486
|
+
The simplest integration - just use an iframe:
|
|
487
|
+
|
|
488
|
+
```html
|
|
489
|
+
<iframe
|
|
490
|
+
src="https://cdn.jaaq.app/jaaq-sdk-js/latest/embed/embed.html?apiKey=YOUR_API_KEY&clientId=YOUR_CLIENT_ID&videoId=YOUR_VIDEO_ID"
|
|
491
|
+
width="800"
|
|
492
|
+
height="450"
|
|
493
|
+
frameborder="0"
|
|
494
|
+
allowfullscreen
|
|
495
|
+
>
|
|
496
|
+
</iframe>
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
**Control via postMessage:**
|
|
500
|
+
|
|
501
|
+
```javascript
|
|
502
|
+
const iframe = document.querySelector('iframe');
|
|
503
|
+
|
|
504
|
+
iframe.contentWindow.postMessage(
|
|
505
|
+
{
|
|
506
|
+
type: 'jaaq-player-command',
|
|
507
|
+
command: 'play',
|
|
508
|
+
},
|
|
509
|
+
'*',
|
|
510
|
+
);
|
|
511
|
+
|
|
512
|
+
window.addEventListener('message', (event) => {
|
|
513
|
+
if (event.data?.type === 'jaaq-player-event') {
|
|
514
|
+
console.log('Event:', event.data.event, event.data.data);
|
|
515
|
+
}
|
|
516
|
+
});
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
See [Embed iframe URL Parameters](#embed-iframe-url-parameters) for all available options.
|
|
520
|
+
|
|
521
|
+
### Available CDN Files
|
|
522
|
+
|
|
523
|
+
| File | Description | Global Variable |
|
|
524
|
+
| ---------------------------------------------------- | -------------------------------- | ------------------- |
|
|
525
|
+
| `jaaq-sdk.min.js` | Core SDK | `JaaqSDK` |
|
|
526
|
+
| `ui/jaaq-ui-bundled.min.js` | Vanilla UI + hls.js | `JaaqUI` |
|
|
527
|
+
| `ui/jaaq-ui.min.js` | Vanilla UI (requires hls.js) | `JaaqUI` |
|
|
528
|
+
| `ui/react/jaaq-ui-react.min.js` | React components | `JaaqUIReact` |
|
|
529
|
+
| `ui/webcomponents/jaaq-webcomponents-bundled.min.js` | Web components + hls.js | `JaaqWebComponents` |
|
|
530
|
+
| `ui/webcomponents/jaaq-webcomponents.min.js` | Web components (requires hls.js) | `JaaqWebComponents` |
|
|
531
|
+
| `embed/embed.html` | Embeddable iframe player | N/A |
|
|
532
|
+
|
|
533
|
+
**Note:** Bundled versions include hls.js and have no external dependencies. Non-bundled versions require loading hls.js separately.
|
|
534
|
+
|
|
535
|
+
## API Reference
|
|
536
|
+
|
|
537
|
+
Complete reference for all SDK components and their configuration options.
|
|
538
|
+
|
|
539
|
+
### Vanilla UI Player Configuration
|
|
540
|
+
|
|
541
|
+
The `JaaqVideoPlayer` class accepts these configuration options:
|
|
542
|
+
|
|
543
|
+
| Option | Type | Required | Default | Description |
|
|
544
|
+
| ----------- | ------------ | ----------- | -------- | ------------------------------------------ |
|
|
545
|
+
| `videoId` | `string` | Yes | - | Video ID to load |
|
|
546
|
+
| `apiKey` | `string` | Conditional | - | API key (required if no client provided) |
|
|
547
|
+
| `clientId` | `string` | Conditional | - | Client ID (required if no client provided) |
|
|
548
|
+
| `client` | `JaaqClient` | Conditional | - | Existing JaaqClient instance |
|
|
549
|
+
| `baseUrl` | `string` | No | API URL | Custom API base URL |
|
|
550
|
+
| `autoplay` | `boolean` | No | `false` | Auto-play video on load |
|
|
551
|
+
| `width` | `string` | No | `'100%'` | CSS width of player container |
|
|
552
|
+
| `height` | `string` | No | `'auto'` | CSS height of player container |
|
|
553
|
+
| `className` | `string` | No | `''` | Additional CSS class name(s) for player |
|
|
554
|
+
|
|
555
|
+
**Usage:**
|
|
556
|
+
|
|
557
|
+
```javascript
|
|
558
|
+
import { JaaqVideoPlayer } from '@jaaq/jaaq-sdk-js/ui';
|
|
559
|
+
|
|
560
|
+
const player = new JaaqVideoPlayer('#container', {
|
|
561
|
+
videoId: 'your-video-id',
|
|
562
|
+
apiKey: 'your-api-key',
|
|
563
|
+
clientId: 'your-client-id',
|
|
564
|
+
autoplay: false,
|
|
565
|
+
width: '800px',
|
|
566
|
+
height: '450px',
|
|
567
|
+
className: 'my-custom-player',
|
|
568
|
+
});
|
|
569
|
+
|
|
570
|
+
player.on('loaded', (video) => console.log('Video loaded:', video));
|
|
571
|
+
player.on('play', () => console.log('Playing'));
|
|
572
|
+
player.play();
|
|
573
|
+
```
|
|
574
|
+
|
|
575
|
+
### Embed iframe URL Parameters
|
|
576
|
+
|
|
577
|
+
The embeddable iframe player accepts these URL query parameters:
|
|
578
|
+
|
|
579
|
+
| Parameter | Type | Required | Default | Description |
|
|
580
|
+
| ---------- | -------- | -------- | ------- | ----------------------------------- |
|
|
581
|
+
| `apiKey` | `string` | Yes | - | Your JAAQ API key |
|
|
582
|
+
| `clientId` | `string` | Yes | - | Your client identifier |
|
|
583
|
+
| `videoId` | `string` | Yes | - | Video ID to load |
|
|
584
|
+
| `autoplay` | `string` | No | `false` | Auto-play video ('true' or 'false') |
|
|
585
|
+
| `width` | `string` | No | `100%` | CSS width of player |
|
|
586
|
+
| `height` | `string` | No | `100%` | CSS height of player |
|
|
587
|
+
| `baseUrl` | `string` | No | API URL | Custom API base URL |
|
|
588
|
+
|
|
589
|
+
**Usage:**
|
|
590
|
+
|
|
591
|
+
```html
|
|
592
|
+
<iframe
|
|
593
|
+
src="https://cdn.jaaq.app/jaaq-sdk-js/latest/embed/embed.html?apiKey=YOUR_API_KEY&clientId=YOUR_CLIENT_ID&videoId=YOUR_VIDEO_ID&autoplay=false"
|
|
594
|
+
width="800"
|
|
595
|
+
height="450"
|
|
596
|
+
frameborder="0"
|
|
597
|
+
allowfullscreen
|
|
598
|
+
>
|
|
599
|
+
</iframe>
|
|
600
|
+
```
|
|
601
|
+
|
|
602
|
+
### Player Methods
|
|
603
|
+
|
|
604
|
+
All player implementations (Vanilla, Web Component, React) provide these methods:
|
|
605
|
+
|
|
606
|
+
| Method | Parameters | Returns | Description |
|
|
607
|
+
| ------------------- | ---------------- | ------------- | ------------------------------------------ |
|
|
608
|
+
| `play()` | - | `void` | Start or resume video playback |
|
|
609
|
+
| `pause()` | - | `void` | Pause video playback |
|
|
610
|
+
| `seek(time)` | `time: number` | `void` | Seek to specific time in seconds |
|
|
611
|
+
| `setVolume(volume)` | `volume: number` | `void` | Set volume level (0-1) |
|
|
612
|
+
| `toggleMute()` | - | `void` | Toggle audio mute state |
|
|
613
|
+
| `getState()` | - | `PlayerState` | Get current player state object |
|
|
614
|
+
| `destroy()` | - | `void` | Clean up player and remove event listeners |
|
|
615
|
+
|
|
616
|
+
**Vanilla Player Example:**
|
|
617
|
+
|
|
618
|
+
```javascript
|
|
619
|
+
player.play();
|
|
620
|
+
player.seek(30);
|
|
621
|
+
player.setVolume(0.5);
|
|
622
|
+
const state = player.getState();
|
|
623
|
+
```
|
|
624
|
+
|
|
625
|
+
**Web Component Example:**
|
|
626
|
+
|
|
627
|
+
```javascript
|
|
628
|
+
const player = document.querySelector('jaaq-video-player');
|
|
629
|
+
player.play();
|
|
630
|
+
player.seek(30);
|
|
631
|
+
player.setVolume(0.5);
|
|
632
|
+
const state = player.getState();
|
|
633
|
+
```
|
|
634
|
+
|
|
635
|
+
**React Example:**
|
|
636
|
+
|
|
637
|
+
```typescript
|
|
638
|
+
const playerRef = useRef<VideoPlayerHandle>(null);
|
|
639
|
+
playerRef.current?.play();
|
|
640
|
+
playerRef.current?.seek(30);
|
|
641
|
+
playerRef.current?.setVolume(0.5);
|
|
642
|
+
const state = playerRef.current?.getState();
|
|
643
|
+
```
|
|
644
|
+
|
|
645
|
+
### Player Events
|
|
646
|
+
|
|
647
|
+
All player implementations emit these events:
|
|
648
|
+
|
|
649
|
+
| Event | Payload Type | Description |
|
|
650
|
+
| ------------------ | ------------ | ------------------------------------------------ |
|
|
651
|
+
| `play` | `void` | Fired when video playback starts |
|
|
652
|
+
| `pause` | `void` | Fired when video playback pauses |
|
|
653
|
+
| `timeupdate` | `number` | Fired during playback, provides current time (s) |
|
|
654
|
+
| `volumechange` | `number` | Fired when volume changes, provides level (0-1) |
|
|
655
|
+
| `ended` | `void` | Fired when video playback completes |
|
|
656
|
+
| `error` | `Error` | Fired when an error occurs |
|
|
657
|
+
| `loaded` | `VideoDTO` | Fired when video metadata loads successfully |
|
|
658
|
+
| `fullscreenchange` | `boolean` | Fired when fullscreen state changes |
|
|
659
|
+
|
|
660
|
+
**Vanilla Player Event Handling:**
|
|
661
|
+
|
|
662
|
+
```javascript
|
|
663
|
+
player.on('play', () => console.log('Playing'));
|
|
664
|
+
player.on('pause', () => console.log('Paused'));
|
|
665
|
+
player.on('timeupdate', (time) => console.log('Current time:', time));
|
|
666
|
+
player.on('loaded', (video) => console.log('Video:', video));
|
|
667
|
+
player.on('error', (error) => console.error('Error:', error));
|
|
668
|
+
```
|
|
669
|
+
|
|
670
|
+
**Web Component Event Handling:**
|
|
671
|
+
|
|
672
|
+
```javascript
|
|
673
|
+
const player = document.querySelector('jaaq-video-player');
|
|
674
|
+
player.addEventListener('jaaq:play', () => console.log('Playing'));
|
|
675
|
+
player.addEventListener('jaaq:pause', () => console.log('Paused'));
|
|
676
|
+
player.addEventListener('jaaq:timeupdate', (e) => console.log('Time:', e.detail));
|
|
677
|
+
player.addEventListener('jaaq:loaded', (e) => console.log('Video:', e.detail));
|
|
678
|
+
player.addEventListener('jaaq:error', (e) => console.error('Error:', e.detail));
|
|
679
|
+
```
|
|
680
|
+
|
|
681
|
+
**React Event Handling:**
|
|
682
|
+
|
|
683
|
+
```typescript
|
|
684
|
+
<VideoPlayer
|
|
685
|
+
videoId="video-id"
|
|
686
|
+
apiKey="api-key"
|
|
687
|
+
clientId="client-id"
|
|
688
|
+
onPlay={() => console.log('Playing')}
|
|
689
|
+
onPause={() => console.log('Paused')}
|
|
690
|
+
onTimeUpdate={(time) => console.log('Time:', time)}
|
|
691
|
+
onLoaded={(video) => console.log('Video:', video)}
|
|
692
|
+
onError={(error) => console.error('Error:', error)}
|
|
693
|
+
/>
|
|
694
|
+
```
|
|
695
|
+
|
|
696
|
+
**Embed iframe Event Handling (postMessage):**
|
|
697
|
+
|
|
698
|
+
```javascript
|
|
699
|
+
window.addEventListener('message', (event) => {
|
|
700
|
+
if (event.data?.type === 'jaaq-player-event') {
|
|
701
|
+
console.log('Event:', event.data.event, event.data.data);
|
|
702
|
+
}
|
|
703
|
+
});
|
|
704
|
+
```
|
|
705
|
+
|
|
706
|
+
### Player State Object
|
|
707
|
+
|
|
708
|
+
The `getState()` method returns a `PlayerState` object with these properties:
|
|
709
|
+
|
|
710
|
+
| Property | Type | Description |
|
|
711
|
+
| -------------- | ------------------ | ----------------------------------------------- |
|
|
712
|
+
| `isPlaying` | `boolean` | Whether video is currently playing |
|
|
713
|
+
| `currentTime` | `number` | Current playback time in seconds |
|
|
714
|
+
| `duration` | `number` | Total video duration in seconds |
|
|
715
|
+
| `volume` | `number` | Current volume level (0-1) |
|
|
716
|
+
| `isMuted` | `boolean` | Whether audio is muted |
|
|
717
|
+
| `isFullscreen` | `boolean` | Whether player is in fullscreen mode |
|
|
718
|
+
| `isLoading` | `boolean` | Whether video is currently loading |
|
|
719
|
+
| `error` | `string \| null` | Error message if error occurred, null otherwise |
|
|
720
|
+
| `videoData` | `VideoDTO \| null` | Loaded video metadata, null if not loaded |
|
|
721
|
+
|
|
722
|
+
**Example:**
|
|
723
|
+
|
|
724
|
+
```javascript
|
|
725
|
+
const state = player.getState();
|
|
726
|
+
console.log('Playing:', state.isPlaying);
|
|
727
|
+
console.log('Current time:', state.currentTime);
|
|
728
|
+
console.log('Duration:', state.duration);
|
|
729
|
+
console.log('Volume:', state.volume);
|
|
730
|
+
console.log('Muted:', state.isMuted);
|
|
731
|
+
console.log('Fullscreen:', state.isFullscreen);
|
|
732
|
+
console.log('Loading:', state.isLoading);
|
|
733
|
+
if (state.error) {
|
|
734
|
+
console.error('Error:', state.error);
|
|
735
|
+
}
|
|
736
|
+
if (state.videoData) {
|
|
737
|
+
console.log('Video ID:', state.videoData.id);
|
|
738
|
+
console.log('Title:', state.videoData.question || state.videoData.description);
|
|
739
|
+
}
|
|
740
|
+
```
|
|
741
|
+
|
|
742
|
+
### React Example: Using VideoPlayer Component
|
|
743
|
+
|
|
744
|
+
The recommended approach is to use the `VideoPlayer` component, which handles all video playback, HLS streaming, and provides custom controls:
|
|
745
|
+
|
|
746
|
+
```typescript
|
|
747
|
+
import { VideoPlayer } from '@jaaq/jaaq-sdk-js/ui/react';
|
|
748
|
+
|
|
749
|
+
const API_KEY = import.meta.env.VITE_JAAQ_API_KEY;
|
|
750
|
+
const CLIENT_ID = import.meta.env.VITE_JAAQ_CLIENT_ID;
|
|
751
|
+
|
|
752
|
+
export default function VideoExample({ videoId }: { videoId: string }) {
|
|
76
753
|
return (
|
|
77
|
-
<
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
754
|
+
<VideoPlayer
|
|
755
|
+
videoId={videoId}
|
|
756
|
+
apiKey={API_KEY}
|
|
757
|
+
clientId={CLIENT_ID}
|
|
758
|
+
autoplay={false}
|
|
759
|
+
showInfo={true}
|
|
760
|
+
onPlay={() => console.log('Playing')}
|
|
761
|
+
onPause={() => console.log('Paused')}
|
|
762
|
+
onError={(error) => console.error('Error:', error)}
|
|
763
|
+
onLoaded={(video) => console.log('Loaded:', video)}
|
|
81
764
|
/>
|
|
82
765
|
);
|
|
83
766
|
}
|
|
84
767
|
```
|
|
85
768
|
|
|
86
|
-
### React Example:
|
|
769
|
+
### React Example: Using Web Component
|
|
770
|
+
|
|
771
|
+
You can also use the native web component directly in React:
|
|
87
772
|
|
|
88
773
|
```typescript
|
|
89
|
-
import {
|
|
90
|
-
import
|
|
91
|
-
import
|
|
774
|
+
import { useRef, useEffect } from 'react';
|
|
775
|
+
import '@jaaq/jaaq-sdk-js/ui/webcomponents';
|
|
776
|
+
import type { JaaqVideoPlayerElement } from '@jaaq/jaaq-sdk-js/ui/webcomponents';
|
|
92
777
|
|
|
93
|
-
const API_KEY = import.meta.env.VITE_JAAQ_API_KEY
|
|
94
|
-
const CLIENT_ID = import.meta.env.VITE_JAAQ_CLIENT_ID
|
|
778
|
+
const API_KEY = import.meta.env.VITE_JAAQ_API_KEY;
|
|
779
|
+
const CLIENT_ID = import.meta.env.VITE_JAAQ_CLIENT_ID;
|
|
95
780
|
|
|
96
|
-
export default function VideoExample({
|
|
97
|
-
const
|
|
781
|
+
export default function VideoExample({ videoId }: { videoId: string }) {
|
|
782
|
+
const playerRef = useRef<JaaqVideoPlayerElement>(null);
|
|
98
783
|
|
|
99
784
|
useEffect(() => {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
hls = new Hls();
|
|
111
|
-
hls.loadSource(url);
|
|
112
|
-
hls.attachMedia(video);
|
|
113
|
-
}
|
|
114
|
-
})();
|
|
785
|
+
const player = playerRef.current;
|
|
786
|
+
if (!player) return;
|
|
787
|
+
|
|
788
|
+
const handlePlay = () => console.log('Playing');
|
|
789
|
+
const handleLoaded = (e: Event) => {
|
|
790
|
+
console.log('Loaded:', (e as CustomEvent).detail);
|
|
791
|
+
};
|
|
792
|
+
|
|
793
|
+
player.addEventListener('jaaq:play', handlePlay);
|
|
794
|
+
player.addEventListener('jaaq:loaded', handleLoaded);
|
|
115
795
|
|
|
116
|
-
return () =>
|
|
117
|
-
|
|
796
|
+
return () => {
|
|
797
|
+
player.removeEventListener('jaaq:play', handlePlay);
|
|
798
|
+
player.removeEventListener('jaaq:loaded', handleLoaded);
|
|
799
|
+
};
|
|
800
|
+
}, []);
|
|
118
801
|
|
|
119
802
|
return (
|
|
120
|
-
<video
|
|
121
|
-
ref={
|
|
122
|
-
|
|
123
|
-
|
|
803
|
+
<jaaq-video-player
|
|
804
|
+
ref={playerRef}
|
|
805
|
+
video-id={videoId}
|
|
806
|
+
api-key={API_KEY}
|
|
807
|
+
client-id={CLIENT_ID}
|
|
808
|
+
autoplay="false"
|
|
124
809
|
/>
|
|
125
810
|
);
|
|
126
811
|
}
|
|
127
812
|
```
|
|
128
813
|
|
|
814
|
+
**For more examples**, see the [React examples directory](./examples/react-vite/) which includes working implementations with Vite.
|
|
815
|
+
|
|
129
816
|
## Configuration
|
|
130
817
|
|
|
131
818
|
| Option | Type | Required | Default | Description |
|
|
@@ -136,8 +823,25 @@ export default function VideoExample({ id }: { id: string }) {
|
|
|
136
823
|
| `fetch` | `Function` | No | `globalThis.fetch` | Custom fetch implementation |
|
|
137
824
|
| `timeoutMs` | `number` | No | - | Request timeout in milliseconds |
|
|
138
825
|
|
|
826
|
+
## Architecture
|
|
827
|
+
|
|
828
|
+
The SDK has a layered UI architecture:
|
|
829
|
+
|
|
830
|
+
1. **Vanilla Player** (Internal) - Core implementation with HLS support, controls, events
|
|
831
|
+
2. **Web Components** - Wraps vanilla player with Shadow DOM, primary public API
|
|
832
|
+
3. **React Component** - Thin wrapper around web component for React-friendly API
|
|
833
|
+
|
|
834
|
+
This architecture ensures:
|
|
835
|
+
|
|
836
|
+
- Single source of truth for player logic
|
|
837
|
+
- Framework-agnostic distribution via web components
|
|
838
|
+
- Consistent behavior across all integrations
|
|
839
|
+
- Easy maintenance and updates
|
|
840
|
+
|
|
139
841
|
## Resources
|
|
140
842
|
|
|
843
|
+
- [Browser Examples](./examples/browser/README.md) - HTML examples for web components and vanilla JS
|
|
844
|
+
- [React Examples](./examples/react-vite/README.md) - React + Vite integration examples
|
|
141
845
|
- [Development Guide](./DEVELOPMENT.md) - For SDK contributors and developers
|
|
142
846
|
- [Release Notes](./RELEASE.md) - Version history and changelog
|
|
143
847
|
|