@drawio/react: the draw.io editor as a React component. Runs the editor in
an iframe in embed mode (embed=1&proto=json) and wraps the JSON protocol in
typed props, events and methods. Docs: https://www.drawio.com/react (the
/react page in the private jgraph/drawusaurus repo).
The focus is getting started quickly: examples people copy into their app.
Keep the API small and the examples short; protocol depth belongs in the
embed mode reference (docs/reference/embed-mode.md in drawusaurus).
src/protocol.ts: types of every action and event. The source of truth isEditorUi.prototype.installMessageHandlerin jgraph/drawio (src/main/webapp/js/diagramly/EditorUi.js), not the docs (they had thedraftresults capitalised and listedpublishCloseas a load option).src/client.ts:DrawioClient, framework-agnostic.src/DrawioEditor.tsx: the React component, a thin layer over the client.src/url.ts:buildEditorUrl.examples/src/*.tsx: one example per file, imported as@drawio/react(aliased tosrc/byexamples/vite.config.ts). The drawusaurus page shows the same code: change both.test/*.test.ts(x): Vitest with jsdom.test/e2e/run.mjs: the real editor in headless Chrome for Testing, the protocol scenarios oftest/e2e/appand every example (test/e2e/examples.mjs).
- Messages: accept only
evt.source === iframe.contentWindowandevt.originequal to the origin of the editor URL; post only with that origin astargetOrigin, never"*". Several editors on one page must not see each other's messages. - Editor URL: only
http:andhttps:(parseEditorUrl, used bybuildEditorUrland theDrawioClientconstructor): ajavascript:iframe URL runs in the host's origin, adata:URL has origin"null". - Unexpected start: a
configureorinitthe client did not cause (a link in the diagram opened another page of the editor's origin in the iframe) makes the client load its own URL again (reload), so the editor never runs without the host's URL parameters. - URL change (React): the old editor gets
setModified(false)(no prompt for unsaved changes when the iframe navigates) andgetXml(), then the reloaded editor loads that diagram. Restarts load the last diagram the editor reported, not stale props. - Listener before URL: the client sets the iframe
srcafter it listens, so it cannot missinit. The component renders the iframe withoutsrc(SSR-safe) and lets the client set it in a layout effect. - Unmount (React): the client closes in a
setTimeout(0)that the next effect run cancels, so strict mode keeps it and a real unmount rejects pending requests. - Requests: responses are matched by the
requestIdthe client adds, which the editor echoes inmessage. Only theloadresponse lacks the echo (except for descriptors). Reject requests the editor would never answer (mergewithout data,resetDiffwithout diff sync) instead of letting them time out. - Iframe color scheme: the default style has
colorScheme: "normal", the scheme of the editor page. A frame whose scheme differs from its document gets an opaque backdrop, which hides dark pages behind the inline editor and flashes white while the editor loads. - Remote functions: look names up with
hasOwnPropertyonly. - Clean room: do not read the source of other draw.io React wrappers (react-drawio and its forks). Their READMEs and issue titles are fine.
npm test && npm run typecheck && npm run build
DRAWIO_URL=https://test.draw.io/?dev=1 npm run test:e2eThe examples (npm run examples) use embed.diagrams.net,
http://localhost:5173/?dev=1 uses https://test.draw.io/?dev=1 (the local
draw.io), and DRAWIO_URL overrides both (examples/dev-editor.tsx).
embed.diagrams.net answers 403 to headless Chrome, so run the e2e tests
against a local draw.io (src/main/webapp of jgraph/drawio over http; CI
uses a sparse checkout). It also refuses embedding pages on a port other
than 80 and 443, except localhost, and some sites; a self-hosted draw.io has
no such limits. These refusals are draw.io's policy: never work around them
(no referrerpolicy="no-referrer" on the iframe, no user agent tricks).
TypeScript is pinned to 6.x: tsup's declaration build needs the compiler API, which TypeScript 7 does not have.
2-space indentation, braces on their own line, double quotes, like jgraph/drawio-mcp. Comments say why, briefly.