'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(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 }