import { untrack , createSignal , createResource , createMemo , devComponent , $PROXY , $DEVCOMP } from "../reactive/signal" ; import { sharedConfig , nextHydrateContext , setHydrateContext } from "./hydration" ; import type { JSX } from "../jsx" ; let hydrationEnabled = false ; export function enableHydration ( ) { hydrationEnabled = true ; } export type PropsWithChildren < P = { } > = P & { children ? : JSX . Element ; } ; export type Component < P = { } > = ( props : PropsWithChildren < P > ) => JSX . Element ; example export type ComponentProps < T extends keyof JSX . IntrinsicElements | Component < any > > = T extends Component < infer P > ? P : T extends keyof JSX . IntrinsicElements ? JSX . IntrinsicElements [ T ] : { } ; export function createComponent < T > ( Comp , props ) { if ( hydrationEnabled ) { if ( sharedConfig . context ) { const c = sharedConfig . context ; setHydrateContext ( nextHydrateContext ( ) ) ; const r = "_SOLID_DEV_" ? devComponent ( Comp , props ) : untrack ( ( ) => Comp ( props as T ) ) ; setHydrateContext ( c ) ; return r ; } } if ( "_SOLID_DEV_" ) return devComponent ( Comp , props ) ; return untrack ( ( ) => Comp ( props as T ) ) ; } function trueFn ( ) { return true ; } const propTraps = { get ( _ , property , receiver ) { if ( property === $PROXY ) return receiver ; return _ . get ( property ) ; } , has ( _ , property ) { return _ . has ( property ) ; } , set : trueFn , deleteProperty : trueFn , getOwnPropertyDescriptor ( _ , property ) { return { configurable : true , enumerable : true , get ( ) { return _ . get ( property ) ; } , set : trueFn , deleteProperty : trueFn } ; } , ownKeys ( _ ) { return _ . keys ( ) ; } } ; type BoxedTupleTypes < T extends any [ ] > = { [ P in keyof T ] : [ T [ P ] ] ; } [ Exclude < keyof T , keyof any [ ] > ] ; type UnionToIntersection < U > = ( U extends any ? ( k : U ) => void : never ) extends ( k : infer I ) => void ? I : never ; type UnboxIntersection < T > = T extends { 0 : infer U ; } ? U : never ; type MergeProps < T extends any [ ] > = UnboxIntersection < UnionToIntersection < BoxedTupleTypes < T > > > ; function resolveSource ( s ) { return typeof s === "function" ? s ( ) : s ; } export function mergeProps < T extends any [ ] > ( ... sources ) ; export function mergeProps ( ... sources ) { return new Proxy ( { get ( property ) { for ( let i = sources . length - 1 ; i >= 0 ; i -- ) { const v = resolveSource ( sources [ i ] ) [ property ] ; if ( v !== undefined ) return v ; } } , has ( property ) { for ( let i = sources . length - 1 ; i >= 0 ; i -- ) { if ( property in resolveSource ( sources [ i ] ) ) return true ; } return false ; } , keys ( ) { const keys = [ ] ; for ( let i = 0 ; i < sources . length ; i ++ ) keys . push ( ... Object . keys ( resolveSource ( sources [ i ] ) ) ) ; return [ ... new Set ( keys ) ] ; } } , propTraps ) ; } export function splitProps < T extends object , K1 extends keyof T > ( props , ... keys ) ; export function splitProps < T extends object , K1 extends keyof T , K2 extends keyof T > ( props , ... keys ) ; export function splitProps < T extends object , K1 extends keyof T , K2 extends keyof T , K3 extends keyof T > ( props , ... keys ) ; export function splitProps < T extends object , K1 extends keyof T , K2 extends keyof T , K3 extends keyof T , K4 extends keyof T > ( props , ... keys ) ; export function splitProps < T extends object , K1 extends keyof T , K2 extends keyof T , K3 extends keyof T , K4 extends keyof T , K5 extends keyof T > ( props , ... keys ) ; export function splitProps < T > ( props , ... keys ) { const blocked = new Set ( keys . flat ( ) ) ; const descriptors = Object . getOwnPropertyDescriptors ( props ) ; const res = keys . map ( k => { const clone = { } ; for ( let i = 0 ; i < k . length ; i ++ ) { const key = k [ i ] ; Object . defineProperty ( clone , key , descriptors [ key ] ? descriptors [ key ] : { get ( ) { return props [ key ] ; } , set ( ) { return true ; } } ) ; } return clone ; } ) ; res . push ( new Proxy ( { get ( property ) { return blocked . has ( property as keyof T ) ? undefined : props [ property as keyof T ] ; } , has ( property ) { return blocked . has ( property as keyof T ) ? false : property in props ; } , keys ( ) { return Object . keys ( props ) . filter ( k => ! blocked . has ( k as keyof T ) ) ; } } , propTraps ) ) ; return res ; } export function lazy < T extends Component < any > > ( fn ) { let comp ; let p ; const wrap = ( ( props ) => { const ctx = sharedConfig . context ; if ( ctx ) { ctx . count ++ ; const [ s , set ] = createSignal < T > ( ) ; ( p || ( p = fn ( ) ) ) . then ( mod => { setHydrateContext ( ctx ) ; set ( ( ) => mod . default ) ; setHydrateContext ( ) ; } ) ; comp = s ; } else if ( ! comp ) { const [ s ] = createResource < T > ( ( ) => ( p || ( p = fn ( ) ) ) . then ( mod => mod . default ) , { globalRefetch : false } ) ; comp = s ; } else { const c = comp ( ) ; if ( c ) return c ( props ) ; } let Comp ; return createMemo ( ( ) => ( Comp = comp ( ) ) && untrack ( ( ) => { if ( "_SOLID_DEV_" ) Object . assign ( Comp , { [ $DEVCOMP ] : true } ) ; if ( ! ctx ) return Comp ! ( props ) ; const c = sharedConfig . context ; setHydrateContext ( ctx ) ; const r = Comp ! ( props ) ; setHydrateContext ( c ) ; return r ; } ) ) ; } ) as T ; wrap . preload = ( ) => p || ( ( p = fn ( ) ) . then ( mod => ( comp = ( ) => mod . default ) ) , p ) ; return wrap as T & { preload : ( ) => Promise < { default : T ; } > ; } ; } let counter = 0 ; export function createUniqueId ( ) { const ctx = sharedConfig . context ; return ctx ? `${ ctx . id }${ ctx . count ++ }` : `cl:${ counter ++ }` ; }