import React , { useRef , useMemo } from 'react' ; import { ListDomain , ListDomainContext } from '@alist/react' ; import _ from 'lodash' ; import { registerListFuncs , registerListComponent , cleanListComponentRegistry , cleanListFunctionRegistry , getComponentsRegistry , getFuncsRegistry } from './shared' ; const injectFuncs = ( props , funcs ) => { if ( ! props ) return props ; if ( Array . isArray ( props ) ) { return props . map ( item => injectFuncs ( item , funcs ) ) ; } else if ( typeof props === 'object' ) { const obj = { ... props } ; Object . keys ( props ) . forEach ( k => { obj [ k ] = injectFuncs ( obj [ k ] , funcs ) ; } ) ; return obj ; } else if ( typeof props === 'string' ) { if ( props . startsWith ( '$func' ) ) { const fn = props . replace ( /\$func\./ , '' ) ; if ( ! ( fn in funcs ) ) { console . warn ( 'function name:' , fn , 'not found in funcRegistry' ) ; } else { return funcs [ fn ] ; } } else { return props ; } if ( props . startsWith ( '$func' ) && props . replace ( /\$func\./ , '' ) in funcs ) { return funcs [ props ] ; } else { return props ; } } else { return props ; } } ; const renderSchema = ( props , contextProps ) => { const { effects , actions , funcRegistry , componentsRegistry } = contextProps ; const { children , componentName , props : componentProps } = props ; const schemaResult = { component : null , props : { } as any , children : null } ; if ( ! _ . has ( componentsRegistry , componentName ) ) { console . warn ( 'componentName:' , componentName , 'not found in componentsRegistry' ) ; } else { let childs = null ; const arrChilds = [ ... ( children || [ ] ) ] ; if ( Array . isArray ( arrChilds ) && arrChilds . length ) { childs = arrChilds . map ( item => { if ( typeof item === 'string' ) { return item ; } const { component , props : parsedProps , children : parsedChidlren } = renderSchema ( item , contextProps ) ; return React . createElement ( component , parsedProps , parsedChidlren ) ; } ) ; } schemaResult . component = _ . get ( componentsRegistry , componentName ) ; schemaResult . props = injectFuncs ( componentProps || { } , funcRegistry ) ; schemaResult . children = childs ; if ( componentName === 'List' ) { if ( actions ) schemaResult . props . actions = actions ; if ( effects ) schemaResult . props . effects = effects ; } } return schemaResult ; } ; const noop = ( ) => ( { } ) ; const SchemaSolver = props => { const { effects , actions , schema , componentsRegistry = { } , funcRegistry = { } , generateContext = noop } = props ; const { componentsTree = [ ] , i18n = { } } = schema ; const finalFuncRegistry = { ... getFuncsRegistry ( ) , ... ( funcRegistry || { } ) } ; const finalComponentsRegistry = { ... getComponentsRegistry ( ) , ... ( componentsRegistry || { } ) } ; const contextRef = useRef ( null ) ; const context = useMemo ( ( ) => { if ( contextRef . current ) { return contextRef . current ; } else { const ctx = new ListDomain ( ) ; const localCtx = generateContext ( ) || { } ; ctx . setContext ( { schema , actions , effects , componentsRegistry : finalComponentsRegistry , funcRegistry : finalFuncRegistry , i18n , ... localCtx } ) ; return ctx ; } } , [ ] ) ; Object . keys ( finalFuncRegistry ) . forEach ( fn => { finalFuncRegistry [ fn ] = finalFuncRegistry [ fn ] . bind ( context ) ; } ) ; return ( < ListDomainContext . Provider value = { context } > { ( componentsTree || [ ] ) . map ( componentSchema => { const { component , props : rootProps , children : rootChilds } = renderSchema ( componentSchema , context ) ; return React . createElement ( component , rootProps , rootChilds ) ; } ) } < /ListDomainContext.Provider>); } ; export { SchemaSolver as default , registerListFuncs , registerListComponent , cleanListComponentRegistry , cleanListFunctionRegistry } ;