102 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			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);
 | |
| } |