# Component Architecture of DrawDB: Editor Canvas and Code Editor Explained

> Explore DrawDB's component architecture featuring EditorCanvas and CodeEditor. Discover how its layered React design and dedicated hooks ensure isolated functionality for a seamless user experience.

- Repository: [drawDB/drawdb](https://github.com/drawdb-io/drawdb)
- Tags: architecture
- Published: 2026-08-14

---

**DrawDB implements a layered React architecture where [`src/pages/Editor.jsx`](https://github.com/drawdb-io/drawdb/blob/main/src/pages/Editor.jsx) nests multiple Context providers to manage state for the visual `Canvas` and text-based code editors (`RichEditor` and `DBMLEditor`), enabling isolated functionality through dedicated hooks like `useCanvas` and `useDiagram`.**

The drawdb-io/drawdb repository organizes its frontend as a hierarchy of specialized React components and context providers. This component architecture separates visual diagramming logic from text editing capabilities while maintaining synchronized state across the application through a centralized provider pattern.

## Top-Level Provider Stack in Editor.jsx

The entry point for the drawing interface resides in [`src/pages/Editor.jsx`](https://github.com/drawdb-io/drawdb/blob/main/src/pages/Editor.jsx). This file does not render UI directly; instead, it composes a nested stack of Context providers that wrap the `Workspace` component. Each provider establishes a specific domain of state—such as layout transforms, undo/redo history, or diagram entities.

According to the drawDB source code, the provider hierarchy follows this structure:

```jsx
// src/pages/Editor.jsx
import LayoutContextProvider from "../context/LayoutContext";
import TransformContextProvider from "../context/TransformContext";
import TablesContextProvider from "../context/DiagramContext";
import UndoRedoContextProvider from "../context/UndoRedoContext";
import SelectContextProvider from "../context/SelectContext";
import AreasContextProvider from "../context/AreasContext";
import NotesContextProvider from "../context/NotesContext";
import TypesContextProvider from "../context/TypesContext";
import SettingsContextProvider from "../context/SettingsContext";
import SaveStateContextProvider from "../context/SaveStateContext";
import EnumsContextProvider from "../context/EnumsContext";
import WorkSpace from "../components/Workspace";

export default function Editor() {
  return (
    <SettingsContextProvider>
      <LayoutContextProvider>
        <TransformContextProvider>
          <UndoRedoContextProvider>
            <SelectContextProvider>
              <AreasContextProvider>
                <NotesContextProvider>
                  <TypesContextProvider>
                    <EnumsContextProvider>
                      <TablesContextProvider>
                        <SaveStateContextProvider>
                          <WorkSpace />
                        </SaveStateContextProvider>
                      </TablesContextProvider>
                    </EnumsContextProvider>
                  </TypesContextProvider>
                </NotesContextProvider>
              </AreasContextProvider>
            </SelectContextProvider>
          </UndoRedoContextProvider>
        </TransformContextProvider>
      </LayoutContextProvider>
    </SettingsContextProvider>
  );
}

```

This nesting ensures that child components can access specific contexts via custom hooks without prop drilling.

## The Workspace Component

[`src/components/Workspace.jsx`](https://github.com/drawdb-io/drawdb/blob/main/src/components/Workspace.jsx) serves as the primary layout shell. It splits the interface into two main regions: the interactive diagram canvas and the side panel containing code editors. The Workspace itself remains agnostic of state management logic, consuming contexts through hooks rather than receiving props.

## Editor Canvas Architecture

The **Canvas** component ([`src/components/Canvas.jsx`](https://github.com/drawdb-io/drawdb/blob/main/src/components/Canvas.jsx)) renders the visual database diagram using HTML5 Canvas or SVG elements. It relies on several specialized contexts:

- **`TransformContext`**: Manages zoom levels and pan coordinates
- **`DiagramContext`** (Tables): Stores table definitions, fields, and relationships
- **`SelectContext`**: Tracks currently selected entities
- **`AreasContext`**: Handles groupings and bounded regions
- **`NotesContext`**: Manages annotation objects

Utility functions in [`src/utils/arrangeTables.js`](https://github.com/drawdb-io/drawdb/blob/main/src/utils/arrangeTables.js) and [`src/utils/autoArrange.js`](https://github.com/drawdb-io/drawdb/blob/main/src/utils/autoArrange.js) calculate optimal positioning, while [`src/utils/calcPath.js`](https://github.com/drawdb-io/drawdb/blob/main/src/utils/calcPath.js) renders relationship lines between tables.

To interact with the canvas programmatically, components use the `useCanvas` hook:

```javascript
// src/hooks/useCanvas.js
import { useContext } from 'react';
import { CanvasContext } from '../context/CanvasContext';

export default function useCanvas() {
  const context = useContext(CanvasContext);
  if (!context) {
    throw new Error('useCanvas must be used within CanvasContextProvider');
  }
  return context;
}

```

## Code Editor Components

DrawDB provides two distinct editing interfaces for schema manipulation:

### RichEditor (SQL Editing)

[`src/components/LexicalEditor/RichEditor.jsx`](https://github.com/drawdb-io/drawdb/blob/main/src/components/LexicalEditor/RichEditor.jsx) implements a syntax-highlighted SQL editor using the Lexical framework. This component integrates with `UndoRedoContext` to provide history management and `TypesContext` for auto-completion of data types.

### DBMLEditor

[`src/components/EditorSidePanel/DBMLEditor.jsx`](https://github.com/drawdb-io/drawdb/blob/main/src/components/EditorSidePanel/DBMLEditor.jsx) offers a dedicated interface for DBML (Database Markup Language) syntax. Unlike the rich editor, this component typically operates as a controlled textarea with validation logic from [`src/utils/validateSchema.js`](https://github.com/drawdb-io/drawdb/blob/main/src/utils/validateSchema.js).

## State Management: Contexts and Hooks

Each domain-specific context pairs with a corresponding hook in `src/hooks/`:

- **`useDiagram()`**: Accesses table and relationship state from `DiagramContext`
- **`useUndoRedo()`**: Controls history stacks for reversible actions
- **`useLayout()`**: Manages sidebar and panel visibility states
- **`useSettings()`**: Persists user preferences to local storage

These hooks enforce type safety and provide consistent error handling when consumed outside their providers.

## Utility Layer

Supporting modules in `src/utils/` handle complex operations outside the React render cycle:

- **[`validateSchema.js`](https://github.com/drawdb-io/drawdb/blob/main/validateSchema.js)**: Validates SQL and DBML before export
- **[`exportSavedData.js`](https://github.com/drawdb-io/drawdb/blob/main/exportSavedData.js)**: Serializes diagram state to JSON
- **[`diff.js`](https://github.com/drawdb-io/drawdb/blob/main/diff.js)**: Calculates state differences for efficient saves
- **[`calcPath.js`](https://github.com/drawdb-io/drawdb/blob/main/calcPath.js)**: Computes Bézier curves for relationship rendering

## Summary

- **DrawDB** uses a nested Context provider pattern in [`src/pages/Editor.jsx`](https://github.com/drawdb-io/drawdb/blob/main/src/pages/Editor.jsx) to manage global state without prop drilling.
- The **`Workspace`** component serves as the layout container, hosting both visual and text editing interfaces.
- **`Canvas`** handles diagram rendering through specialized contexts like `TransformContext` and `DiagramContext`, supported by arrangement utilities.
- **Code editing** splits between **`RichEditor`** (Lexical-based SQL) and **`DBMLEditor`** for markup syntax.
- Custom hooks (**`useCanvas`**, **`useDiagram`**, **`useUndoRedo`**) provide type-safe access to context values across the component tree.

## Frequently Asked Questions

### How does DrawDB manage zoom and pan functionality in the Canvas?

The zoom and pan functionality is managed through **`TransformContext`** and consumed via the `useTransform` hook. The context stores current scale and offset coordinates, while the **`Canvas`** component applies these values as CSS transforms or Canvas coordinate adjustments. Utility functions in [`src/utils/calcPath.js`](https://github.com/drawdb-io/drawdb/blob/main/src/utils/calcPath.js) recalculate relationship paths when transforms change.

### What is the difference between DiagramContext and CanvasContext?

**`DiagramContext`** (aliased as TablesContext in the provider hierarchy) manages the semantic data model—tables, columns, indexes, and foreign keys—while **`CanvasContext`** handles the visual representation state such as zoom levels, pan positions, and selection boxes. This separation allows the underlying data to persist independently of viewport changes.

### How does DrawDB implement undo/redo functionality?

DrawDB implements undo/redo through **`UndoRedoContext`**, which maintains a history stack of immutable state snapshots. Components dispatch actions that the context reduces into new states, pushing the previous state onto an undo stack. The **`useUndoRedo`** hook exposes `undo()` and `redo()` methods that pop states from these stacks and restore previous configurations.

### Which component is responsible for SQL syntax highlighting?

SQL syntax highlighting is handled by **`RichEditor`** in [`src/components/LexicalEditor/RichEditor.jsx`](https://github.com/drawdb-io/drawdb/blob/main/src/components/LexicalEditor/RichEditor.jsx). This component leverages the Lexical editor framework to provide token-based highlighting, auto-completion via **`TypesContext`**, and integrated validation through [`src/utils/validateSchema.js`](https://github.com/drawdb-io/drawdb/blob/main/src/utils/validateSchema.js) before exporting the final SQL DDL.