102 lines
3.5 KiB
TypeScript

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);
}