@dlh.io/dlh-erd-viewer-deux 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +410 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -7,4 +7,413 @@ Popular ERD viewer designed by DLH.io originally to provide a better ERD experie
|
|
|
7
7
|
Future features and enhancements are taken by reqeust and PR.
|
|
8
8
|
|
|
9
9
|
## More about DLH.io
|
|
10
|
-
ETL/ELT, data integration, API solutions, and data engineering for reports, dashboards, and AI use cases. See more at [DLH.io](DLH.io)
|
|
10
|
+
ETL/ELT, data integration, API solutions, and data engineering for reports, dashboards, and AI use cases. See more at [DLH.io](DLH.io)
|
|
11
|
+
|
|
12
|
+
# @dlh.io/dlh-erd-viewer-deux
|
|
13
|
+
|
|
14
|
+
A React component for visualizing database Entity-Relationship Diagrams (ERD) from DBML and TBLS schema formats.
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install @dlh.io/dlh-erd-viewer-deux
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Quick Start
|
|
23
|
+
|
|
24
|
+
```tsx
|
|
25
|
+
import { ERDViewer } from '@dlh.io/dlh-erd-viewer-deux';
|
|
26
|
+
import '@dlh.io/dlh-erd-viewer-deux/styles.css';
|
|
27
|
+
|
|
28
|
+
const dbmlSchema = `
|
|
29
|
+
Table users {
|
|
30
|
+
id integer [pk]
|
|
31
|
+
username varchar(255) [not null]
|
|
32
|
+
email varchar(255) [not null]
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
Table posts {
|
|
36
|
+
id integer [pk]
|
|
37
|
+
title varchar(255) [not null]
|
|
38
|
+
author_id integer [ref: > users.id]
|
|
39
|
+
}
|
|
40
|
+
`;
|
|
41
|
+
|
|
42
|
+
function App() {
|
|
43
|
+
return (
|
|
44
|
+
<div style={{ width: '100%', height: '600px' }}>
|
|
45
|
+
<ERDViewer
|
|
46
|
+
format="dbml"
|
|
47
|
+
content={dbmlSchema}
|
|
48
|
+
/>
|
|
49
|
+
</div>
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Props
|
|
55
|
+
|
|
56
|
+
### Required Props
|
|
57
|
+
|
|
58
|
+
| Prop | Type | Description |
|
|
59
|
+
|------|------|-------------|
|
|
60
|
+
| `format` | `'dbml' \| 'tbls'` | The schema format of the content |
|
|
61
|
+
| `content` | `string` | The schema content to parse and display |
|
|
62
|
+
|
|
63
|
+
### Optional Props
|
|
64
|
+
|
|
65
|
+
| Prop | Type | Default | Description |
|
|
66
|
+
|------|------|---------|-------------|
|
|
67
|
+
| `className` | `string` | `''` | Additional CSS class names for the container |
|
|
68
|
+
| `style` | `React.CSSProperties` | - | Inline styles for the container |
|
|
69
|
+
| `positions` | `PositionMetadata` | - | Pre-defined table positions for the layout |
|
|
70
|
+
| `devMode` | `boolean` | `false` | Enable developer mode with position copying tools |
|
|
71
|
+
| `draggable` | `boolean` | `false` | Allow users to drag and reposition tables |
|
|
72
|
+
| `showMinimap` | `boolean` | `true` | Show or hide the minimap navigation |
|
|
73
|
+
| `showInfoPanel` | `boolean` | `true` | Show or hide the information side panel |
|
|
74
|
+
| `displayMode` | `DisplayMode` | `'all'` | Column display mode: `'all'`, `'keys'`, or `'tableOnly'` |
|
|
75
|
+
| `layoutAlgorithm` | `LayoutAlgorithm` | `'default'` | Layout algorithm for table positioning |
|
|
76
|
+
| `reverseAnimationFlow` | `boolean` | `false` | Reverse the animation flow direction on connector lines |
|
|
77
|
+
| `tableOnlyConnectionMode` | `TableOnlyConnectionMode` | `'center'` | Connection mode when in table-only display |
|
|
78
|
+
| `toolbarAlignment` | `PanelAlignment` | `'center'` | Toolbar position: `'left'`, `'center'`, or `'right'` |
|
|
79
|
+
| `infoPaneAlignment` | `PanelAlignment` | `'right'` | Info panel position: `'left'` or `'right'` |
|
|
80
|
+
| `printExportLogo` | `string` | DLH logo | URL of logo to watermark on exports |
|
|
81
|
+
| `printExportLogoPosition` | `WatermarkPosition` | `'top-left'` | Position of watermark: `'top-left'`, `'top-right'`, `'bottom-left'`, `'bottom-right'` |
|
|
82
|
+
| `theme` | `ERDViewerTheme` | - | Theme overrides via CSS custom properties |
|
|
83
|
+
|
|
84
|
+
### Callback Props
|
|
85
|
+
|
|
86
|
+
| Prop | Type | Description |
|
|
87
|
+
|------|------|-------------|
|
|
88
|
+
| `onExport` | `(format: 'png' \| 'pdf') => void` | Called when diagram is exported |
|
|
89
|
+
| `onPositionsChange` | `(positions: PositionMetadata) => void` | Called when table positions change (in devMode or draggable) |
|
|
90
|
+
| `onTableSelect` | `(table: Table \| null) => void` | Called when a table is selected |
|
|
91
|
+
| `onColumnSelect` | `(table: Table \| null, columnName: string \| null) => void` | Called when a column is selected |
|
|
92
|
+
| `onDisplayModeChange` | `(mode: DisplayMode) => void` | Called when display mode changes |
|
|
93
|
+
| `onLayoutAlgorithmChange` | `(algorithm: LayoutAlgorithm) => void` | Called when layout algorithm changes |
|
|
94
|
+
|
|
95
|
+
## Types
|
|
96
|
+
|
|
97
|
+
### DisplayMode
|
|
98
|
+
|
|
99
|
+
Controls which columns are shown in table cards:
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
type DisplayMode = 'all' | 'keys' | 'tableOnly';
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
- `'all'` - Show all columns
|
|
106
|
+
- `'keys'` - Show only primary and foreign key columns
|
|
107
|
+
- `'tableOnly'` - Show only table names (no columns)
|
|
108
|
+
|
|
109
|
+
### LayoutAlgorithm
|
|
110
|
+
|
|
111
|
+
Controls how tables are automatically positioned:
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
type LayoutAlgorithm = 'default' | 'hierarchical' | 'force' | 'grid' | 'spiral' | 'proximity';
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
- `'default'` - Dagre-based top-to-bottom layout
|
|
118
|
+
- `'hierarchical'` - Left-to-right hierarchical layout
|
|
119
|
+
- `'force'` - Force-directed layout
|
|
120
|
+
- `'grid'` - Grid pattern layout
|
|
121
|
+
- `'spiral'` - Spiral pattern layout
|
|
122
|
+
- `'proximity'` - Groups related tables together
|
|
123
|
+
|
|
124
|
+
### PanelAlignment
|
|
125
|
+
|
|
126
|
+
```typescript
|
|
127
|
+
type PanelAlignment = 'left' | 'center' | 'right';
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### WatermarkPosition
|
|
131
|
+
|
|
132
|
+
```typescript
|
|
133
|
+
type WatermarkPosition = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### PositionMetadata
|
|
137
|
+
|
|
138
|
+
Pre-defined positions for tables:
|
|
139
|
+
|
|
140
|
+
```typescript
|
|
141
|
+
interface PositionMetadata {
|
|
142
|
+
schemaFormat?: 'dbml' | 'tbls';
|
|
143
|
+
capturedAt?: string;
|
|
144
|
+
version?: string;
|
|
145
|
+
positions: TablePosition[];
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
interface TablePosition {
|
|
149
|
+
tableName: string;
|
|
150
|
+
x: number;
|
|
151
|
+
y: number;
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## CSS Customization
|
|
156
|
+
|
|
157
|
+
The component uses CSS custom properties (variables) for theming. You can override these in your application's CSS:
|
|
158
|
+
|
|
159
|
+
```css
|
|
160
|
+
:root {
|
|
161
|
+
/* Core colors */
|
|
162
|
+
--erd-primary: #3b82f6;
|
|
163
|
+
--erd-secondary: #64748b;
|
|
164
|
+
--erd-background: #ffffff;
|
|
165
|
+
--erd-surface: #f8fafc;
|
|
166
|
+
--erd-border: #e2e8f0;
|
|
167
|
+
--erd-text: #1e293b;
|
|
168
|
+
--erd-text-muted: #64748b;
|
|
169
|
+
--erd-highlight: #3b82f6;
|
|
170
|
+
|
|
171
|
+
/* Key indicators */
|
|
172
|
+
--erd-pk: #eab308; /* Primary key color */
|
|
173
|
+
--erd-fk: #8b5cf6; /* Foreign key color */
|
|
174
|
+
|
|
175
|
+
/* Typography */
|
|
176
|
+
--erd-font-family: ui-sans-serif, system-ui, sans-serif;
|
|
177
|
+
--erd-font-mono: ui-monospace, monospace;
|
|
178
|
+
|
|
179
|
+
/* Toolbar */
|
|
180
|
+
--erd-toolbar-text: #1e293b;
|
|
181
|
+
|
|
182
|
+
/* Connector lines */
|
|
183
|
+
--erd-edge-color: #64748b;
|
|
184
|
+
--erd-edge-highlight-color: #3b82f6;
|
|
185
|
+
--erd-animation-color: #3b82f6;
|
|
186
|
+
|
|
187
|
+
/* Table cards */
|
|
188
|
+
--erd-table-header-bg: #3b82f6;
|
|
189
|
+
--erd-table-header-text: #ffffff;
|
|
190
|
+
--erd-table-column-bg: #ffffff;
|
|
191
|
+
--erd-table-column-highlight-bg: #eff6ff;
|
|
192
|
+
|
|
193
|
+
/* Info panel */
|
|
194
|
+
--erd-info-panel-bg: #ffffff;
|
|
195
|
+
--erd-info-panel-header-bg: #f8fafc;
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### Using the theme prop
|
|
200
|
+
|
|
201
|
+
You can also pass theme overrides directly via the `theme` prop:
|
|
202
|
+
|
|
203
|
+
```tsx
|
|
204
|
+
<ERDViewer
|
|
205
|
+
format="dbml"
|
|
206
|
+
content={schema}
|
|
207
|
+
theme={{
|
|
208
|
+
'--erd-primary': '#10b981',
|
|
209
|
+
'--erd-highlight': '#10b981',
|
|
210
|
+
'--erd-table-header-bg': '#10b981',
|
|
211
|
+
}}
|
|
212
|
+
/>
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
## Examples
|
|
216
|
+
|
|
217
|
+
### Basic Usage
|
|
218
|
+
|
|
219
|
+
```tsx
|
|
220
|
+
import { ERDViewer } from '@dlh.io/dlh-erd-viewer-deux';
|
|
221
|
+
import '@dlh.io/dlh-erd-viewer-deux/styles.css';
|
|
222
|
+
|
|
223
|
+
function BasicExample() {
|
|
224
|
+
const schema = `
|
|
225
|
+
Table users {
|
|
226
|
+
id integer [pk]
|
|
227
|
+
name varchar(255)
|
|
228
|
+
}
|
|
229
|
+
`;
|
|
230
|
+
|
|
231
|
+
return (
|
|
232
|
+
<div style={{ width: '100%', height: '500px' }}>
|
|
233
|
+
<ERDViewer format="dbml" content={schema} />
|
|
234
|
+
</div>
|
|
235
|
+
);
|
|
236
|
+
}
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
### With Custom Layout and Display Mode
|
|
240
|
+
|
|
241
|
+
```tsx
|
|
242
|
+
function CustomLayoutExample() {
|
|
243
|
+
return (
|
|
244
|
+
<ERDViewer
|
|
245
|
+
format="dbml"
|
|
246
|
+
content={schema}
|
|
247
|
+
layoutAlgorithm="hierarchical"
|
|
248
|
+
displayMode="keys"
|
|
249
|
+
toolbarAlignment="left"
|
|
250
|
+
/>
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
### With Selection Callbacks
|
|
256
|
+
|
|
257
|
+
```tsx
|
|
258
|
+
function SelectionExample() {
|
|
259
|
+
const handleTableSelect = (table) => {
|
|
260
|
+
if (table) {
|
|
261
|
+
console.log('Selected table:', table.name);
|
|
262
|
+
}
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
const handleColumnSelect = (table, columnName) => {
|
|
266
|
+
if (table && columnName) {
|
|
267
|
+
console.log(`Selected column: ${table.name}.${columnName}`);
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
return (
|
|
272
|
+
<ERDViewer
|
|
273
|
+
format="dbml"
|
|
274
|
+
content={schema}
|
|
275
|
+
onTableSelect={handleTableSelect}
|
|
276
|
+
onColumnSelect={handleColumnSelect}
|
|
277
|
+
/>
|
|
278
|
+
);
|
|
279
|
+
}
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
### With Custom Export Watermark
|
|
283
|
+
|
|
284
|
+
```tsx
|
|
285
|
+
function ExportExample() {
|
|
286
|
+
return (
|
|
287
|
+
<ERDViewer
|
|
288
|
+
format="dbml"
|
|
289
|
+
content={schema}
|
|
290
|
+
printExportLogo="https://example.com/my-logo.png"
|
|
291
|
+
printExportLogoPosition="bottom-right"
|
|
292
|
+
onExport={(format) => console.log(`Exported as ${format}`)}
|
|
293
|
+
/>
|
|
294
|
+
);
|
|
295
|
+
}
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
### Developer Mode for Position Capture
|
|
299
|
+
|
|
300
|
+
Enable `devMode` to capture table positions for later use:
|
|
301
|
+
|
|
302
|
+
```tsx
|
|
303
|
+
function DevModeExample() {
|
|
304
|
+
const handlePositionsChange = (positions) => {
|
|
305
|
+
// Save positions to use as the `positions` prop later
|
|
306
|
+
console.log(JSON.stringify(positions, null, 2));
|
|
307
|
+
};
|
|
308
|
+
|
|
309
|
+
return (
|
|
310
|
+
<ERDViewer
|
|
311
|
+
format="dbml"
|
|
312
|
+
content={schema}
|
|
313
|
+
devMode={true}
|
|
314
|
+
draggable={true}
|
|
315
|
+
onPositionsChange={handlePositionsChange}
|
|
316
|
+
/>
|
|
317
|
+
);
|
|
318
|
+
}
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
### Using Pre-defined Positions
|
|
322
|
+
|
|
323
|
+
```tsx
|
|
324
|
+
const savedPositions = {
|
|
325
|
+
schemaFormat: 'dbml',
|
|
326
|
+
positions: [
|
|
327
|
+
{ tableName: 'users', x: 100, y: 100 },
|
|
328
|
+
{ tableName: 'posts', x: 400, y: 100 },
|
|
329
|
+
{ tableName: 'comments', x: 400, y: 300 },
|
|
330
|
+
],
|
|
331
|
+
};
|
|
332
|
+
|
|
333
|
+
function PositionedExample() {
|
|
334
|
+
return (
|
|
335
|
+
<ERDViewer
|
|
336
|
+
format="dbml"
|
|
337
|
+
content={schema}
|
|
338
|
+
positions={savedPositions}
|
|
339
|
+
/>
|
|
340
|
+
);
|
|
341
|
+
}
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
### Dark Theme Example
|
|
345
|
+
|
|
346
|
+
```tsx
|
|
347
|
+
function DarkThemeExample() {
|
|
348
|
+
return (
|
|
349
|
+
<ERDViewer
|
|
350
|
+
format="dbml"
|
|
351
|
+
content={schema}
|
|
352
|
+
theme={{
|
|
353
|
+
'--erd-background': '#1e293b',
|
|
354
|
+
'--erd-surface': '#334155',
|
|
355
|
+
'--erd-border': '#475569',
|
|
356
|
+
'--erd-text': '#f1f5f9',
|
|
357
|
+
'--erd-text-muted': '#94a3b8',
|
|
358
|
+
'--erd-table-header-bg': '#3b82f6',
|
|
359
|
+
'--erd-table-column-bg': '#1e293b',
|
|
360
|
+
'--erd-toolbar-text': '#f1f5f9',
|
|
361
|
+
}}
|
|
362
|
+
/>
|
|
363
|
+
);
|
|
364
|
+
}
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
### Next.js Usage
|
|
368
|
+
|
|
369
|
+
For Next.js applications, use dynamic import with SSR disabled:
|
|
370
|
+
|
|
371
|
+
```tsx
|
|
372
|
+
import dynamic from 'next/dynamic';
|
|
373
|
+
|
|
374
|
+
const ERDViewer = dynamic(
|
|
375
|
+
() => import('@dlh.io/dlh-erd-viewer-deux').then((mod) => mod.ERDViewer),
|
|
376
|
+
{ ssr: false }
|
|
377
|
+
);
|
|
378
|
+
|
|
379
|
+
// Import CSS in your layout or page
|
|
380
|
+
import '@dlh.io/dlh-erd-viewer-deux/styles.css';
|
|
381
|
+
|
|
382
|
+
export default function Page() {
|
|
383
|
+
return (
|
|
384
|
+
<div style={{ width: '100%', height: '100vh' }}>
|
|
385
|
+
<ERDViewer format="dbml" content={schema} />
|
|
386
|
+
</div>
|
|
387
|
+
);
|
|
388
|
+
}
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
## Supported Schema Formats
|
|
392
|
+
|
|
393
|
+
### DBML
|
|
394
|
+
|
|
395
|
+
The component supports [DBML (Database Markup Language)](https://dbml.dbdiagram.io/home/) format:
|
|
396
|
+
|
|
397
|
+
```dbml
|
|
398
|
+
Table users {
|
|
399
|
+
id integer [pk, increment]
|
|
400
|
+
username varchar(255) [not null, unique]
|
|
401
|
+
email varchar(255) [not null]
|
|
402
|
+
created_at timestamp [default: `now()`]
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
Table posts {
|
|
406
|
+
id integer [pk, increment]
|
|
407
|
+
title varchar(255) [not null]
|
|
408
|
+
content text
|
|
409
|
+
author_id integer [ref: > users.id]
|
|
410
|
+
}
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
### TBLS
|
|
414
|
+
|
|
415
|
+
The component also supports [TBLS](https://github.com/k1LoW/tbls) JSON format for schema documentation.
|
|
416
|
+
|
|
417
|
+
## License
|
|
418
|
+
|
|
419
|
+
MIT
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dlh.io/dlh-erd-viewer-deux",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "A React component for viewing database ERD diagrams from DBML and TBLS formats",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
@@ -73,6 +73,6 @@
|
|
|
73
73
|
"license": "MIT",
|
|
74
74
|
"repository": {
|
|
75
75
|
"type": "git",
|
|
76
|
-
"url": "https://github.com/datalakehouse/dlh-erd-viewer-deux.git"
|
|
76
|
+
"url": "git+https://github.com/datalakehouse/dlh-erd-viewer-deux.git"
|
|
77
77
|
}
|
|
78
78
|
}
|