import React from 'react'; import * as ReactDOM from 'react-dom/client'; import r2wc from 'react-to-webcomponent'; import ExcalidrawWrapper from './ExcalidrawElement'; import type { Scene } from './types'; // Importer le type Scene si défini ailleurs import { exportToBlob, exportToSvg } from '@excalidraw/excalidraw'; // Importer les fonctions exportToBlob et exportToSvg // Définition du type pour l'événement personnalisé declare global { interface HTMLElementEventMap { 'ready': CustomEvent<{ apiAvailable: boolean }>; } } // Map attributes/props to React props const BaseCE = r2wc(ExcalidrawWrapper as any, React as any, ReactDOM as any, { props: { initialData: 'json', readOnly: 'boolean', theme: 'string', lang: 'string', gridMode: 'boolean', zenMode: 'boolean', hostRef: 'object', }, // render in light DOM to allow package styles to apply }); class ExcalidrawElement extends (BaseCE as any) { connectedCallback() { // Ensure the React component receives a reference to the host element before first render (this as any).__host = this; (this as any).hostRef = this; // Dispatch a ready event once the API has been set on the host by the React wrapper const onReady = () => { console.log('[excalidraw-editor] 🎨 READY event dispatched', { apiAvailable: !!(this as any).__excalidrawAPI }); this.dispatchEvent(new CustomEvent('ready', { detail: { apiAvailable: !!(this as any).__excalidrawAPI }, bubbles: true, composed: true, })); }; if ((this as any).__excalidrawAPI) { onReady(); } else { const checkApi = setInterval(() => { if ((this as any).__excalidrawAPI) { clearInterval(checkApi); onReady(); } }, 100); } super.connectedCallback?.(); } // Imperative API surface getScene() { const api = (this as any).__excalidrawAPI; if (!api) return { elements: [], appState: {}, files: {} } as Scene; return { elements: api.getSceneElements?.() ?? [], appState: api.getAppState?.() ?? {}, files: api.getFiles?.() ?? {}, } as Scene; } exportPNG(opts?: { withBackground?: boolean }) { const api = (this as any).__excalidrawAPI; if (!api) return { elements: [], appState: {}, files: {} }; const elements = api.getSceneElements?.() ?? []; const appState = { ...(api.getAppState?.() ?? {}), exportBackground: !!opts?.withBackground } as any; const files = api.getFiles?.() ?? {}; return exportToBlob({ elements, appState, files, mimeType: 'image/png', quality: 1 }); } async exportSVG(opts?: { withBackground?: boolean }) { const api = (this as any).__excalidrawAPI; if (!api) return { elements: [], appState: {}, files: {} }; const elements = api.getSceneElements?.() ?? []; const appState = { ...(api.getAppState?.() ?? {}), exportBackground: !!opts?.withBackground } as any; const files = api.getFiles?.() ?? {}; const svgEl = await exportToSvg({ elements, appState, files }); const svgText = new XMLSerializer().serializeToString(svgEl); return new Blob([svgText], { type: 'image/svg+xml' }); } setScene(scene: any) { const api = (this as any).__excalidrawAPI; if (!api) return; api.updateScene(scene); } refresh() { const api = (this as any).__excalidrawAPI; if (!api) return; api.refresh(); } } if (!customElements.get('excalidraw-editor')) { customElements.define('excalidraw-editor', ExcalidrawElement as any); }