import { Component , onCleanup } from 'solid-js' ; let PROVIDER ; interface ProviderData < T > { value : T ; } interface ProviderTree { parent ? : ProviderTree ; data : Record < string , ProviderData < any > | undefined > ; } export function capturedProvider < T extends any [ ] , R > ( callback ) { const current = PROVIDER ; return ( ... args ) => { const parent = PROVIDER ; PROVIDER = current ; try { return callback ( ... args ) ; } finally { PROVIDER = parent ; } } ; } export function providerScope < T > ( callback ) { const parent = PROVIDER ; PROVIDER = { parent , data : { } , } ; try { return callback ( ) ; } finally { PROVIDER = parent ; } } export interface Provider < T > { id : number ; defaultValue : T ; } let ID = 0 ; export function createProvider < T > ( defaultValue ) { return { id : ID ++ , defaultValue , } ; } export function provide < T > ( context , value ) { const parent = PROVIDER ; if ( parent ) { parent . data [ context . id ] = { value } ; onCleanup ( ( ) => { parent . data [ context . id ] = undefined ; } ) ; } } export function inject < T > ( context ) { let current = PROVIDER ; while ( current ) { const currentData = current . data [ context . id ] ; if ( currentData ) { return currentData . value ; } current = PROVIDER ?. parent ; } return context . defaultValue ; } export function withProvider < T > ( Comp ) { return ( props ) => providerScope ( ( ) => Comp ( props ) ) ; }