You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
69 lines
1.8 KiB
TypeScript
69 lines
1.8 KiB
TypeScript
'use client'
|
|
|
|
import type { ContentModule, ScriptModule, WasmModuleParam, ResourceFileParam, StringParam } from "./types"
|
|
import { useEffect, useRef } from "react"
|
|
import { themeSignal } from "../Appearance"
|
|
|
|
interface ScriptLoaderClientParams {
|
|
src: ScriptModule,
|
|
wasm: WasmModuleParam | undefined,
|
|
rest: {
|
|
[name: string]: ResourceFileParam | StringParam
|
|
}
|
|
}
|
|
|
|
export default function ScriptLoaderClient({ src, wasm, rest }: ScriptLoaderClientParams) {
|
|
const moduleRef = useRef<ContentModule | null>(null)
|
|
|
|
useEffect(() => {
|
|
(async () => {
|
|
if (!src) return undefined
|
|
|
|
const scriptModule : ContentModule = await import(/*webpackIgnore: true */ src.path)
|
|
|
|
let wasmModule: WebAssembly.Instance | undefined = undefined
|
|
|
|
if (wasm) {
|
|
const instantiatedWasm = await WebAssembly.instantiateStreaming(fetch(wasm.binaryPath))
|
|
wasmModule = instantiatedWasm.instance
|
|
}
|
|
|
|
moduleRef.current = scriptModule
|
|
|
|
const restProps = Object.keys(rest).reduce((acc: {[name: string]: string}, propName: string) => {
|
|
const prop = rest[propName]
|
|
return {
|
|
...acc,
|
|
[propName]: prop.type === 'string' ? prop.value : prop
|
|
}
|
|
}, {})
|
|
|
|
if (scriptModule.setup && typeof scriptModule.setup === 'function')
|
|
scriptModule.setup(restProps, wasmModule)
|
|
})()
|
|
|
|
return () => {
|
|
const mod = moduleRef.current
|
|
|
|
if (mod?.cleanup && typeof mod.cleanup === 'function') {
|
|
mod.cleanup()
|
|
}
|
|
}
|
|
}, [])
|
|
|
|
useEffect(() => {
|
|
function onThemeChange() {
|
|
const mod = moduleRef.current
|
|
|
|
if (mod?.onThemeChange && typeof mod?.onThemeChange === 'function') {
|
|
mod.onThemeChange()
|
|
}
|
|
}
|
|
|
|
themeSignal.addListener('change', onThemeChange)
|
|
return () => { themeSignal.removeListener('change', onThemeChange) }
|
|
}, [])
|
|
|
|
return null
|
|
}
|