@hopecloud/jetstream-player 0.3.3 → 0.3.5

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/.eslintrc.cjs ADDED
@@ -0,0 +1,32 @@
1
+ module.exports = {
2
+ env: {
3
+ browser: true,
4
+ es2021: true,
5
+ },
6
+ extends: [
7
+ 'eslint:recommended',
8
+ 'plugin:@typescript-eslint/recommended',
9
+ 'prettier',
10
+ ],
11
+ overrides: [
12
+ {
13
+ env: {
14
+ node: true,
15
+ },
16
+ files: ['.eslintrc.{js,cjs}'],
17
+ parserOptions: {
18
+ sourceType: 'script',
19
+ },
20
+ },
21
+ ],
22
+ parser: '@typescript-eslint/parser',
23
+ parserOptions: {
24
+ ecmaVersion: 'latest',
25
+ sourceType: 'module',
26
+ },
27
+ plugins: ['@typescript-eslint'],
28
+ rules: {
29
+ 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
30
+ 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
31
+ },
32
+ };
@@ -0,0 +1,2 @@
1
+ tsconfig.json
2
+ package.json
package/dist/index.d.ts CHANGED
@@ -1,21 +1,23 @@
1
- type CallbackType = () => void;
2
- export declare class JetstreamPlayer {
3
- iframe: HTMLIFrameElement;
4
- callbacks: {
5
- [key: string]: CallbackType;
6
- };
7
- constructor(selector: string);
1
+ import { JetStreamPlayerOptions } from './player.type';
2
+ export declare class JetStreamPlayer {
3
+ private iframe;
4
+ private options;
5
+ private registeredEvents;
6
+ constructor(el: string | HTMLIFrameElement, options: JetStreamPlayerOptions);
7
+ private registerEventHandler;
8
+ private registerEvents;
9
+ private dispatch;
10
+ private getterDispatch;
8
11
  play(): void;
9
12
  pause(): void;
10
13
  mute(): void;
11
14
  unmute(): void;
12
- isMuted(): Promise<unknown>;
13
- playNext(): void;
14
- playPrevious(): void;
15
15
  seekTo(seconds: number): void;
16
- onEnded: (callback: CallbackType) => void;
17
- onPlayVideo: (callback: CallbackType) => void;
18
- onPauseVideo: (callback: CallbackType) => void;
19
- onVolumeChange: (callback: CallbackType) => void;
16
+ playNext(): void;
17
+ playPrev(): void;
18
+ isMuted(): Promise<boolean>;
19
+ isPaused(): Promise<boolean>;
20
+ getVideoCurrentTime(): Promise<number>;
21
+ getDuration(): Promise<number>;
22
+ dispose(): void;
20
23
  }
21
- export {};
package/dist/index.js CHANGED
@@ -1,60 +1,114 @@
1
- export class JetstreamPlayer {
2
- iframe;
3
- callbacks = {};
4
- constructor(selector) {
5
- this.iframe = document.querySelector(selector);
6
- window.addEventListener('message', (event) => {
7
- if (event.data.src && this.iframe.src.includes(event.data.src.split('/').find(substr => (substr.startsWith('jsv:') || substr.startsWith('jspl:'))))) {
8
- if (event.data.msg in this.callbacks) {
9
- this.callbacks[event.data.msg]();
10
- }
1
+ import { denormalizeEventData, normalizeEventData } from './utils';
2
+ export class JetStreamPlayer {
3
+ iframe = null;
4
+ options;
5
+ registeredEvents = {};
6
+ constructor(el, options) {
7
+ this.iframe =
8
+ typeof el === 'string'
9
+ ? document.querySelector(el)
10
+ : el;
11
+ this.options = options;
12
+ this.registerEvents();
13
+ }
14
+ registerEventHandler(event) {
15
+ const data = normalizeEventData(event);
16
+ const targetEvent = data.target;
17
+ if (event.source === this.iframe.contentWindow) {
18
+ if (targetEvent in this.registeredEvents) {
19
+ this.registeredEvents[targetEvent](data.target);
20
+ }
21
+ }
22
+ }
23
+ registerEvents() {
24
+ if (!this.options.events ||
25
+ (this.options.events && Object.keys(this.options.events).length < 0)) {
26
+ return;
27
+ }
28
+ Object.entries(this.options.events).forEach(([eventName, cb]) => {
29
+ if (!(eventName in this.registeredEvents)) {
30
+ this.registeredEvents[eventName] = cb;
11
31
  }
12
32
  });
33
+ window.addEventListener('message', this.registerEventHandler.bind(this));
34
+ }
35
+ dispatch(event) {
36
+ if (!this.iframe || !this.iframe.contentWindow) {
37
+ throw new Error('iframe is not provided or parent window not found!');
38
+ }
39
+ this.iframe.contentWindow.postMessage(denormalizeEventData(event), '*');
40
+ }
41
+ getterDispatch(getterEvent) {
42
+ return new Promise((resolve) => {
43
+ this.dispatch(getterEvent);
44
+ window.addEventListener('message', (event) => {
45
+ const data = normalizeEventData(event);
46
+ if (data.type === getterEvent.name) {
47
+ resolve(data.target);
48
+ }
49
+ }, {
50
+ once: true,
51
+ });
52
+ });
13
53
  }
14
- /* Methods */
15
54
  play() {
16
- this.iframe.contentWindow?.postMessage('play', '*');
55
+ this.dispatch({
56
+ name: 'play',
57
+ });
17
58
  }
18
59
  pause() {
19
- this.iframe.contentWindow?.postMessage('pause', '*');
60
+ this.dispatch({
61
+ name: 'pause',
62
+ });
20
63
  }
21
64
  mute() {
22
- this.iframe.contentWindow?.postMessage('mute', '*');
65
+ this.dispatch({
66
+ name: 'mute',
67
+ });
23
68
  }
24
69
  unmute() {
25
- this.iframe.contentWindow?.postMessage('unmute', '*');
70
+ this.dispatch({
71
+ name: 'unmute',
72
+ });
26
73
  }
27
- isMuted() {
28
- return new Promise((resolve, reject) => {
29
- this.iframe.contentWindow?.postMessage('isMuted', '*');
30
- window.addEventListener('message', (event) => {
31
- if (event.data.type === 'isMuted') {
32
- resolve(event.data.value);
33
- }
34
- });
74
+ seekTo(seconds) {
75
+ this.dispatch({
76
+ name: 'seekTo',
77
+ params: seconds,
35
78
  });
36
79
  }
37
80
  playNext() {
38
- this.iframe.contentWindow?.postMessage('playNext', '*');
81
+ this.dispatch({
82
+ name: 'play-next',
83
+ });
39
84
  }
40
- playPrevious() {
41
- this.iframe.contentWindow?.postMessage('playPrevious', '*');
85
+ playPrev() {
86
+ this.dispatch({
87
+ name: 'play-prev',
88
+ });
89
+ }
90
+ isMuted() {
91
+ return this.getterDispatch({
92
+ name: 'isMuted',
93
+ });
94
+ }
95
+ isPaused() {
96
+ return this.getterDispatch({
97
+ name: 'isPaused',
98
+ });
99
+ }
100
+ getVideoCurrentTime() {
101
+ return this.getterDispatch({
102
+ name: 'getVideoCurrentTime',
103
+ });
104
+ }
105
+ getDuration() {
106
+ return this.getterDispatch({
107
+ name: 'getDuration',
108
+ });
109
+ }
110
+ dispose() {
111
+ window.removeEventListener('message', this.registerEventHandler);
112
+ this.registeredEvents = {};
42
113
  }
43
- seekTo(seconds) {
44
- this.iframe.contentWindow?.postMessage({ method: 'seekTo', param: seconds }, '*');
45
- }
46
- /* #Methods */
47
- /* Events */
48
- onEnded = (callback) => {
49
- this.callbacks.onEnded = callback;
50
- };
51
- onPlayVideo = (callback) => {
52
- this.callbacks.onPlayVideo = callback;
53
- };
54
- onPauseVideo = (callback) => {
55
- this.callbacks.onPauseVideo = callback;
56
- };
57
- onVolumeChange = (callback) => {
58
- this.callbacks.onVolumeChange = callback;
59
- };
60
114
  }
@@ -0,0 +1,31 @@
1
+ export declare const eventsMap: {
2
+ readonly ready: "onReady";
3
+ readonly timeupdate: "onTimeUpdate";
4
+ readonly play: "onPlay";
5
+ readonly pause: "onPause";
6
+ readonly loadedmetadata: "onLoadedMetadata";
7
+ readonly ended: "onEnded";
8
+ readonly volumechange: "onVolumeChange";
9
+ readonly error: "onError";
10
+ };
11
+ export declare const gettersEvents: {
12
+ readonly 'is-muted': "isMuted";
13
+ readonly 'get-video-current-time': "getVideoCurrentTime";
14
+ readonly 'get-duration': "getDuration";
15
+ readonly 'is-paused': "isPaused";
16
+ };
17
+ export type EventMap = typeof eventsMap;
18
+ export type EventKey = keyof EventMap;
19
+ export type GettersEvents = keyof typeof gettersEvents;
20
+ export type PlayerEvent = {
21
+ type: EventKey | GettersEvents;
22
+ target?: unknown;
23
+ };
24
+ export type PlayerCommand = {
25
+ name: 'play' | 'pause' | 'mute' | 'unmute' | 'isMuted' | 'seekTo' | 'getVideoCurrentTime' | 'getDuration' | 'isPaused' | 'play-next' | 'play-prev';
26
+ params?: unknown;
27
+ };
28
+ export type JetStreamPlayerOptions = {
29
+ sticky?: boolean;
30
+ events?: Partial<Record<EventKey, (target?: unknown) => void>>;
31
+ };
@@ -0,0 +1,16 @@
1
+ export const eventsMap = {
2
+ ready: 'onReady',
3
+ timeupdate: 'onTimeUpdate',
4
+ play: 'onPlay',
5
+ pause: 'onPause',
6
+ loadedmetadata: 'onLoadedMetadata',
7
+ ended: 'onEnded',
8
+ volumechange: 'onVolumeChange',
9
+ error: 'onError',
10
+ };
11
+ export const gettersEvents = {
12
+ 'is-muted': 'isMuted',
13
+ 'get-video-current-time': 'getVideoCurrentTime',
14
+ 'get-duration': 'getDuration',
15
+ 'is-paused': 'isPaused',
16
+ };
@@ -0,0 +1,2 @@
1
+ export declare const normalizeEventData: <T = unknown>({ data, }: MessageEvent<string>) => T;
2
+ export declare const denormalizeEventData: <T = unknown>(data: T) => string;
package/dist/utils.js ADDED
@@ -0,0 +1,6 @@
1
+ export const normalizeEventData = ({ data, }) => {
2
+ return JSON.parse(data);
3
+ };
4
+ export const denormalizeEventData = (data) => {
5
+ return JSON.stringify(data);
6
+ };
@@ -1,6 +1,5 @@
1
- import { defineConfig } from 'vitepress'
2
1
 
3
- export default defineConfig({
2
+ export default {
4
3
  title: "Jetstream player API",
5
4
  description: "Documentation of embed jetstream player API",
6
5
  themeConfig: {
@@ -52,4 +51,4 @@ export default defineConfig({
52
51
  { icon: 'github', link: 'https://github.com/deeepvision/hcc-jetstream-player' }
53
52
  ]
54
53
  }
55
- })
54
+ };
@@ -5,8 +5,9 @@
5
5
  ### Next events are available in this version of the library:
6
6
 
7
7
  - `onEnded()`
8
- - `playVideo()`
9
- - `pauseVideo()`
8
+ - `onPlayVideo()`
9
+ - `onPauseVideo()`
10
+ - `onVolumeChange()`
10
11
 
11
12
  This list is not exhaustive. New events can be added as needed.
12
13
 
@@ -17,17 +18,17 @@ import { JetstreamPlayer } from '@hopecloud/jetstream-player';
17
18
 
18
19
  setup() {
19
20
  let player: JetstreamPlayer | null;
20
-
21
+
21
22
  onMounted(() => {
22
23
  player = new JetstreamPlayer('#iframe1');
23
-
24
+
24
25
  player.onEnded(() => {
25
26
  console.log('Video is ENDED');
26
- })
27
-
27
+ });
28
+
28
29
  ...
29
- })
30
- }
30
+ });
31
+ },
31
32
  ```
32
33
 
33
34
  ### Pay attention ☝️⬇️
@@ -46,9 +47,9 @@ This event is called when a video or a video in a playlist ends. For example, if
46
47
  ```js
47
48
  import { JetstreamPlayer } from '@hopecloud/jetstream-player';
48
49
 
49
- setup() {
50
+ setup() {
50
51
  const players = [];
51
-
52
+
52
53
  onMounted(() => {
53
54
  players.push(new JetstreamPlayer('#iframe1'));
54
55
  players.push(new JetstreamPlayer('#iframe2'));
@@ -57,10 +58,10 @@ setup() {
57
58
  console.log('Video 2 is ENDED');
58
59
  });
59
60
  });
60
- }
61
+ },
61
62
  ```
62
63
 
63
- ## `playVideo()` event
64
+ ## `onPlayVideo()` event
64
65
 
65
66
  This event is a listener that fires when any video or playlist on your page starts playing. If your page has one or more embedded iframes and a video starts playing in the first window, event will be triggered for first player.
66
67
 
@@ -69,21 +70,21 @@ This event is a listener that fires when any video or playlist on your page star
69
70
  ```js
70
71
  import { JetstreamPlayer } from '@hopecloud/jetstream-player';
71
72
 
72
- setup() {
73
+ setup() {
73
74
  const players = [];
74
-
75
+
75
76
  onMounted(() => {
76
77
  players.push(new JetstreamPlayer('#iframe1'));
77
78
  players.push(new JetstreamPlayer('#iframe2'));
78
79
 
79
- players[0]?.playVideo(() => {
80
+ players[0]?.onPlayVideo(() => {
80
81
  console.log('Video 1 is PLAYING');
81
82
  });
82
83
  });
83
- }
84
+ },
84
85
  ```
85
86
 
86
- ## `pauseVideo()` event
87
+ ## `onPauseVideo()` event
87
88
 
88
89
  This event is a listener that fires when any video or playlist on your page paused. If your page has one or more embedded iframes and a video paused in the second window, event will be triggered for second player.
89
90
 
@@ -92,16 +93,39 @@ This event is a listener that fires when any video or playlist on your page paus
92
93
  ```js
93
94
  import { JetstreamPlayer } from '@hopecloud/jetstream-player';
94
95
 
95
- setup() {
96
+ setup() {
96
97
  const players = [];
97
-
98
+
98
99
  onMounted(() => {
99
100
  players.push(new JetstreamPlayer('#iframe1'));
100
101
  players.push(new JetstreamPlayer('#iframe2'));
101
102
 
102
- players[1]?.pauseVideo(() => {
103
+ players[1]?.onPauseVideo(() => {
103
104
  console.log('Video 2 is PAUSED');
104
105
  });
105
106
  });
106
- }
107
+ },
108
+ ```
109
+
110
+ ## `onVolumeChange()` event
111
+
112
+ This event is a listener that fires when any video or playlist on your page change volume. If your page has one or more embedded iframes and a video paused in the second window, event will be triggered for second player.
113
+
114
+ ### Example of use:
115
+
116
+ ```js
117
+ import { JetstreamPlayer } from '@hopecloud/jetstream-player';
118
+
119
+ setup() {
120
+ const players = [];
121
+
122
+ onMounted(() => {
123
+ players.push(new JetstreamPlayer('#iframe1'));
124
+ players.push(new JetstreamPlayer('#iframe2'));
125
+
126
+ players[1]?.onVolumeChange(() => {
127
+ console.log('Video 2 was changed volume');
128
+ });
129
+ });
130
+ },
107
131
  ```
@@ -7,7 +7,9 @@
7
7
  - `play()`
8
8
  - `pause()`
9
9
  - `seekTo()`
10
- - `playNext()`
10
+ - `mute()`
11
+ - `unmute()`
12
+ - `isMuted()`
11
13
  - `playPrevious()`
12
14
 
13
15
  This list is not exhaustive. New methods can be added to the library as needed.
@@ -19,24 +21,24 @@ import { JetstreamPlayer } from '@hopecloud/jetstream-player';
19
21
 
20
22
  setup() {
21
23
  let player: JetstreamPlayer | null;
22
-
24
+
23
25
  onMounted(() => {
24
26
  player = new JetstreamPlayer('#iframe1');
25
- })
27
+ });
26
28
 
27
29
  const playVideo = () => {
28
30
  player.play();
29
- }
30
-
31
+ };
32
+
31
33
  const pauseVideo = () => {
32
34
  player.pause();
33
- }
35
+ };
34
36
 
35
37
  return {
36
- playVideo,
37
- pauseVideo,
38
- }
39
- }
38
+ playVideo,
39
+ pauseVideo,
40
+ };
41
+ },
40
42
  ```
41
43
 
42
44
  ## `play()` `pause()` methods
@@ -53,6 +55,75 @@ Modern browsers don't provide an opportunity to avoid this setting. Therefore, f
53
55
 
54
56
  If the video or playlist has **sound settings off** `(muted)`, then all methods work in normal mode.
55
57
 
58
+ ## `mute()` method
59
+ Mute function set media volume to silent.
60
+
61
+ ```js
62
+ import { JetstreamPlayer } from '@hopecloud/jetstream-player';
63
+
64
+ setup() {
65
+ let player: JetstreamPlayer | null;
66
+
67
+ onMounted(() => {
68
+ player = new JetstreamPlayer('#iframe1');
69
+ });
70
+
71
+ const muteVideo = () => {
72
+ player.mute();
73
+ };
74
+
75
+ return {
76
+ muteVideo,
77
+ };
78
+ },
79
+ ```
80
+
81
+ ## `unmute()` method
82
+ Cancel volume mute.
83
+
84
+ ```js
85
+ import { JetstreamPlayer } from '@hopecloud/jetstream-player';
86
+
87
+ setup() {
88
+ let player: JetstreamPlayer | null;
89
+
90
+ onMounted(() => {
91
+ player = new JetstreamPlayer('#iframe1');
92
+ });
93
+
94
+ const unmuteVideo = () => {
95
+ player.unmute();
96
+ };
97
+
98
+ return {
99
+ unmuteVideo,
100
+ };
101
+ },
102
+ ```
103
+
104
+ ## `isMuted()` method
105
+ Returns `true` if the player volume is muted, `false` if not.
106
+
107
+ ```js
108
+ import { JetstreamPlayer } from '@hopecloud/jetstream-player';
109
+
110
+ setup() {
111
+ let player: JetstreamPlayer | null;
112
+
113
+ onMounted(() => {
114
+ player = new JetstreamPlayer('#iframe1');
115
+ });
116
+
117
+ const isMutedVideo = () => {
118
+ player.isMuted();
119
+ };
120
+
121
+ return {
122
+ isMutedVideo,
123
+ };
124
+ },
125
+ ```
126
+
56
127
  ## `seekTo(seconds: Number)` method
57
128
 
58
129
  Seeks to a specified time in the video. If the player is paused when the function is called, it will remain paused. If the function is called from another state (playing), the player will play the video.
@@ -69,19 +140,19 @@ import { JetstreamPlayer } from '@hopecloud/jetstream-player';
69
140
 
70
141
  setup() {
71
142
  let player: JetstreamPlayer | null;
72
-
143
+
73
144
  onMounted(() => {
74
145
  player = new JetstreamPlayer('#iframe1');
75
- })
146
+ });
76
147
 
77
148
  const seekTo = () => {
78
149
  player.seekTo(45); // Set time on 45 second
79
- }
150
+ };
80
151
 
81
152
  return {
82
- seekTo
83
- }
84
- }
153
+ seekTo
154
+ };
155
+ },
85
156
  ```
86
157
 
87
158
  ## `playNext()` `playPrevious()` methods
@@ -94,10 +165,10 @@ import { JetstreamPlayer } from '@hopecloud/jetstream-player';
94
165
 
95
166
  setup() {
96
167
  let playlistPlayer: JetstreamPlayer | null;
97
-
168
+
98
169
  onMounted(() => {
99
170
  playlistPlayer = new JetstreamPlayer('#iframe1');
100
- })
171
+ });
101
172
 
102
173
  const playNextVideo = () => {
103
174
  playlistPlayer.playNext();
@@ -108,8 +179,8 @@ setup() {
108
179
  };
109
180
 
110
181
  return {
111
- playNextVideo,
112
- playPreviousVideo,
113
- }
114
- }
182
+ playNextVideo,
183
+ playPreviousVideo,
184
+ };
185
+ }.
115
186
  ```
package/package.json CHANGED
@@ -1,17 +1,27 @@
1
1
  {
2
2
  "name": "@hopecloud/jetstream-player",
3
- "version": "0.3.3",
4
- "description": "Embeddable player for Jetstream videos",
3
+ "version": "0.3.5",
4
+ "description": "JetStream Embed Player API",
5
+ "type": "module",
5
6
  "scripts": {
6
7
  "build": "tsc",
7
8
  "pack": "npm run build && npm pack",
8
9
  "docs:dev": "vitepress dev docs",
9
10
  "docs:build": "vitepress build docs",
10
- "docs:preview": "vitepress preview docs"
11
+ "docs:preview": "vitepress preview docs",
12
+ "lint": "eslint \"src/**/*.ts\"",
13
+ "lint:fix": "eslint \"src/**/*.ts\" --fix",
14
+ "publish:next": "npm version patch -m \"release: %s\""
11
15
  },
12
16
  "main": "dist/index.js",
17
+ "types": "dist/index.d.ts",
13
18
  "devDependencies": {
14
- "typescript": "^5.0.4",
15
- "vitepress": "^1.0.0-alpha.65"
19
+ "@typescript-eslint/eslint-plugin": "^7.2.0",
20
+ "@typescript-eslint/parser": "^7.2.0",
21
+ "eslint": "^8.57.0",
22
+ "eslint-config-prettier": "^9.1.0",
23
+ "prettier": "3.2.5",
24
+ "typescript": "^5.4.2",
25
+ "vitepress": "1.0.0-rc.45"
16
26
  }
17
27
  }
@@ -0,0 +1,7 @@
1
+ /** @type {import("prettier").Config} */
2
+ export default {
3
+ trailingComma: 'es5',
4
+ tabWidth: 2,
5
+ semi: true,
6
+ singleQuote: true,
7
+ };
package/tsconfig.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "compilerOptions": {
3
- "target": "esnext",
4
- "module": "esnext",
3
+ "target": "ESNext",
4
+ "module": "ESNext",
5
5
  "strict": true,
6
6
  "esModuleInterop": true,
7
+ "allowJs": true,
8
+ "moduleResolution": "Bundler",
7
9
  "declaration": true,
8
- "outDir": "./dist",
10
+ "outDir": "./dist"
9
11
  },
10
12
  "exclude": ["node_modules"],
11
- "include": [
12
- "src/**/*.ts"
13
- ]
13
+ "include": ["src/**/*.ts"]
14
14
  }