import { Component } from '../component.ts'import { isSSR, strToHash } from '../core.ts'
interface Props { fallback: any cache?: boolean [key: string]: any}
export class Suspense extends Component<Props> { ready = false
constructor(props: Props) { super(props)
const { children, fallback, cache = false, ...rest } = this.props
const str = JSON.stringify(rest, function (_key, val) { if (typeof val === 'function') return `${val}` return val })
this.id = strToHash(JSON.stringify(str)) }
async didMount() { const { children, fallback, cache = false, ...rest } = this.props
if (cache) this.initState = {}
if (this.loadFromCache(cache)) return
const promises = Object.values(rest).map(p => p()) const resolved = await Promise.all(promises)
const data = this.prepareData(rest, resolved, cache)
this.addDataToChildren(data)
this.ready = true this.update() }
ssr() { const { children, fallback, cache = false, ...rest } = this.props
const functions = Object.values(rest).map(p => p())
const data = this.prepareData(rest, functions, false)
this.addDataToChildren(data) }
loadFromCache(cache: boolean) { const hasCachedProps = this.state && cache && Object.keys(this.state).length > 0
if (hasCachedProps) { this.addDataToChildren(this.state) this.ready = true }
return hasCachedProps }
prepareData(rest: any, fnc: Function[], cache: boolean) { const data = Object.keys(rest).reduce((obj, item, index) => { if (cache) this.state = { ...this.state, [item]: fnc[index] } return { ...obj, [item]: fnc[index] } }, {}) return data }
addDataToChildren(data: any) { this.props.children.forEach((child: any) => { if (child.props) child.props = { ...child.props, ...data } }) }
render() { if (!isSSR()) { const { cache = false } = this.props this.loadFromCache(cache) return !this.ready ? this.props.fallback : this.props.children } else { this.ssr() return this.props.children } }}