"use client" import { useEffect, useRef } from "react" type DocEditorInstance = { destroyEditor: () => void } declare global { interface Window { DocsAPI?: { DocEditor: new (id: string, config: Record) => DocEditorInstance } DocEditor?: { instances: Record } } } let docsApiLoad: Promise | null = null function loadDocsApi(documentServerUrl: string, scriptId: string): Promise { if (window.DocsAPI) return Promise.resolve() if (docsApiLoad) return docsApiLoad const base = documentServerUrl.replace(/\/$/, "") + "/" docsApiLoad = new Promise((resolve, reject) => { const script = document.createElement("script") script.id = scriptId script.src = `${base}web-apps/apps/api/documents/api.js` script.async = true script.onload = () => resolve() script.onerror = () => { docsApiLoad = null reject(new Error(`Error load DocsAPI from ${base}`)) } document.body.appendChild(script) }) return docsApiLoad } function destroyDocEditor(id: string) { const inst = window.DocEditor?.instances?.[id] if (inst) { try { inst.destroyEditor() } catch { /* ignore */ } delete window.DocEditor!.instances[id] } document.getElementById(id)?.replaceChildren() } export function OnlyOfficeMount({ editorId, documentServerUrl, config, onError, scriptId = "onlyoffice-docs-api", }: { editorId: string documentServerUrl: string config: Record onError: (message: string) => void scriptId?: string }) { const configJson = JSON.stringify(config) const onErrorRef = useRef(onError) onErrorRef.current = onError useEffect(() => { let cancelled = false const id = editorId const parsed = JSON.parse(configJson) as Record const editorConfig: Record = { type: "desktop", width: "100%", height: "100%", events: { onDocumentReady: () => { /* loaded */ }, onError: (event: { data?: { errorCode?: number; errorDescription?: string } }) => { const code = event?.data?.errorCode const desc = event?.data?.errorDescription const msg = desc || (code != null ? `OnlyOffice error ${code}` : "Erreur OnlyOffice.") onErrorRef.current(msg) }, }, ...parsed, } void loadDocsApi(documentServerUrl, scriptId) .then(() => { if (cancelled) return if (!window.DocsAPI) throw new Error("DocsAPI is not defined") destroyDocEditor(id) if (!window.DocEditor) window.DocEditor = { instances: {} } const editor = new window.DocsAPI.DocEditor(id, editorConfig) window.DocEditor.instances[id] = editor }) .catch((err: unknown) => { if (!cancelled) { onErrorRef.current( err instanceof Error ? err.message : "Impossible de charger OnlyOffice.", ) } }) return () => { cancelled = true destroyDocEditor(id) } }, [editorId, documentServerUrl, configJson, scriptId]) return
}