modatatool
v0.2.1
Published
Visual data modeling diagram tool - React component for creating entity relationship diagrams
Downloads
329
Maintainers
Readme
Modatatool
A visual data modeling diagram tool for React. Create entity-relationship diagrams with an intuitive drag-and-drop interface.
Features
- 🎨 Interactive entity-relationship diagram editor
- 🔄 Multiple relationship types (1:1, 1:N, N:M)
- 📦 Sub-entities and enum types support
- 🎯 Auto-layout with configurable directions
- 💾 Import/Export schemas (JSON, PNG, SVG)
- 🎨 Customizable entity colors
- 📱 Responsive and touch-friendly
- 💪 TypeScript support
Installation
npm install modatatool
# or
yarn add modatatool
# or
pnpm add modatatoolUsage
import { ModataCanvas } from 'modatatool';
import 'modatatool/styles.css';
import '@xyflow/react/dist/style.css';
function App() {
return (
<div style={{ width: '100vw', height: '100vh' }}>
<ModataCanvas />
</div>
);
}API
ModataCanvas
The main component that renders the entire diagram editor with sidebar controls.
<ModataCanvas />Props (ModataCanvasProps)
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| data | DiagramSchema | — | Initial diagram data to load on mount (instead of localStorage) |
| onChange | (schema: DiagramSchema) => void | — | Called on any diagram change (debounced 800ms) |
| onSave | (schema: DiagramSchema) => void | — | Called when the user clicks Save |
| onExportImage | (blob: Blob, filename: string) => void | — | Custom PNG export handler (receives a Blob) |
| onExportSvg | (blob: Blob, filename: string) => void | — | Custom SVG export handler (receives a Blob) |
| onExportJSON | (schema: DiagramSchema, filename: string) => void | — | Custom JSON export handler |
| onImport | () => Promise<DiagramSchema> | — | Custom import handler (replaces file picker) |
| persistInLocalStorage | boolean | true | Enable/disable auto-saving to localStorage |
| readOnly | boolean | false | Disable all editing (nodes, edges, entity creation) |
Ref API (ModataCanvasRef)
You can pass a ref to ModataCanvas to programmatically trigger exports and retrieve the diagram schema from an external component.
import { useRef } from 'react';
import { ModataCanvas, type ModataCanvasRef } from 'modatatool';
import 'modatatool/styles.css';
import '@xyflow/react/dist/style.css';
function App() {
const canvasRef = useRef<ModataCanvasRef>(null);
const handleExportPng = async () => {
const blob = await canvasRef.current!.exportPng();
// Do something with the PNG blob (upload, display, etc.)
};
const handleExportSvg = async () => {
const blob = await canvasRef.current!.exportSvg();
// Do something with the SVG blob
};
const handleExportJSON = () => {
const json = canvasRef.current!.exportJSON();
console.log(json); // JSON string of the diagram schema
};
const handleGetSchema = () => {
const schema = canvasRef.current!.getSchema();
// DiagramSchema object
};
return (
<div style={{ width: '100vw', height: '100vh' }}>
<div>
<button onClick={handleExportPng}>Export PNG</button>
<button onClick={handleExportSvg}>Export SVG</button>
<button onClick={handleExportJSON}>Export JSON</button>
<button onClick={handleGetSchema}>Get Schema</button>
</div>
<ModataCanvas ref={canvasRef} />
</div>
);
}| Method | Return Type | Description |
|--------|-------------|-------------|
| getSchema() | DiagramSchema | Returns the current diagram schema object |
| exportPng() | Promise<Blob> | Generates and returns a PNG blob of the diagram |
| exportSvg() | Promise<Blob> | Generates and returns an SVG blob of the diagram |
| exportJSON() | string | Returns the diagram schema as a formatted JSON string |
Server Integration Example
import { ModataCanvas, type DiagramSchema, type ModataCanvasProps } from 'modatatool';
import 'modatatool/styles.css';
import '@xyflow/react/dist/style.css';
function App() {
const handleChange = (schema: DiagramSchema) => {
// Auto-sync to server on every change
fetch('/api/diagrams/123', {
method: 'PUT',
body: JSON.stringify(schema),
});
};
const handleSave = (schema: DiagramSchema) => {
// Explicit save action
fetch('/api/diagrams', {
method: 'POST',
body: JSON.stringify(schema),
});
};
const handleExportImage = (blob: Blob, filename: string) => {
// Upload PNG to server instead of downloading
const formData = new FormData();
formData.append('image', blob, filename);
fetch('/api/uploads', { method: 'POST', body: formData });
};
return (
<div style={{ width: '100vw', height: '100vh' }}>
<ModataCanvas
data={initialSchemaFromServer}
onChange={handleChange}
onSave={handleSave}
onExportImage={handleExportImage}
persistInLocalStorage={false}
/>
</div>
);
}Hooks
useDiagramStore
Access the diagram state and actions:
import { useDiagramStore } from 'modatatool';
function MyComponent() {
const nodes = useDiagramStore((s) => s.nodes);
const edges = useDiagramStore((s) => s.edges);
const addEntity = useDiagramStore((s) => s.addEntity);
// Add entity programmatically
const handleAdd = () => {
addEntity({ x: 100, y: 100 });
};
return <button onClick={handleAdd}>Add Entity</button>;
}Utilities
Auto Layout
import { autoLayout } from 'modatatool';
const layoutedNodes = autoLayout(nodes, edges, 'TB'); // 'TB' or 'LR'Export
import { exportPng, exportSvg, exportSchemaJSON } from 'modatatool';
// Export as PNG
await exportPng('my-diagram.png', nodes);
// Export as SVG
await exportSvg('my-diagram.svg', nodes);
// Export schema as JSON
const schema = useDiagramStore.getState().toDiagramSchema();
exportSchemaJSON(schema);Persistence
import {
saveDiagram,
loadDiagram,
listSavedDiagrams
} from 'modatatool';
// Save to localStorage
saveDiagram(schema);
// Load from localStorage
const loaded = loadDiagram('diagram-name');
// List all saved diagrams
const diagrams = listSavedDiagrams();Types
Field Types
- Primitive:
int,uuid,decimal,string,boolean,date,datetime - Enum: Custom enums with user-defined options
- Sub-entity: Nested entity definitions
Relationship Types
- 1:1 (One-to-One)
- 1:N (One-to-Many) - Direction can be swapped
- N:M (Many-to-Many)
Development
# Install dependencies
npm install
# Run demo app
npm run dev
# Build library
npm run build:lib
# Build demo
npm run buildPublishing to NPM
To publish this package to npm:
Build the library:
npm run build:libUpdate version in
package.json(following semver):npm version patch # or minor, or majorLogin to npm (if not already logged in):
npm loginPublish:
npm publish
License
MIT
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
