@flowplayer/spins 0.6.0 → 0.7.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.
Files changed (2) hide show
  1. package/README.md +316 -61
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -2,10 +2,12 @@
2
2
 
3
3
  A TypeScript library for creating Flowplayer playlist components optimized for short-form video content like Reels and Shorts.
4
4
 
5
+ ## Quick Start
6
+
5
7
  ```typescript
6
8
  import { createSpins } from "@flowplayer/spins";
7
9
 
8
- const spinsContainer = createSpins({
10
+ const spinsContainer = createSpins({
9
11
  playlist: "your-playlist-id",
10
12
  token: "your-token",
11
13
  lang: "en",
@@ -13,30 +15,6 @@ const spinsContainer = createSpins({
13
15
  document.body.appendChild(spinsContainer);
14
16
  ```
15
17
 
16
- ### React Usage
17
-
18
- ```tsx
19
- import { createSpins, type SpinsConfig } from "@flowplayer/spins";
20
- import { useEffect, useRef } from "react";
21
-
22
- function SpinsPlayer({ playlistId }: { playlistId: string }) {
23
- const containerRef = useRef<HTMLDivElement>(null);
24
-
25
- useEffect(() => {
26
- if (containerRef.current) {
27
- const spinsContainer = createSpins({
28
- playlist: playlistId,
29
- token: "your-token",
30
- lang: "en",
31
- });
32
- containerRef.current.appendChild(spinsContainer);
33
- }
34
- }, [playlistId]);
35
-
36
- return <div ref={containerRef} className="spins-container" />;
37
- }
38
- ```
39
-
40
18
  ## Features
41
19
 
42
20
  - 🎯 **Type-safe** - Built with TypeScript and Zod schema validation
@@ -56,20 +34,76 @@ bun add @flowplayer/spins
56
34
 
57
35
  ## Usage
58
36
 
37
+ ### Basic Usage
38
+
59
39
  ```typescript
60
- import { spins, type SpinsConfig } from "@flowplayer/spins";
40
+ import { createSpins, type SpinsConfig } from "@flowplayer/spins";
61
41
 
62
- // Create a playlist component for short-form content
63
42
  const config: SpinsConfig = {
64
43
  playlist: "your-playlist-id", // or array of SpinItem objects
65
44
  token: "your-flowplayer-token",
66
45
  lang: "en"
67
46
  };
68
47
 
69
- const spinsContainer = spins(config);
48
+ const spinsContainer = createSpins(config);
70
49
  document.body.appendChild(spinsContainer);
71
50
  ```
72
51
 
52
+ ### React Integration
53
+
54
+ ```tsx
55
+ import { createSpins, type SpinsConfig } from "@flowplayer/spins";
56
+ import { useEffect, useRef } from "react";
57
+
58
+ function SpinsPlayer({ playlistId }: { playlistId: string }) {
59
+ const containerRef = useRef<HTMLDivElement>(null);
60
+
61
+ useEffect(() => {
62
+ if (!containerRef.current) return;
63
+
64
+ const spinsContainer = createSpins({
65
+ playlist: playlistId,
66
+ token: "your-token",
67
+ lang: "en",
68
+ });
69
+
70
+ containerRef.current.appendChild(spinsContainer);
71
+
72
+ return () => {
73
+ spinsContainer.remove();
74
+ };
75
+ }, [playlistId]);
76
+
77
+ return <div ref={containerRef} className="spins-container" />;
78
+ }
79
+ ```
80
+
81
+ ### With Custom Playlist
82
+
83
+ ```typescript
84
+ import { createSpins, type SpinItem } from "@flowplayer/spins";
85
+
86
+ const customPlaylist: SpinItem[] = [
87
+ {
88
+ url: "https://example.com/video1.mp4",
89
+ title: "First Video",
90
+ poster: "https://example.com/poster1.jpg",
91
+ description: "Description of first video"
92
+ },
93
+ {
94
+ url: { src: "https://example.com/video2.mp4", type: "video/mp4" },
95
+ title: "Second Video",
96
+ poster: "https://example.com/poster2.jpg"
97
+ }
98
+ ];
99
+
100
+ const spinsContainer = createSpins({
101
+ playlist: customPlaylist,
102
+ token: "your-token",
103
+ lang: "en"
104
+ });
105
+ ```
106
+
73
107
  ## Short-Form Video Content
74
108
 
75
109
  This library is specifically designed to handle short-form video playlists, making it easy to create engaging vertical video experiences similar to:
@@ -86,78 +120,298 @@ The component automatically handles playlist loading and provides the structure
86
120
 
87
121
  Creates a Flowplayer playlist component container optimized for short-form video content.
88
122
 
89
- #### Parameters
123
+ #### Configuration Options
90
124
 
91
- - `config.playlist: string | Array<SpinItem>` - The playlist ID or array of spin configurations
92
- - `config.token: string` - Your Flowplayer token
93
- - `config.lang: string` - Language code (e.g., "en", "es")
125
+ ```typescript
126
+ interface SpinsConfig {
127
+ playlist: string | Array<SpinItem>; // Playlist ID or array of SpinItem
128
+ token?: string; // Your Flowplayer token
129
+ lang?: string; // Language code (e.g., "en", "es")
130
+ ui?: number; // UI configuration bitmask
131
+ ima?: PlayerIMAConfig; // IMA ads configuration
132
+ adsFrequency?: number; // Show ads every Nth spin (default: 10)
133
+ share?: ShareConfig; // Share plugin configuration
134
+ consent?: number; // Consent plugin configuration
135
+ plugins?: string[]; // List of plugins to enable
136
+ }
137
+ ```
94
138
 
95
139
  #### Returns
96
140
 
97
- Returns a `SpinsContainer` (extends `HTMLElement`) with event handling capabilities:
98
- - `on(event, handler)` - Subscribe to events
99
- - `off(event, handler)` - Unsubscribe from events
100
- - `addSpins(spins: SpinItem[])` - Adds more spins dynamically
141
+ A `SpinsContainer` instance (extends `HTMLElement`) with the following methods:
142
+
143
+ ##### Event Handling
144
+
145
+ ```typescript
146
+ // Listen to spin lifecycle events
147
+ spinsContainer.on(spinEvents.SPIN_CREATED, (e) => {
148
+ console.log('Spin created:', e.detail.config, e.detail.index);
149
+ });
150
+
151
+ spinsContainer.on(spinEvents.SPIN_IN_VIEWPORT, (e) => {
152
+ console.log('Spin in viewport:', e.detail.index);
153
+ });
154
+
155
+ // Listen to player events (media events)
156
+ spinsContainer.onPlayerEvent(mediaEvents.PLAY, (e) => {
157
+ console.log('Video playing:', e.detail.spinIndex, e.detail.currentTime);
158
+ });
159
+
160
+ spinsContainer.onPlayerEvent(mediaEvents.ENDED, (e) => {
161
+ console.log('Video ended:', e.detail.spinIndex);
162
+ });
163
+
164
+ // Listen to ad events
165
+ spinsContainer.onPlayerEvent(adEvents.AD_STARTED, (e) => {
166
+ console.log('Ad started:', e.detail.spinIndex);
167
+ });
168
+
169
+ // Remove event listeners
170
+ spinsContainer.off(spinEvents.SPIN_CREATED, handler);
171
+ spinsContainer.offPlayerEvent(mediaEvents.PLAY, handler);
172
+ ```
173
+
174
+ ##### Dynamic Content
101
175
 
102
- #### Events
176
+ ```typescript
177
+ // Add more spins dynamically
178
+ spinsContainer.addSpins([
179
+ {
180
+ url: "https://example.com/video3.mp4",
181
+ title: "New Video",
182
+ poster: "https://example.com/poster3.jpg"
183
+ }
184
+ ]);
185
+ ```
186
+
187
+ ### Events
188
+
189
+ #### Spin Events (`spinEvents`)
103
190
 
104
191
  - `SPIN_CREATED` - Fired when a new spin is created
192
+ - `detail.config`: SpinItem configuration
193
+ - `detail.spin`: The spin container HTMLElement
194
+ - `detail.index`: Spin index
195
+
105
196
  - `SPIN_IN_VIEWPORT` - Fired when a spin enters the viewport
197
+ - `detail.config`: SpinItem configuration
198
+ - `detail.spin`: The spin container HTMLElement
199
+ - `detail.index`: Spin index
200
+
201
+ #### Media Events (`mediaEvents`)
202
+
203
+ - `PLAY` - Playback started/resumed
204
+ - `PAUSE` - Playback paused
205
+ - `PLAYING` - Actively playing
206
+ - `WAITING` - Buffering
207
+ - `CAN_PLAY` - Ready to play
208
+ - `TIME_UPDATE` - Playback position changed
209
+ - `SEEKING` - User seeking
210
+ - `ENDED` - Playback ended
211
+
212
+ All media events include:
213
+ - `detail.spinIndex`: Index of the spin
214
+ - `detail.currentTime`: Current playback time in seconds
215
+ - `detail.duration`: Video duration in seconds
216
+ - `detail.mediaId`: Media ID (if available)
217
+ - `detail.url`: Full URL of the media
218
+
219
+ #### Ad Events (`adEvents`)
220
+
221
+ - `AD_STARTED` - Ad playback started
222
+ - `AD_COMPLETED` - Ad finished playing
223
+ - `AD_PROGRESS` - Ad playback progress
224
+ - `AD_PAUSED` - Ad paused
225
+ - `AD_RESUMED` - Ad resumed
226
+ - `AD_SKIPPED` - Ad skipped by user
227
+ - `AD_ERROR` - Ad error occurred
228
+ - `AD_REQUEST_ERROR` - Ad request failed
229
+ - `AD_PLAYBACK_ERROR` - Ad playback error
230
+ - `AD_BREAK_COMPLETED` - Ad break finished
231
+ - `AD_TEARDOWN` - Ad cleanup
232
+ - `AD_MUTED` - Ad muted
233
+ - `AD_VOLUME_CHANGED` - Ad volume changed
234
+ - `AD_PREROLL_FINSIHED` - Preroll ad finished
235
+
236
+ All ad events include:
237
+ - `detail.spinIndex`: Index of the spin where the ad is shown
106
238
 
107
239
  ## TypeScript Support
108
240
 
109
- The library exports TypeScript types for full type safety:
241
+ The library is fully typed with TypeScript. Import types for full type safety:
110
242
 
111
243
  ```typescript
112
- import { type SpinsConfig, type SpinItem, type SpinsContainer } from "@flowplayer/spins";
244
+ import {
245
+ createSpins,
246
+ createAdPlayer,
247
+ spinEvents,
248
+ mediaEvents,
249
+ adEvents,
250
+ type SpinsConfig,
251
+ type SpinItem,
252
+ type SpinsContainer,
253
+ type SpinsAdPlayer,
254
+ type SpinsAdPlayerConfig,
255
+ type SpinEvent,
256
+ type MediaEvent,
257
+ type AdEvent,
258
+ type PlayerEvent,
259
+ type SpinEventData,
260
+ type MediaEventData,
261
+ type AdEventData,
262
+ type PlayerEventsDetailMap,
263
+ type AdEventsDetailMap,
264
+ } from "@flowplayer/spins";
113
265
  ```
114
266
 
115
- ### `SpinsConfig`
267
+ ### Key Type Definitions
116
268
 
117
- The main configuration interface:
269
+ #### `SpinsConfig`
270
+
271
+ Main configuration for creating a spins container:
118
272
 
119
273
  ```typescript
120
274
  interface SpinsConfig {
121
275
  playlist: string | Array<SpinItem>;
122
- token: string;
123
- lang: string;
276
+ token?: string;
277
+ lang?: string;
278
+ ui?: number;
279
+ ima?: PlayerIMAConfig;
280
+ adsFrequency?: number;
281
+ share?: ShareConfig;
282
+ consent?: number;
283
+ plugins?: string[];
124
284
  }
125
285
  ```
126
286
 
127
- ### `SpinItem`
287
+ #### `SpinItem`
128
288
 
129
- Individual spin configuration:
289
+ Individual video configuration:
130
290
 
131
291
  ```typescript
132
292
  interface SpinItem {
133
- url: string | { src: string; type: string }
134
- title?: string
135
- poster?: string
136
- description?: string
293
+ url: string | { src: string; type: string };
294
+ title?: string;
295
+ poster?: string;
296
+ description?: string;
297
+ subtitles?: SubtitlesConfig;
137
298
  }
138
299
  ```
139
300
 
140
- ## CSS Styling
301
+ #### `SpinsContainer`
141
302
 
142
- The component includes default CSS styling optimized for short-form video content. Styles are imported from:
143
- You can override styles by targeting the spins container and its children:
303
+ The container element with event handling:
144
304
 
145
- ```css
146
- .fp-spins-container {
147
- /* Base spins container styles */
305
+ ```typescript
306
+ interface SpinsContainer extends HTMLElement {
307
+ on(event: SpinEvent, handler: (e: CustomEvent<SpinEventData>) => void): void;
308
+ off(event: SpinEvent, handler: (e: CustomEvent<SpinEventData>) => void): void;
309
+ onPlayerEvent<K extends PlayerEvent>(
310
+ event: K,
311
+ handler: (e: CustomEvent<PlayerEventsDetailMap[K]>) => void
312
+ ): void;
313
+ offPlayerEvent<K extends PlayerEvent>(
314
+ event: K,
315
+ handler: (e: CustomEvent<PlayerEventsDetailMap[K]>) => void
316
+ ): void;
317
+ addSpins(spins: SpinItem[]): void;
318
+ }
319
+ ```
320
+
321
+ #### Event Data Types
322
+
323
+ ```typescript
324
+ interface SpinEventData {
325
+ config: SpinItem;
326
+ spin: HTMLElement;
327
+ index: number;
148
328
  }
149
329
 
150
- flowplayer-spin {
151
- /* Individual spin container styles */
330
+ interface MediaEventData {
331
+ spinIndex: number;
332
+ duration?: number;
333
+ currentTime: number;
334
+ mediaId?: string;
335
+ url: string;
152
336
  }
337
+
338
+ type AdEventData<K extends AdEvent> = {
339
+ spinIndex: number;
340
+ } & AdEventsDetailMap[K];
153
341
  ```
154
342
 
155
- ## Development
343
+ ## Advanced Usage
156
344
 
157
- ### Prerequisites
345
+ ### Listening to All Events
158
346
 
159
- - [Bun](https://bun.sh/) runtime
160
- - TypeScript 5+
347
+ ```typescript
348
+ import {
349
+ createSpins,
350
+ spinEvents,
351
+ mediaEvents,
352
+ adEvents,
353
+ type SpinEventData,
354
+ type MediaEventData
355
+ } from "@flowplayer/spins";
356
+
357
+ const container = createSpins({
358
+ playlist: "your-playlist-id",
359
+ token: "your-token",
360
+ lang: "en",
361
+ adsFrequency: 5 // Show ads every 5th spin
362
+ });
363
+
364
+ // Spin lifecycle events
365
+ container.on(spinEvents.SPIN_CREATED, (e) => {
366
+ console.log(`Spin ${e.detail.index} created:`, e.detail.config);
367
+ });
368
+
369
+ container.on(spinEvents.SPIN_IN_VIEWPORT, (e) => {
370
+ console.log(`Spin ${e.detail.index} is now visible`);
371
+ });
372
+
373
+ // Media playback events
374
+ container.onPlayerEvent(mediaEvents.PLAY, (e) => {
375
+ console.log(`Playing spin ${e.detail.spinIndex}`);
376
+ });
377
+
378
+ container.onPlayerEvent(mediaEvents.TIME_UPDATE, (e) => {
379
+ console.log(`Progress: ${e.detail.currentTime}/${e.detail.duration}`);
380
+ });
381
+
382
+ container.onPlayerEvent(mediaEvents.ENDED, (e) => {
383
+ console.log(`Spin ${e.detail.spinIndex} finished`);
384
+ });
385
+
386
+ // Ad events
387
+ container.onPlayerEvent(adEvents.AD_STARTED, (e) => {
388
+ console.log(`Ad started at spin ${e.detail.spinIndex}`);
389
+ });
390
+
391
+ container.onPlayerEvent(adEvents.AD_COMPLETED, (e) => {
392
+ console.log(`Ad completed at spin ${e.detail.spinIndex}`);
393
+ });
394
+
395
+ document.body.appendChild(container);
396
+ ```
397
+
398
+ ### Advertising Configuration
399
+
400
+ ```typescript
401
+ import { createSpins } from "@flowplayer/spins";
402
+
403
+ const container = createSpins({
404
+ playlist: "your-playlist-id",
405
+ token: "your-token",
406
+ lang: "en",
407
+ adsFrequency: 3, // Show ads every 3rd spin
408
+ ima: {
409
+ ads: [{
410
+ adTag: "https://pubads.g.doubleclick.net/gampad/ads?...",
411
+ time: 0
412
+ }]}
413
+ });
414
+ ```
161
415
 
162
416
  ## Contributing
163
417
 
@@ -167,6 +421,7 @@ This project uses:
167
421
  - **Vitest** with **Playwright** for browser testing
168
422
  - **Storybook** for component development and documentation
169
423
  - **Lit** for custom web components
424
+ - **Zod** for runtime schema validation
170
425
 
171
426
  ## License
172
427
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@flowplayer/spins",
3
3
  "module": "dist/index.js",
4
- "version": "0.6.0",
4
+ "version": "0.7.0",
5
5
  "type": "module",
6
6
  "types": "./dist/types.d.ts",
7
7
  "exports": {