oddysee-react 0.1.1 → 0.2.0-canary.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.
- package/README.md +4 -2
- package/dist/index.cjs +33399 -2
- package/dist/index.d.cts +184 -1
- package/dist/index.d.ts +184 -1
- package/dist/index.js +33404 -3
- package/package.json +11 -4
- package/eslint.config.js +0 -23
- package/src/index.ts +0 -2
- package/src/use-hls-audio-player.ts +0 -241
- package/tsconfig.app.json +0 -28
- package/tsconfig.json +0 -7
- package/tsconfig.lib.json +0 -16
- package/tsconfig.node.json +0 -26
- package/vite.config.ts +0 -7
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
7
|
-
"version": "0.
|
|
7
|
+
"version": "0.2.0-canary.1",
|
|
8
8
|
"type": "module",
|
|
9
9
|
"author": "Karelle Hofler",
|
|
10
10
|
"main": "dist/index.js",
|
|
@@ -24,12 +24,13 @@
|
|
|
24
24
|
"build": "tsup src/index.ts --format esm,cjs --dts --tsconfig tsconfig.lib.json",
|
|
25
25
|
"dev": "tsup src/index.ts --format esm,cjs --dts --watch",
|
|
26
26
|
"lint": "eslint .",
|
|
27
|
+
"test": "vitest",
|
|
27
28
|
"preview": "vite preview",
|
|
28
29
|
"pub": "npm run build && npm publish",
|
|
29
30
|
"pub:test": "npm run build && npm publish --tag test"
|
|
30
31
|
},
|
|
31
32
|
"dependencies": {
|
|
32
|
-
"oddysee-typescript": "^0.
|
|
33
|
+
"oddysee-typescript": "^0.2.0-canary.1",
|
|
33
34
|
"react": "^19.2.0",
|
|
34
35
|
"react-dom": "^19.2.0"
|
|
35
36
|
},
|
|
@@ -46,6 +47,12 @@
|
|
|
46
47
|
"tsup": "7.2.0",
|
|
47
48
|
"typescript": "~5.9.3",
|
|
48
49
|
"typescript-eslint": "^8.46.4",
|
|
49
|
-
"vite": "^7.2.4"
|
|
50
|
-
|
|
50
|
+
"vite": "^7.2.4",
|
|
51
|
+
"vitest": "^4.0.16"
|
|
52
|
+
},
|
|
53
|
+
"files": [
|
|
54
|
+
"dist",
|
|
55
|
+
"README.md",
|
|
56
|
+
"LICENSE"
|
|
57
|
+
]
|
|
51
58
|
}
|
package/eslint.config.js
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import js from '@eslint/js'
|
|
2
|
-
import globals from 'globals'
|
|
3
|
-
import reactHooks from 'eslint-plugin-react-hooks'
|
|
4
|
-
import reactRefresh from 'eslint-plugin-react-refresh'
|
|
5
|
-
import tseslint from 'typescript-eslint'
|
|
6
|
-
import { defineConfig, globalIgnores } from 'eslint/config'
|
|
7
|
-
|
|
8
|
-
export default defineConfig([
|
|
9
|
-
globalIgnores(['dist']),
|
|
10
|
-
{
|
|
11
|
-
files: ['**/*.{ts,tsx}'],
|
|
12
|
-
extends: [
|
|
13
|
-
js.configs.recommended,
|
|
14
|
-
tseslint.configs.recommended,
|
|
15
|
-
reactHooks.configs.flat.recommended,
|
|
16
|
-
reactRefresh.configs.vite,
|
|
17
|
-
],
|
|
18
|
-
languageOptions: {
|
|
19
|
-
ecmaVersion: 2020,
|
|
20
|
-
globals: globals.browser,
|
|
21
|
-
},
|
|
22
|
-
},
|
|
23
|
-
])
|
package/src/index.ts
DELETED
|
@@ -1,241 +0,0 @@
|
|
|
1
|
-
import { useEffect, useMemo, useState } from 'react'
|
|
2
|
-
import {
|
|
3
|
-
HLSAudioPlayer,
|
|
4
|
-
type HLSAudioPlayerInterface,
|
|
5
|
-
type PlayerConfig,
|
|
6
|
-
type SourceOptions,
|
|
7
|
-
type PlayerEvent,
|
|
8
|
-
type PlayerError,
|
|
9
|
-
type Track,
|
|
10
|
-
type QualityLevel,
|
|
11
|
-
type PlayerState
|
|
12
|
-
} from 'oddysee-typescript'
|
|
13
|
-
|
|
14
|
-
// Local mirror of the core's PlayerEventMap so we don't depend on it being exported
|
|
15
|
-
export type PlayerEventMap = {
|
|
16
|
-
play: void
|
|
17
|
-
pause: void
|
|
18
|
-
'track-end': Track | null
|
|
19
|
-
error: PlayerError
|
|
20
|
-
'quality-change': QualityLevel
|
|
21
|
-
'playlist-ready': void
|
|
22
|
-
loadedmetadata: Track | null
|
|
23
|
-
timeupdate: { currentTime: number; duration: number | null }
|
|
24
|
-
loading: void
|
|
25
|
-
canplay: void
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export interface UseHlsAudioPlayerOptions {
|
|
29
|
-
config?: PlayerConfig
|
|
30
|
-
src?: { url: string; options?: SourceOptions }
|
|
31
|
-
autoPlay?: boolean
|
|
32
|
-
on?: Partial<{
|
|
33
|
-
[K in PlayerEvent]: (data: PlayerEventMap[K]) => void
|
|
34
|
-
}>
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export interface UseHlsAudioPlayerResult {
|
|
38
|
-
player: HLSAudioPlayerInterface | null
|
|
39
|
-
state: PlayerState
|
|
40
|
-
isPlaying: boolean
|
|
41
|
-
duration: number
|
|
42
|
-
isLoading: boolean
|
|
43
|
-
loading: boolean
|
|
44
|
-
error: PlayerError | null
|
|
45
|
-
readyState: number
|
|
46
|
-
controls: {
|
|
47
|
-
setSource: (
|
|
48
|
-
url: string,
|
|
49
|
-
options?: SourceOptions,
|
|
50
|
-
) => Promise<HLSAudioPlayerInterface | null>
|
|
51
|
-
play: () => void
|
|
52
|
-
playAsync: () => Promise<HLSAudioPlayerInterface | null>
|
|
53
|
-
pause: () => void
|
|
54
|
-
setVolume: (volume: number) => void
|
|
55
|
-
setCurrentTime: (time: number) => void
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
const defaultState: PlayerState = {
|
|
60
|
-
track: null,
|
|
61
|
-
currentTime: 0,
|
|
62
|
-
duration: null,
|
|
63
|
-
volume: 1,
|
|
64
|
-
loading: false,
|
|
65
|
-
error: null,
|
|
66
|
-
readyState: 0,
|
|
67
|
-
isPlaying: false,
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
export function useHlsAudioPlayer(
|
|
71
|
-
options: UseHlsAudioPlayerOptions = {},
|
|
72
|
-
): UseHlsAudioPlayerResult {
|
|
73
|
-
const { config, src, autoPlay, on } = options
|
|
74
|
-
|
|
75
|
-
const player = useMemo(() => {
|
|
76
|
-
return new HLSAudioPlayer(config)
|
|
77
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
78
|
-
}, [])
|
|
79
|
-
|
|
80
|
-
const [state, setState] = useState<PlayerState>(
|
|
81
|
-
() => player.getState() ?? defaultState,
|
|
82
|
-
)
|
|
83
|
-
|
|
84
|
-
const [loading, setLoading] = useState<boolean>(player.loading ?? false)
|
|
85
|
-
const [error, setError] = useState<PlayerError | null>(player.error ?? null)
|
|
86
|
-
const [readyState, setReadyState] = useState<number>(player.readyState ?? 0)
|
|
87
|
-
const [isPlaying, setIsPlaying] = useState<boolean>(player.isPlaying ?? false)
|
|
88
|
-
const [duration, setDuration] = useState<number>(player.getState()?.duration ?? 0)
|
|
89
|
-
const [isLoading, setIsLoading] = useState<boolean>(player.loading ?? false)
|
|
90
|
-
|
|
91
|
-
useEffect(() => {
|
|
92
|
-
const handleStateChange = () => {
|
|
93
|
-
const next = player.getState()
|
|
94
|
-
setState(next)
|
|
95
|
-
setLoading(next.loading)
|
|
96
|
-
setError(next.error)
|
|
97
|
-
setReadyState(next.readyState)
|
|
98
|
-
setIsPlaying(next.isPlaying)
|
|
99
|
-
setDuration(next.duration ?? 0)
|
|
100
|
-
setIsLoading(next.loading)
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
const listeners: { [K in PlayerEvent]?: (data: PlayerEventMap[K]) => void } = {
|
|
104
|
-
play: data => {
|
|
105
|
-
handleStateChange()
|
|
106
|
-
on?.play?.(data as PlayerEventMap['play'])
|
|
107
|
-
},
|
|
108
|
-
pause: data => {
|
|
109
|
-
handleStateChange()
|
|
110
|
-
on?.pause?.(data as PlayerEventMap['pause'])
|
|
111
|
-
},
|
|
112
|
-
'track-end': data => {
|
|
113
|
-
handleStateChange()
|
|
114
|
-
on?.['track-end']?.(data as PlayerEventMap['track-end'])
|
|
115
|
-
},
|
|
116
|
-
error: data => {
|
|
117
|
-
handleStateChange()
|
|
118
|
-
on?.error?.(data as PlayerEventMap['error'])
|
|
119
|
-
},
|
|
120
|
-
'quality-change': data => {
|
|
121
|
-
handleStateChange()
|
|
122
|
-
on?.['quality-change']?.(data as PlayerEventMap['quality-change'])
|
|
123
|
-
},
|
|
124
|
-
'playlist-ready': data => {
|
|
125
|
-
handleStateChange()
|
|
126
|
-
on?.['playlist-ready']?.(data as PlayerEventMap['playlist-ready'])
|
|
127
|
-
},
|
|
128
|
-
loadedmetadata: data => {
|
|
129
|
-
handleStateChange()
|
|
130
|
-
on?.loadedmetadata?.(data as PlayerEventMap['loadedmetadata'])
|
|
131
|
-
},
|
|
132
|
-
timeupdate: data => {
|
|
133
|
-
handleStateChange()
|
|
134
|
-
on?.timeupdate?.(data as PlayerEventMap['timeupdate'])
|
|
135
|
-
},
|
|
136
|
-
loading: data => {
|
|
137
|
-
handleStateChange()
|
|
138
|
-
on?.loading?.(data as PlayerEventMap['loading'])
|
|
139
|
-
},
|
|
140
|
-
canplay: data => {
|
|
141
|
-
handleStateChange()
|
|
142
|
-
on?.canplay?.(data as PlayerEventMap['canplay'])
|
|
143
|
-
},
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
;(Object.keys(listeners) as PlayerEvent[]).forEach(event => {
|
|
147
|
-
const handler = listeners[event]!
|
|
148
|
-
player.on(event, handler as any)
|
|
149
|
-
})
|
|
150
|
-
|
|
151
|
-
return () => {
|
|
152
|
-
;(Object.keys(listeners) as PlayerEvent[]).forEach(event => {
|
|
153
|
-
const handler = listeners[event]
|
|
154
|
-
if (handler) {
|
|
155
|
-
player.off(event, handler as any)
|
|
156
|
-
}
|
|
157
|
-
})
|
|
158
|
-
}
|
|
159
|
-
}, [player, on])
|
|
160
|
-
|
|
161
|
-
useEffect(() => {
|
|
162
|
-
let cancelled = false
|
|
163
|
-
|
|
164
|
-
if (!src) return
|
|
165
|
-
|
|
166
|
-
player
|
|
167
|
-
.setSource(src.url, src.options)
|
|
168
|
-
.then((p: HLSAudioPlayerInterface) => {
|
|
169
|
-
if (cancelled) return
|
|
170
|
-
if (autoPlay) {
|
|
171
|
-
p.play()
|
|
172
|
-
}
|
|
173
|
-
})
|
|
174
|
-
.catch((err: unknown) => {
|
|
175
|
-
if (cancelled) return
|
|
176
|
-
console.error('Failed to set HLS source', err)
|
|
177
|
-
})
|
|
178
|
-
|
|
179
|
-
return () => {
|
|
180
|
-
cancelled = true
|
|
181
|
-
}
|
|
182
|
-
}, [player, src?.url, src?.options, autoPlay])
|
|
183
|
-
|
|
184
|
-
useEffect(() => {
|
|
185
|
-
return () => {
|
|
186
|
-
player.destroy()
|
|
187
|
-
}
|
|
188
|
-
}, [player])
|
|
189
|
-
|
|
190
|
-
const controls = useMemo(
|
|
191
|
-
() => ({
|
|
192
|
-
setSource: async (url: string, options?: SourceOptions) => {
|
|
193
|
-
try {
|
|
194
|
-
const p = await player.setSource(url, options)
|
|
195
|
-
if (autoPlay) {
|
|
196
|
-
p.play()
|
|
197
|
-
}
|
|
198
|
-
return p
|
|
199
|
-
} catch {
|
|
200
|
-
return null
|
|
201
|
-
}
|
|
202
|
-
},
|
|
203
|
-
play: () => {
|
|
204
|
-
player.play()
|
|
205
|
-
},
|
|
206
|
-
playAsync: async () => {
|
|
207
|
-
try {
|
|
208
|
-
const p = await player.playAsync()
|
|
209
|
-
return p
|
|
210
|
-
} catch {
|
|
211
|
-
return null
|
|
212
|
-
}
|
|
213
|
-
},
|
|
214
|
-
pause: () => {
|
|
215
|
-
player.pause()
|
|
216
|
-
},
|
|
217
|
-
setVolume: (volume: number) => {
|
|
218
|
-
player.setVolume(volume)
|
|
219
|
-
const next = player.getState()
|
|
220
|
-
setState(next)
|
|
221
|
-
},
|
|
222
|
-
setCurrentTime: (time: number) => {
|
|
223
|
-
const audioElement = player.getAudioElement()
|
|
224
|
-
audioElement.currentTime = time
|
|
225
|
-
},
|
|
226
|
-
}),
|
|
227
|
-
[player, autoPlay],
|
|
228
|
-
)
|
|
229
|
-
|
|
230
|
-
return {
|
|
231
|
-
player,
|
|
232
|
-
state,
|
|
233
|
-
isPlaying,
|
|
234
|
-
duration,
|
|
235
|
-
isLoading,
|
|
236
|
-
loading,
|
|
237
|
-
error,
|
|
238
|
-
readyState,
|
|
239
|
-
controls,
|
|
240
|
-
}
|
|
241
|
-
}
|
package/tsconfig.app.json
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
|
4
|
-
"target": "ES2022",
|
|
5
|
-
"useDefineForClassFields": true,
|
|
6
|
-
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
|
7
|
-
"module": "ESNext",
|
|
8
|
-
"types": ["vite/client"],
|
|
9
|
-
"skipLibCheck": true,
|
|
10
|
-
|
|
11
|
-
/* Bundler mode */
|
|
12
|
-
"moduleResolution": "bundler",
|
|
13
|
-
"allowImportingTsExtensions": true,
|
|
14
|
-
"verbatimModuleSyntax": true,
|
|
15
|
-
"moduleDetection": "force",
|
|
16
|
-
"noEmit": true,
|
|
17
|
-
"jsx": "react-jsx",
|
|
18
|
-
|
|
19
|
-
/* Linting */
|
|
20
|
-
"strict": true,
|
|
21
|
-
"noUnusedLocals": true,
|
|
22
|
-
"noUnusedParameters": true,
|
|
23
|
-
"erasableSyntaxOnly": true,
|
|
24
|
-
"noFallthroughCasesInSwitch": true,
|
|
25
|
-
"noUncheckedSideEffectImports": true
|
|
26
|
-
},
|
|
27
|
-
"include": ["src"]
|
|
28
|
-
}
|
package/tsconfig.json
DELETED
package/tsconfig.lib.json
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2020",
|
|
4
|
-
"module": "ESNext",
|
|
5
|
-
"moduleResolution": "node",
|
|
6
|
-
"esModuleInterop": true,
|
|
7
|
-
"strict": true,
|
|
8
|
-
"skipLibCheck": true,
|
|
9
|
-
"forceConsistentCasingInFileNames": true,
|
|
10
|
-
"declaration": true,
|
|
11
|
-
"declarationMap": true,
|
|
12
|
-
"jsx": "react-jsx"
|
|
13
|
-
},
|
|
14
|
-
"include": ["src/index.ts", "src/use-hls-audio-player.ts"],
|
|
15
|
-
"exclude": ["dist", "node_modules"]
|
|
16
|
-
}
|
package/tsconfig.node.json
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
|
|
4
|
-
"target": "ES2023",
|
|
5
|
-
"lib": ["ES2023"],
|
|
6
|
-
"module": "ESNext",
|
|
7
|
-
"types": ["node"],
|
|
8
|
-
"skipLibCheck": true,
|
|
9
|
-
|
|
10
|
-
/* Bundler mode */
|
|
11
|
-
"moduleResolution": "bundler",
|
|
12
|
-
"allowImportingTsExtensions": true,
|
|
13
|
-
"verbatimModuleSyntax": true,
|
|
14
|
-
"moduleDetection": "force",
|
|
15
|
-
"noEmit": true,
|
|
16
|
-
|
|
17
|
-
/* Linting */
|
|
18
|
-
"strict": true,
|
|
19
|
-
"noUnusedLocals": true,
|
|
20
|
-
"noUnusedParameters": true,
|
|
21
|
-
"erasableSyntaxOnly": true,
|
|
22
|
-
"noFallthroughCasesInSwitch": true,
|
|
23
|
-
"noUncheckedSideEffectImports": true
|
|
24
|
-
},
|
|
25
|
-
"include": ["vite.config.ts"]
|
|
26
|
-
}
|