import { PlayerProp , usePlayerContext , PlayerProps , Dispatcher , createDispatcher , findPlayer , WritableProps , isWritableProp , initialState , } from '@vime/core' ; import { onMount } from 'svelte' ; import { writable , get as unwrap , Writable , Readable } from 'svelte/store' ; type PropStoreType < P extends keyof PlayerProps > = P extends keyof WritableProps ? Writable < PlayerProps [ P ] > : Readable < PlayerProps [ P ] > ; type PlayerStore = { [ P in keyof PlayerProps ] : PropStoreType < P > ; } ; interface SvelteWebComponent < T extends HTMLElement > { getWebComponent : T | undefined ; } type Ref < T extends HTMLElement > = ( ) => T | SvelteWebComponent < T > ; param ref export const usePlayer = < T extends HTMLElement > ( ref , callback ) => { onMount ( async ( ) => { let el = ref ( ) ; if ( el . $$ ) el = el . getWebComponent ( ) ; const player = await findPlayer ( el ) ; if ( ! player ) return ; callback ( player ) ; } ) ; } ; param playerRef example export const usePlayerStore = < T extends HTMLElement > ( ref ) : PlayerStore => { let dispatch = ( ) => { } ; const internalStoreRef = new Map ( ) ; const mountedQueue = [ ] ; const onPlayerMounted = ( ) => { mountedQueue . forEach ( fn => fn ( ) ) ; } ; const vimeable = < P extends keyof PlayerProps > ( prop , initialValue ) => { const store = writable ( initialValue ) ; const canWrite = isWritableProp ( prop ) ; const set = ( value ) => { if ( ! unwrap ( internalStoreRef . get ( 'ready' ) ! ) ) { mountedQueue . push ( ( ) => { dispatch ( prop as any , value ) ; } ) ; } else { dispatch ( prop as any , value ) ; } } ; const update = ( updater ) => { set ( updater ( unwrap ( store ) ) ) ; } ; internalStoreRef . set ( prop , store ) ; return { subscribe : store . subscribe , update : canWrite ? update : undefined , set : canWrite ? set : undefined , } ; } ; const store = ( Object . keys ( initialState ) as PlayerProp [ ] ) . reduce ( ( prev , prop ) => ( { ... prev , [ prop ] : vimeable ( prop , initialState [ prop ] ) , } ) , { } ) ; onMount ( async ( ) => { let el = ref ( ) ; if ( el . $$ ) el = el . getWebComponent ( ) ; const player = await findPlayer ( el ) ; if ( ! player ) return ; dispatch = createDispatcher ( el ) ; internalStoreRef . get ( 'ready' ) ! . set ( player . ready ) ; const disconnect = await usePlayerContext ( el , Object . keys ( initialState ) as PlayerProp [ ] , ( prop , value ) => { internalStoreRef . get ( prop as PlayerProp ) ! . set ( value ) ; } , player ) ; if ( ! player . ready ) { const off = await usePlayerContext ( el , [ 'ready' ] , ( ) => { onPlayerMounted ( ) ; off ( ) ; } , player ) ; } return ( ) => { disconnect ( ) ; internalStoreRef . clear ( ) ; } ; } ) ; return store as any ; } ;