@hopecloud/jetstream-player 0.3.4 → 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<boolean>;
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
+ };
package/package.json CHANGED
@@ -1,17 +1,27 @@
1
1
  {
2
2
  "name": "@hopecloud/jetstream-player",
3
- "version": "0.3.4",
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
  }