@banou/media-player 0.5.1 → 0.6.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.
Files changed (43) hide show
  1. package/README.md +6 -6
  2. package/build/components/playback-slider.d.ts +2 -0
  3. package/build/index.js +1159 -1012
  4. package/build/state-machines/index.d.ts +2503 -1838
  5. package/build/state-machines/media.d.ts +218 -51
  6. package/build/state-machines/subtitles.d.ts +3 -0
  7. package/build/utils/use-local-storage.d.ts +1 -1
  8. package/package.json +51 -51
  9. package/src/assets/picture-in-picture.svg +5 -5
  10. package/src/components/chrome.tsx +95 -95
  11. package/src/components/control-bar.tsx +333 -327
  12. package/src/components/overlay.tsx +91 -91
  13. package/src/components/playback-slider.tsx +174 -0
  14. package/src/components/progress-bar.tsx +251 -251
  15. package/src/components/settings.tsx +321 -268
  16. package/src/components/sound.tsx +100 -100
  17. package/src/components/tooltip-display.tsx +83 -83
  18. package/src/components/volume-slider.tsx +156 -156
  19. package/src/index.tsx +195 -195
  20. package/src/main.tsx +169 -169
  21. package/src/state-machines/data-source.ts +84 -84
  22. package/src/state-machines/index.ts +5 -5
  23. package/src/state-machines/media-properties.ts +82 -82
  24. package/src/state-machines/media-source.ts +129 -129
  25. package/src/state-machines/media.ts +255 -252
  26. package/src/state-machines/subtitles.ts +285 -269
  27. package/src/state-machines/thumbnails.ts +123 -123
  28. package/src/state-machines/utils.ts +94 -94
  29. package/src/utils/actor-utils.ts +19 -19
  30. package/src/utils/colors.ts +8 -8
  31. package/src/utils/context.ts +23 -23
  32. package/src/utils/fonts.ts +159 -159
  33. package/src/utils/index.ts +229 -229
  34. package/src/utils/languages.ts +262 -262
  35. package/src/utils/mp4box.ts +74 -74
  36. package/src/utils/time.ts +15 -15
  37. package/src/utils/use-local-storage.ts +30 -30
  38. package/src/utils/use-scrub.ts +40 -40
  39. package/src/utils/volume-utils.ts +39 -39
  40. package/src/utils/window-height.ts +19 -19
  41. package/src/vite-env.d.ts +1 -1
  42. package/tsconfig.json +28 -28
  43. package/tsconfig.node.json +9 -9
@@ -10,6 +10,9 @@ type SubtitlesEvents = {
10
10
  } | {
11
11
  type: 'SELECT_SUBTITLE_STREAM';
12
12
  streamIndex: number;
13
+ } | {
14
+ type: 'TIME_UPDATE';
15
+ currentTime: number;
13
16
  };
14
17
  type SubtitlesEmittedEvents = {
15
18
  type: 'WAITING';
@@ -1,3 +1,3 @@
1
1
  export declare const useLocalStorage: <T>(name: string, defaultValue?: T) => readonly [string | T | undefined, (newValue: string) => void];
2
2
  export default useLocalStorage;
3
- export type mediaMutedType = 'true' | 'false' | undefined;
3
+ export type booleanType = 'true' | 'false' | undefined;
package/package.json CHANGED
@@ -1,51 +1,51 @@
1
- {
2
- "name": "@banou/media-player",
3
- "version": "0.5.1",
4
- "description": "",
5
- "type": "module",
6
- "main": "build/index.js",
7
- "files": [
8
- "build",
9
- "tsconfig.json",
10
- "tsconfig.node.json",
11
- "src"
12
- ],
13
- "scripts": {
14
- "dev": "vite --port 4560",
15
- "build-dev": "vite build --watch",
16
- "build": "vite build && npm run types",
17
- "build-for-dev": "vite build && npm run copy-dependencies && npm run types",
18
- "copy-dependencies": "npm run copy-libass && npm run copy-worker && npm run copy-worker-wasm",
19
- "copy-worker": "shx cp node_modules/libav-wasm/build/worker.js build/libav.js",
20
- "copy-worker-wasm": "shx cp node_modules/libav-wasm/build/libav.wasm build/libav.wasm",
21
- "copy-libass": "copyfiles -u 3 ./node_modules/jassub/dist/* build",
22
- "types": "tsc"
23
- },
24
- "author": "Banou26",
25
- "devDependencies": {
26
- "@types/node": "^18.11.18",
27
- "@types/react": "^18.0.27",
28
- "@types/react-dom": "^18.0.10",
29
- "@vitejs/plugin-react": "^4.3.4",
30
- "concurrently": "^7.6.0",
31
- "copyfiles": "^2.4.1",
32
- "mime": "^3.0.0",
33
- "shx": "^0.3.4",
34
- "typescript": "^5.8.2",
35
- "vite": "^6.2.1"
36
- },
37
- "dependencies": {
38
- "@emotion/react": "^11.14.0",
39
- "@xstate/react": "^5.0.1",
40
- "ass-compiler": "^0.1.15",
41
- "jassub": "^1.7.18",
42
- "libav-wasm": "^0.5.5",
43
- "osra": "^0.1.2",
44
- "p-queue": "^7.3.4",
45
- "react": "^19.0.0",
46
- "react-dom": "^19.0.0",
47
- "react-feather": "^2.0.10",
48
- "react-tooltip": "^5.28.0",
49
- "xstate": "^5.19.1"
50
- }
51
- }
1
+ {
2
+ "name": "@banou/media-player",
3
+ "version": "0.6.1",
4
+ "description": "",
5
+ "type": "module",
6
+ "main": "build/index.js",
7
+ "files": [
8
+ "build",
9
+ "tsconfig.json",
10
+ "tsconfig.node.json",
11
+ "src"
12
+ ],
13
+ "scripts": {
14
+ "dev": "vite --port 4560",
15
+ "build-dev": "vite build --watch",
16
+ "build": "vite build && npm run types",
17
+ "build-for-dev": "vite build && npm run copy-dependencies && npm run types",
18
+ "copy-dependencies": "npm run copy-libass && npm run copy-worker && npm run copy-worker-wasm",
19
+ "copy-worker": "shx cp node_modules/libav-wasm/build/worker.js build/libav.js",
20
+ "copy-worker-wasm": "shx cp node_modules/libav-wasm/build/libav.wasm build/libav.wasm",
21
+ "copy-libass": "copyfiles -u 3 ./node_modules/jassub/dist/* build",
22
+ "types": "tsc"
23
+ },
24
+ "author": "Banou26",
25
+ "devDependencies": {
26
+ "@types/node": "^18.11.18",
27
+ "@types/react": "^18.0.27",
28
+ "@types/react-dom": "^18.0.10",
29
+ "@vitejs/plugin-react": "^4.3.4",
30
+ "concurrently": "^7.6.0",
31
+ "copyfiles": "^2.4.1",
32
+ "mime": "^3.0.0",
33
+ "shx": "^0.3.4",
34
+ "typescript": "^5.8.2",
35
+ "vite": "^6.2.1"
36
+ },
37
+ "dependencies": {
38
+ "@emotion/react": "^11.14.0",
39
+ "@xstate/react": "^5.0.1",
40
+ "ass-compiler": "^0.1.15",
41
+ "jassub": "^1.7.18",
42
+ "libav-wasm": "^0.6.1",
43
+ "osra": "^0.1.2",
44
+ "p-queue": "^7.3.4",
45
+ "react": "^19.0.0",
46
+ "react-dom": "^19.0.0",
47
+ "react-feather": "^2.0.10",
48
+ "react-tooltip": "^5.28.0",
49
+ "xstate": "^5.19.1"
50
+ }
51
+ }
@@ -1,5 +1,5 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#fff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-picture-in-picture">
2
- <path stroke="none" d="M0 0h24v24H0z" fill="none" />
3
- <path d="M11 19h-6a2 2 0 0 1 -2 -2v-10a2 2 0 0 1 2 -2h14a2 2 0 0 1 2 2v4" />
4
- <path d="M14 14m0 1a1 1 0 0 1 1 -1h5a1 1 0 0 1 1 1v3a1 1 0 0 1 -1 1h-5a1 1 0 0 1 -1 -1z" />
5
- </svg>
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#fff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-picture-in-picture">
2
+ <path stroke="none" d="M0 0h24v24H0z" fill="none" />
3
+ <path d="M11 19h-6a2 2 0 0 1 -2 -2v-10a2 2 0 0 1 2 -2h14a2 2 0 0 1 2 2v4" />
4
+ <path d="M14 14m0 1a1 1 0 0 1 1 -1h5a1 1 0 0 1 1 1v3a1 1 0 0 1 -1 1h-5a1 1 0 0 1 -1 -1z" />
5
+ </svg>
@@ -1,95 +1,95 @@
1
- /// <reference types="@emotion/react/types/css-prop" />
2
- import { MouseEventHandler, ReactNode, useContext, useRef, type HTMLAttributes } from 'react'
3
-
4
- import { css } from '@emotion/react'
5
-
6
- import { MediaMachineContext } from '../state-machines'
7
- import { MediaPlayerContext } from '../utils/context'
8
- import { togglePlay } from '../utils/actor-utils'
9
- import { Overlay } from './overlay'
10
- import ControlBar from './control-bar'
11
-
12
- const style = css`
13
- position: relative;
14
- background-color: black;
15
- display: flex;
16
- justify-content: center;
17
- align-items: center;
18
- height: 100%;
19
- width: 100%;
20
-
21
- & > div:not(:last-of-type) {
22
- position: absolute;
23
- z-index: 2;
24
- }
25
-
26
- canvas {
27
- height: 100%;
28
- width: 100%;
29
- pointer-events: none;
30
- position: absolute;
31
- z-index: 1;
32
- }
33
-
34
- .video, video {
35
- height: 100%;
36
- width: 100%;
37
- background-color: black;
38
- object-fit: contain;
39
- }
40
-
41
- &.hide {
42
- cursor: none;
43
- }
44
- `
45
-
46
- export type ChromeOptions = {
47
- mediaInformation?: ReactNode
48
- loadingInformation?: ReactNode
49
- } & HTMLAttributes<HTMLDivElement>
50
-
51
- export const Chrome = ({ children, mediaInformation, loadingInformation }: ChromeOptions) => {
52
- const mediaActor = MediaMachineContext.useActorRef()
53
- const mediaPlayerContext = useContext(MediaPlayerContext)
54
- const isPaused = MediaMachineContext.useSelector((state) => state.context.media.paused)
55
- const currentTime = MediaMachineContext.useSelector((state) => state.context.media.currentTime)
56
- const duration = MediaMachineContext.useSelector((state) => state.context.media.duration)
57
-
58
- const autoHide = useRef<number>()
59
- const containerRef = useRef<HTMLDivElement>(null)
60
-
61
- const mouseMove: MouseEventHandler<HTMLDivElement> = (ev) => {
62
- mediaPlayerContext.update(({ ...mediaPlayerContext, hideUI: false }))
63
- if (autoHide.current) clearInterval(autoHide.current)
64
- const timeout = setTimeout(() => {
65
- mediaPlayerContext.update(({ ...mediaPlayerContext, hideUI: true }))
66
- }, 3_000) as unknown as number
67
- autoHide.current = timeout
68
- }
69
-
70
- const mouseOut: React.DOMAttributes<HTMLDivElement>['onMouseOut'] = (ev) => {
71
- if (ev.currentTarget.parentElement !== ev.relatedTarget && ev.relatedTarget !== null) return
72
- mediaPlayerContext.update(({ ...mediaPlayerContext, hideUI: true }))
73
- }
74
-
75
- return (
76
- <div
77
- css={style}
78
- ref={containerRef}
79
- onMouseMove={mouseMove}
80
- onMouseOut={mouseOut}
81
- className={mediaPlayerContext.hideUI ? 'hide' : ''}
82
- >
83
- <Overlay loadingInformation={loadingInformation}/>
84
- <ControlBar mediaInformation={mediaInformation} containerRef={containerRef}/>
85
- <div
86
- className='video'
87
- onClick={() => togglePlay(mediaActor, isPaused, duration, currentTime)}
88
- >
89
- {children}
90
- </div>
91
- </div>
92
- )
93
- }
94
-
95
- export default Chrome
1
+ /// <reference types="@emotion/react/types/css-prop" />
2
+ import { MouseEventHandler, ReactNode, useContext, useRef, type HTMLAttributes } from 'react'
3
+
4
+ import { css } from '@emotion/react'
5
+
6
+ import { MediaMachineContext } from '../state-machines'
7
+ import { MediaPlayerContext } from '../utils/context'
8
+ import { togglePlay } from '../utils/actor-utils'
9
+ import { Overlay } from './overlay'
10
+ import ControlBar from './control-bar'
11
+
12
+ const style = css`
13
+ position: relative;
14
+ background-color: black;
15
+ display: flex;
16
+ justify-content: center;
17
+ align-items: center;
18
+ height: 100%;
19
+ width: 100%;
20
+
21
+ & > div:not(:last-of-type) {
22
+ position: absolute;
23
+ z-index: 2;
24
+ }
25
+
26
+ canvas {
27
+ height: 100%;
28
+ width: 100%;
29
+ pointer-events: none;
30
+ position: absolute;
31
+ z-index: 1;
32
+ }
33
+
34
+ .video, video {
35
+ height: 100%;
36
+ width: 100%;
37
+ background-color: black;
38
+ object-fit: contain;
39
+ }
40
+
41
+ &.hide {
42
+ cursor: none;
43
+ }
44
+ `
45
+
46
+ export type ChromeOptions = {
47
+ mediaInformation?: ReactNode
48
+ loadingInformation?: ReactNode
49
+ } & HTMLAttributes<HTMLDivElement>
50
+
51
+ export const Chrome = ({ children, mediaInformation, loadingInformation }: ChromeOptions) => {
52
+ const mediaActor = MediaMachineContext.useActorRef()
53
+ const mediaPlayerContext = useContext(MediaPlayerContext)
54
+ const isPaused = MediaMachineContext.useSelector((state) => state.context.media.paused)
55
+ const currentTime = MediaMachineContext.useSelector((state) => state.context.media.currentTime)
56
+ const duration = MediaMachineContext.useSelector((state) => state.context.media.duration)
57
+
58
+ const autoHide = useRef<number>()
59
+ const containerRef = useRef<HTMLDivElement>(null)
60
+
61
+ const mouseMove: MouseEventHandler<HTMLDivElement> = (ev) => {
62
+ mediaPlayerContext.update(({ ...mediaPlayerContext, hideUI: false }))
63
+ if (autoHide.current) clearInterval(autoHide.current)
64
+ const timeout = setTimeout(() => {
65
+ mediaPlayerContext.update(({ ...mediaPlayerContext, hideUI: true }))
66
+ }, 3_000) as unknown as number
67
+ autoHide.current = timeout
68
+ }
69
+
70
+ const mouseOut: React.DOMAttributes<HTMLDivElement>['onMouseOut'] = (ev) => {
71
+ if (ev.currentTarget.parentElement !== ev.relatedTarget && ev.relatedTarget !== null) return
72
+ mediaPlayerContext.update(({ ...mediaPlayerContext, hideUI: true }))
73
+ }
74
+
75
+ return (
76
+ <div
77
+ css={style}
78
+ ref={containerRef}
79
+ onMouseMove={mouseMove}
80
+ onMouseOut={mouseOut}
81
+ className={mediaPlayerContext.hideUI ? 'hide' : ''}
82
+ >
83
+ <Overlay loadingInformation={loadingInformation}/>
84
+ <ControlBar mediaInformation={mediaInformation} containerRef={containerRef}/>
85
+ <div
86
+ className='video'
87
+ onClick={() => togglePlay(mediaActor, isPaused, duration, currentTime)}
88
+ >
89
+ {children}
90
+ </div>
91
+ </div>
92
+ )
93
+ }
94
+
95
+ export default Chrome