@msdshsk/react-er-canvas 0.0.1 → 0.0.3
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/dist/components/JoinEdge.d.ts +4 -0
- package/dist/components/JoinEdge.d.ts.map +1 -1
- package/dist/components/MermaidER.d.ts +59 -6
- package/dist/components/MermaidER.d.ts.map +1 -1
- package/dist/components/TableNode.d.ts +4 -1
- package/dist/components/TableNode.d.ts.map +1 -1
- package/dist/core/model.d.ts +13 -0
- package/dist/core/model.d.ts.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +249 -157
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -3,6 +3,10 @@ import { JoinType } from '../core/model';
|
|
|
3
3
|
export interface JoinEdgeData extends Record<string, unknown> {
|
|
4
4
|
type: JoinType;
|
|
5
5
|
color: string;
|
|
6
|
+
/** Optional override for the edge stroke width. Defaults to 2 / 2.5 (when emphasized). */
|
|
7
|
+
strokeWidth?: number;
|
|
8
|
+
/** Optional override for the edge dasharray. Defaults to '6 3' (dashed). Pass '' for solid. */
|
|
9
|
+
strokeDasharray?: string;
|
|
6
10
|
hovered?: boolean;
|
|
7
11
|
onDelete?: () => void;
|
|
8
12
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JoinEdge.d.ts","sourceRoot":"","sources":["../../src/components/JoinEdge.tsx"],"names":[],"mappings":"AACA,OAAO,EAIL,KAAK,SAAS,EACf,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C,MAAM,WAAW,YAAa,SAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAC3D,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;CACvB;AAED,eAAO,MAAM,QAAQ,oIAUlB,SAAS,6CAkFV,CAAC"}
|
|
1
|
+
{"version":3,"file":"JoinEdge.d.ts","sourceRoot":"","sources":["../../src/components/JoinEdge.tsx"],"names":[],"mappings":"AACA,OAAO,EAIL,KAAK,SAAS,EACf,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C,MAAM,WAAW,YAAa,SAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAC3D,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,0FAA0F;IAC1F,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+FAA+F;IAC/F,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;CACvB;AAED,eAAO,MAAM,QAAQ,oIAUlB,SAAS,6CAkFV,CAAC"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { CSSProperties } from 'react';
|
|
2
|
+
import { FitViewOptions, Rect, Viewport } from '@xyflow/react';
|
|
2
3
|
import { LayoutAlgorithm, LayoutDirection } from '../core/layout';
|
|
3
4
|
import { ColumnRef, ERModel, Join, PartialColumnRef } from '../core/model';
|
|
4
5
|
export interface NodePosition {
|
|
@@ -6,6 +7,29 @@ export interface NodePosition {
|
|
|
6
7
|
y: number;
|
|
7
8
|
}
|
|
8
9
|
export type NodePositions = Record<string, NodePosition>;
|
|
10
|
+
/**
|
|
11
|
+
* Imperative API exposed via `ref`. Designed to give consumers the primitives
|
|
12
|
+
* needed for image export (fit → snapshot → restore) without baking any
|
|
13
|
+
* specific export library into this package. Methods that change the viewport
|
|
14
|
+
* return Promise<boolean> matching React Flow's underlying API.
|
|
15
|
+
*/
|
|
16
|
+
export interface MermaidERHandle {
|
|
17
|
+
/** Fit all nodes into the visible viewport. */
|
|
18
|
+
fitView: (options?: FitViewOptions) => Promise<boolean>;
|
|
19
|
+
/** Read the current viewport (x, y, zoom) — capture before export to restore later. */
|
|
20
|
+
getViewport: () => Viewport;
|
|
21
|
+
/** Restore (or set) viewport. */
|
|
22
|
+
setViewport: (viewport: Viewport) => Promise<boolean>;
|
|
23
|
+
/** Bounding box of all current nodes. Useful for sizing offscreen canvases. */
|
|
24
|
+
getNodesBounds: () => Rect;
|
|
25
|
+
/** Outer wrapper element (the div that receives `className` / `style`). */
|
|
26
|
+
getWrapperElement: () => HTMLDivElement | null;
|
|
27
|
+
/**
|
|
28
|
+
* The internal `.react-flow__viewport` element. Typical snapshot target
|
|
29
|
+
* when you want to exclude `<Controls>` and `<MiniMap>` from the image.
|
|
30
|
+
*/
|
|
31
|
+
getViewportElement: () => HTMLElement | null;
|
|
32
|
+
}
|
|
9
33
|
export interface MermaidERProps {
|
|
10
34
|
/** Mermaid ER source. Mutually exclusive with `model`. */
|
|
11
35
|
source?: string;
|
|
@@ -30,17 +54,46 @@ export interface MermaidERProps {
|
|
|
30
54
|
* `column` may be undefined when the drag landed on a default (table-center) handle.
|
|
31
55
|
*/
|
|
32
56
|
onJoinConnect?: (source: PartialColumnRef, target: PartialColumnRef) => void;
|
|
33
|
-
/**
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
57
|
+
/**
|
|
58
|
+
* Fired when the user removes a manual join via Delete or the trash icon.
|
|
59
|
+
* `meta` is the opaque value attached to `Join.meta` (if any), provided so
|
|
60
|
+
* the consumer can map the joinId back to its own domain object directly.
|
|
61
|
+
*/
|
|
62
|
+
onJoinDelete?: (joinId: string, meta?: unknown) => void;
|
|
63
|
+
/**
|
|
64
|
+
* Fired when the user clicks an existing manual join edge. Use this to open
|
|
65
|
+
* an in-app edit dialog (change join type / pivot columns) without forcing
|
|
66
|
+
* the user to delete-and-recreate the connection.
|
|
67
|
+
*/
|
|
68
|
+
onJoinClick?: (joinId: string, meta?: unknown) => void;
|
|
69
|
+
/**
|
|
70
|
+
* Per-edge style override for manual joins. Returning `undefined` (or
|
|
71
|
+
* omitting fields) keeps the default style. Useful e.g. to color
|
|
72
|
+
* auto-detected vs user-drawn joins differently.
|
|
73
|
+
*/
|
|
74
|
+
joinStyle?: (join: Join) => {
|
|
75
|
+
stroke?: string;
|
|
76
|
+
strokeWidth?: number;
|
|
77
|
+
strokeDasharray?: string;
|
|
78
|
+
} | undefined;
|
|
79
|
+
/**
|
|
80
|
+
* When provided, a small × appears on each table header to remove it.
|
|
81
|
+
* `meta` mirrors `Table.meta` so the consumer can resolve to its own node id.
|
|
82
|
+
*/
|
|
83
|
+
onTableRemove?: (table: string, meta?: unknown) => void;
|
|
37
84
|
highlightReferencesOnHover?: boolean;
|
|
38
85
|
onColumnClick?: (table: string, column: string) => void;
|
|
39
|
-
onTableClick?: (table: string) => void;
|
|
86
|
+
onTableClick?: (table: string, meta?: unknown) => void;
|
|
87
|
+
/**
|
|
88
|
+
* When `showColumnCheckboxes` is enabled, also render a per-table
|
|
89
|
+
* select-all checkbox in the header (with indeterminate state for partial
|
|
90
|
+
* selection). Toggles all of that table's columns at once.
|
|
91
|
+
*/
|
|
92
|
+
showSelectAllPerTable?: boolean;
|
|
40
93
|
/** Override the default delete-key code(s). Default is 'Delete' (Backspace ignored to prevent accidents). */
|
|
41
94
|
deleteKeyCode?: string | string[] | null;
|
|
42
95
|
className?: string;
|
|
43
96
|
style?: CSSProperties;
|
|
44
97
|
}
|
|
45
|
-
export declare
|
|
98
|
+
export declare const MermaidER: import('react').ForwardRefExoticComponent<MermaidERProps & import('react').RefAttributes<MermaidERHandle>>;
|
|
46
99
|
//# sourceMappingURL=MermaidER.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MermaidER.d.ts","sourceRoot":"","sources":["../../src/components/MermaidER.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"MermaidER.d.ts","sourceRoot":"","sources":["../../src/components/MermaidER.tsx"],"names":[],"mappings":"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"}
|
|
@@ -11,16 +11,19 @@ export interface TableNodeData extends Record<string, unknown> {
|
|
|
11
11
|
export declare const HighlightContext: import('react').Context<ReadonlyMap<string, ReadonlySet<string>>>;
|
|
12
12
|
export interface ColumnSelectionContextValue {
|
|
13
13
|
enabled: boolean;
|
|
14
|
+
/** When true, render a per-table select-all checkbox in each header. */
|
|
15
|
+
showSelectAll: boolean;
|
|
14
16
|
/** "table.column" keys for fast lookup. */
|
|
15
17
|
selected: ReadonlySet<string>;
|
|
16
18
|
onToggle: (table: string, column: string, checked: boolean) => void;
|
|
19
|
+
onToggleAll: (table: string, columns: string[], nextState: boolean) => void;
|
|
17
20
|
}
|
|
18
21
|
export declare const ColumnSelectionContext: import('react').Context<ColumnSelectionContextValue>;
|
|
19
22
|
/** When true, column handles become visible/connectable for manual JOIN drawing. */
|
|
20
23
|
export declare const ConnectModeContext: import('react').Context<boolean>;
|
|
21
24
|
export interface TableActionsContextValue {
|
|
22
25
|
/** When provided, a delete affordance is shown on the table header. */
|
|
23
|
-
onTableRemove?: (table: string) => void;
|
|
26
|
+
onTableRemove?: (table: string, meta?: unknown) => void;
|
|
24
27
|
/** Per-column click handler. Provided via context (not node data) so its
|
|
25
28
|
* identity can change without invalidating the React Flow node array. */
|
|
26
29
|
onColumnClick?: (table: string, column: string) => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TableNode.d.ts","sourceRoot":"","sources":["../../src/components/TableNode.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,KAAK,EAAU,KAAK,EAAE,MAAM,eAAe,CAAC;AAGnD,MAAM,WAAW,aAAc,SAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAC5D,KAAK,EAAE,KAAK,CAAC;CACd;AAED;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,mEAAqE,CAAC;AAEnG,MAAM,WAAW,2BAA2B;IAC1C,OAAO,EAAE,OAAO,CAAC;IACjB,2CAA2C;IAC3C,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC9B,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"TableNode.d.ts","sourceRoot":"","sources":["../../src/components/TableNode.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,KAAK,EAAU,KAAK,EAAE,MAAM,eAAe,CAAC;AAGnD,MAAM,WAAW,aAAc,SAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAC5D,KAAK,EAAE,KAAK,CAAC;CACd;AAED;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,mEAAqE,CAAC;AAEnG,MAAM,WAAW,2BAA2B;IAC1C,OAAO,EAAE,OAAO,CAAC;IACjB,wEAAwE;IACxE,aAAa,EAAE,OAAO,CAAC;IACvB,2CAA2C;IAC3C,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC9B,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACpE,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,OAAO,KAAK,IAAI,CAAC;CAC7E;AAED,eAAO,MAAM,sBAAsB,sDAMjC,CAAC;AAEH,oFAAoF;AACpF,eAAO,MAAM,kBAAkB,kCAAgC,CAAC;AAEhE,MAAM,WAAW,wBAAwB;IACvC,uEAAuE;IACvE,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IACxD;8EAC0E;IAC1E,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CACzD;AAED,eAAO,MAAM,mBAAmB,mDAA8C,CAAC;AA+G/E,eAAO,MAAM,SAAS,iDAAqC,SAAS,6CA6NlE,CAAC"}
|
package/dist/core/model.d.ts
CHANGED
|
@@ -14,6 +14,13 @@ export interface Table {
|
|
|
14
14
|
name: string;
|
|
15
15
|
columns: Column[];
|
|
16
16
|
group?: string;
|
|
17
|
+
/**
|
|
18
|
+
* Opaque consumer-defined data. The library never reads this — it is only
|
|
19
|
+
* passed back through callbacks (e.g. `onTableRemove(name, meta)`) so the
|
|
20
|
+
* consumer can map a table back to its own domain entity (kind: 'view',
|
|
21
|
+
* pseudo-id, alias info, etc.) without a name-based scan.
|
|
22
|
+
*/
|
|
23
|
+
meta?: unknown;
|
|
17
24
|
}
|
|
18
25
|
export interface Relation {
|
|
19
26
|
id: string;
|
|
@@ -51,5 +58,11 @@ export interface Join {
|
|
|
51
58
|
source: ColumnRef;
|
|
52
59
|
target: ColumnRef;
|
|
53
60
|
type: JoinType;
|
|
61
|
+
/**
|
|
62
|
+
* Opaque consumer-defined data. Same role as `Table.meta` — passed back
|
|
63
|
+
* through `onJoinClick` / `onJoinDelete` so consumer can carry origin info
|
|
64
|
+
* (e.g. 'auto' vs 'manual'), styling hints, etc.
|
|
65
|
+
*/
|
|
66
|
+
meta?: unknown;
|
|
54
67
|
}
|
|
55
68
|
//# sourceMappingURL=model.d.ts.map
|
package/dist/core/model.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../src/core/model.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GACnB,KAAK,GACL,aAAa,GACb,aAAa,GACb,cAAc,CAAC;AAEnB,MAAM,WAAW,SAAS;IACxB,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,EAAE,CAAC,EAAE,OAAO,CAAC;CACd;AAED,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,SAAS,CAAC;CACjB;AAED,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,eAAe,EAAE,WAAW,CAAC;IAC7B,aAAa,EAAE,WAAW,CAAC;IAC3B,WAAW,EAAE,OAAO,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0EAA0E;IAC1E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,wEAAwE;IACxE,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,OAAO;IACtB,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,MAAM,EAAE,KAAK,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC;AAErE,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,SAAS,CAAC;IAClB,MAAM,EAAE,SAAS,CAAC;IAClB,IAAI,EAAE,QAAQ,CAAC;CAChB"}
|
|
1
|
+
{"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../src/core/model.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GACnB,KAAK,GACL,aAAa,GACb,aAAa,GACb,cAAc,CAAC;AAEnB,MAAM,WAAW,SAAS;IACxB,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,EAAE,CAAC,EAAE,OAAO,CAAC;CACd;AAED,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,SAAS,CAAC;CACjB;AAED,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;OAKG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,eAAe,EAAE,WAAW,CAAC;IAC7B,aAAa,EAAE,WAAW,CAAC;IAC3B,WAAW,EAAE,OAAO,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0EAA0E;IAC1E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,wEAAwE;IACxE,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,OAAO;IACtB,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,MAAM,EAAE,KAAK,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC;AAErE,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,SAAS,CAAC;IAClB,MAAM,EAAE,SAAS,CAAC;IAClB,IAAI,EAAE,QAAQ,CAAC;IACf;;;;OAIG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB"}
|
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./core-BtdV83x9.cjs`);let t=require(`react`),n=require(`@xyflow/react`),r=require(`react/jsx-runtime`);var i=(0,t.createContext)(new Map),a=(0,t.createContext)({enabled:!1,selected:new Set,onToggle:()=>void 0}),o=(0,t.createContext)(!1),s=(0,t.createContext)({}),c={pk:{label:`PK`,bg:`#f59e0b`},fk:{label:`FK`,bg:`#3b82f6`},uk:{label:`UK`,bg:`#10b981`}};function l({tableName:e,column:t,highlighted:n,onClick:i,selectionEnabled:a,selected:o,onSelectToggle:s}){let l=[];return t.keys.pk&&l.push(c.pk),t.keys.fk&&l.push(c.fk),t.keys.uk&&l.push(c.uk),(0,r.jsxs)(`div`,{title:t.comment,onClick:i?()=>i(e,t.name):void 0,style:{display:`flex`,alignItems:`center`,gap:6,padding:`0 10px`,fontSize:12,fontFamily:`ui-monospace, SFMono-Regular, Consolas, monospace`,borderTop:`1px solid #eee`,height:22,boxSizing:`border-box`,cursor:i?`pointer`:`default`,background:n?`#fef3c7`:o?`#eff6ff`:`transparent`,transition:`background 0.15s`},children:[a&&(0,r.jsx)(`input`,{type:`checkbox`,checked:o,onChange:e=>s(e.target.checked),onClick:e=>e.stopPropagation(),style:{width:13,height:13,margin:0,flexShrink:0,cursor:`pointer`}}),(0,r.jsx)(`span`,{style:{display:`flex`,gap:2,flexShrink:0,minWidth:18},children:l.map(e=>(0,r.jsx)(`span`,{style:{display:`inline-block`,padding:`0 4px`,borderRadius:3,background:e.bg,color:`#fff`,fontSize:9,fontWeight:700,lineHeight:`14px`},children:e.label},e.label))}),(0,r.jsx)(`span`,{style:{flexShrink:0,fontWeight:t.keys.pk?600:400,color:`#1f2937`},children:t.name}),t.type&&(0,r.jsx)(`span`,{style:{flex:1,textAlign:`right`,color:`#9ca3af`,fontStyle:`italic`,overflow:`hidden`,textOverflow:`ellipsis`,whiteSpace:`nowrap`},children:t.type})]})}var u=(0,t.memo)(function({data:e}){let{table:c}=e,u=(0,t.useContext)(i),d=(0,t.useContext)(a),f=(0,t.useContext)(o),p=(0,t.useContext)(s),m=p.onColumnClick,h=u.get(c.name),g=c.group?`#1e40af`:`#374151`,_=e=>({...e,width:f?9:6,height:f?9:6,background:f?`#3b82f6`:`transparent`,border:f?`1.5px solid #fff`:`none`,boxShadow:f?`0 0 0 1px rgba(59,130,246,0.4)`:`none`,opacity:f?.85:0,pointerEvents:f?`auto`:`none`,cursor:f?`crosshair`:`default`});return(0,r.jsxs)(`div`,{style:{background:`#fff`,border:`1px solid #c4c4c4`,borderRadius:6,boxShadow:`0 2px 6px rgba(0,0,0,0.08)`,overflow:`visible`,width:`100%`,height:`100%`,display:`flex`,flexDirection:`column`,position:`relative`},children:[(0,r.jsx)(n.Handle,{id:`__default-target`,type:`target`,position:n.Position.Left,style:_({top:32/2})}),(0,r.jsx)(n.Handle,{id:`__default-source`,type:`source`,position:n.Position.Right,style:_({top:32/2})}),(0,r.jsxs)(`div`,{style:{padding:`6px 10px`,background:g,color:`#fff`,fontWeight:600,fontSize:13,height:32,boxSizing:`border-box`,display:`flex`,alignItems:`center`,justifyContent:`space-between`,gap:8,borderTopLeftRadius:6,borderTopRightRadius:6},children:[(0,r.jsx)(`span`,{style:{overflow:`hidden`,textOverflow:`ellipsis`,whiteSpace:`nowrap`},children:c.name}),(0,r.jsxs)(`span`,{style:{display:`flex`,alignItems:`center`,gap:4,flexShrink:0},children:[c.group&&(0,r.jsx)(`span`,{style:{fontSize:10,opacity:.75,fontWeight:400,padding:`1px 5px`,border:`1px solid rgba(255,255,255,0.3)`,borderRadius:3},children:c.group}),p.onTableRemove&&(0,r.jsx)(`button`,{className:`nodrag`,onClick:e=>{e.stopPropagation(),p.onTableRemove?.(c.name)},onMouseDown:e=>e.stopPropagation(),title:`Remove this table`,style:{background:`rgba(255,255,255,0.18)`,border:`none`,color:`#fff`,width:18,height:18,borderRadius:3,cursor:`pointer`,fontSize:13,fontWeight:700,padding:0,lineHeight:1,display:`flex`,alignItems:`center`,justifyContent:`center`},children:`×`})]})]}),c.columns.map((e,i)=>{let a=32+i*22+22/2,o=h?.has(e.name)??!1,s=`${c.name}.${e.name}`,u=d.enabled&&d.selected.has(s);return(0,r.jsxs)(t.Fragment,{children:[(0,r.jsx)(n.Handle,{id:`${e.name}__target`,type:`target`,position:n.Position.Left,style:_({top:a})}),(0,r.jsx)(n.Handle,{id:`${e.name}__source`,type:`source`,position:n.Position.Right,style:_({top:a})}),(0,r.jsx)(l,{tableName:c.name,column:e,highlighted:o,onClick:m,selectionEnabled:d.enabled,selected:u,onSelectToggle:t=>d.onToggle(c.name,e.name,t)})]},`${e.name}-${i}`)})]})}),d=(0,t.memo)(function({id:e,sourceX:t,sourceY:i,targetX:a,targetY:o,sourcePosition:s,targetPosition:c,data:l,selected:u}){let[d,f,p]=(0,n.getSmoothStepPath)({sourceX:t,sourceY:i,sourcePosition:s,targetX:a,targetY:o,targetPosition:c}),m=l??{},h=!!u||!!m.hovered,g=m.color||`#3b82f6`;return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.BaseEdge,{id:e,path:d,style:{stroke:g,strokeWidth:h?2.5:2,strokeDasharray:`6 3`}}),(0,r.jsx)(n.EdgeLabelRenderer,{children:(0,r.jsxs)(`div`,{className:`nodrag nopan`,style:{position:`absolute`,transform:`translate(-50%, -50%) translate(${f}px, ${p}px)`,background:g,color:`#fff`,fontSize:10,fontFamily:`ui-monospace, SFMono-Regular, Consolas, monospace`,fontWeight:700,borderRadius:3,padding:`2px 4px 2px 6px`,display:`flex`,alignItems:`center`,gap:4,pointerEvents:`all`,boxShadow:h?`0 0 0 2px rgba(0,0,0,0.4)`:`0 1px 2px rgba(0,0,0,0.15)`,userSelect:`none`},children:[(0,r.jsx)(`span`,{children:m.type}),m.onDelete&&(0,r.jsx)(`button`,{type:`button`,onClick:e=>{e.stopPropagation(),m.onDelete?.()},onMouseDown:e=>e.stopPropagation(),title:`Remove this JOIN`,style:{background:`rgba(255,255,255,0.25)`,border:`none`,color:`#fff`,width:14,height:14,borderRadius:2,cursor:`pointer`,fontSize:11,fontWeight:700,padding:0,lineHeight:1,display:`flex`,alignItems:`center`,justifyContent:`center`},children:`×`})]})})]})}),f={table:u},p={joinEdge:d};function m(t){try{return{model:e.c(t),error:null}}catch(t){if(t instanceof e.s)return{model:null,error:t};throw t}}function h(e,t){return t?`${t}__${e}`:`__default-${e}`}var g=`join:`;function _(e){if(!e||e.startsWith(`__default-`))return;let t=/^(.+)__(?:source|target)$/.exec(e);return t?t[1]:void 0}function ee(e){return`${e.table}.${e.column}`}var v={INNER:`#3b82f6`,LEFT:`#8b5cf6`,RIGHT:`#a855f7`,FULL:`#ec4899`,CROSS:`#6b7280`};function y(c){let{source:l,model:u,algorithm:d,direction:y,aspectRatio:b,positions:x,onPositionsChange:S,showColumnCheckboxes:C,selectedColumns:w,onColumnSelectionChange:T,enableManualJoins:E,joins:D,onJoinConnect:O,onJoinDelete:k,onTableRemove:A,onColumnClick:j,onTableClick:M,deleteKeyCode:N=`Delete`,className:P,style:F,highlightReferencesOnHover:I=!0}=c,{model:L,error:R}=(0,t.useMemo)(()=>u?{model:u,error:null}:l==null?{model:null,error:null}:m(l),[l,u]),[z,B]=(0,t.useState)(null),[V,H]=(0,t.useState)(null);(0,t.useEffect)(()=>{if(!L){B(null);return}let t=!1;return e.o(L,{algorithm:d,direction:y,aspectRatio:b}).then(e=>{t||B(e)}),()=>{t=!0}},[L,d,y,b]);let U=(0,t.useMemo)(()=>{if(!z||!L)return[];let e=new Map(L.tables.map(e=>[e.name,e])),t=[];for(let n of z.nodes){let r=e.get(n.id);if(!r)continue;let i=x?.[n.id],a={table:r};t.push({id:n.id,type:`table`,position:i??{x:n.x,y:n.y},data:a,width:n.width,height:n.height,draggable:!0,deletable:!1})}return t},[z,L,x]),[W,G,K]=(0,n.useNodesState)(U);(0,t.useEffect)(()=>{G(U)},[U,G]);let q=(0,t.useCallback)((e,t,n)=>{if(!S)return;let r={...x??{}};for(let e of n)r[e.id]={x:e.position.x,y:e.position.y};S(r)},[x,S]),J=(0,t.useMemo)(()=>{if(!(!V||!L))return L.relations.find(e=>e.id===V)},[V,L]),Y=(0,t.useMemo)(()=>{if(!V||!D||!V.startsWith(g))return;let e=V.slice(5);return D.find(t=>t.id===e)},[V,D]),X=(0,t.useMemo)(()=>{let e=new Map;if(!I)return e;let t=(t,n)=>{if(!n)return;let r=e.get(t)??new Set;r.add(n),e.set(t,r)};return J&&(t(J.from,J.fromColumn),t(J.to,J.toColumn)),Y&&(t(Y.source.table,Y.source.column),t(Y.target.table,Y.target.column)),e},[J,Y,I]),Z=(0,t.useMemo)(()=>new Set((w??[]).map(ee)),[w]),Q=(0,t.useCallback)((e,t,n)=>{if(!T)return;let r=w??[];if(n){if(r.some(n=>n.table===e&&n.column===t))return;T([...r,{table:e,column:t}])}else T(r.filter(n=>!(n.table===e&&n.column===t)))},[w,T]),te=(0,t.useMemo)(()=>({enabled:C??!1,selected:Z,onToggle:Q}),[C,Z,Q]),ne=(0,t.useMemo)(()=>{if(!z||!L)return[];let e=new Set(L.tables.map(e=>e.name)),t=new Map(L.relations.map(e=>[e.id,e])),n=[];for(let r of z.edges){if(!e.has(r.source)||!e.has(r.target))continue;let i=t.get(r.id),a=r.id===V;n.push({id:r.id,source:r.source,target:r.target,sourceHandle:h(`source`,i?.fromColumn),targetHandle:h(`target`,i?.toColumn),type:`smoothstep`,animated:a,deletable:!1,style:{stroke:a?`#f59e0b`:`#9ca3af`,strokeWidth:a?2:1.5},label:i?.label,labelStyle:{fontSize:10,fill:`#6b7280`},labelBgStyle:{fill:`#fff`,fillOpacity:.85},labelBgPadding:[4,2],labelBgBorderRadius:3})}let r=[];for(let t of D??[]){if(!e.has(t.source.table)||!e.has(t.target.table))continue;let n=`${g}${t.id}`,i=n===V,a=v[t.type]??`#3b82f6`,o={type:t.type,color:a,hovered:i,onDelete:k?()=>k(t.id):void 0};r.push({id:n,source:t.source.table,target:t.target.table,sourceHandle:h(`source`,t.source.column),targetHandle:h(`target`,t.target.column),type:`joinEdge`,deletable:!0,data:o})}return[...n,...r]},[z,L,D,V,k]),re=(0,t.useCallback)(e=>{O&&(!e.source||!e.target||O({table:e.source,column:_(e.sourceHandle)},{table:e.target,column:_(e.targetHandle)}))},[O]),ie=(0,t.useCallback)(e=>{if(k)for(let t of e)t.id.startsWith(g)&&k(t.id.slice(5))},[k]),$=!!E,ae=(0,t.useMemo)(()=>({onTableRemove:A,onColumnClick:j}),[A,j]);return(0,r.jsxs)(`div`,{className:P,style:{width:`100%`,height:`100%`,position:`relative`,...F},children:[R&&(0,r.jsx)(`div`,{style:{position:`absolute`,top:8,left:8,right:8,zIndex:10,padding:`8px 12px`,background:`#fef2f2`,border:`1px solid #fecaca`,borderRadius:6,color:`#991b1b`,fontFamily:`ui-monospace, SFMono-Regular, Consolas, monospace`,fontSize:12,whiteSpace:`pre-wrap`},children:R.message}),!R&&!z&&(0,r.jsx)(`div`,{style:{position:`absolute`,inset:0,display:`flex`,alignItems:`center`,justifyContent:`center`,color:`#9ca3af`,fontSize:13},children:`Computing layout…`}),(0,r.jsx)(i.Provider,{value:X,children:(0,r.jsx)(a.Provider,{value:te,children:(0,r.jsx)(o.Provider,{value:$,children:(0,r.jsx)(s.Provider,{value:ae,children:(0,r.jsxs)(n.ReactFlow,{nodes:W,edges:ne,nodeTypes:f,edgeTypes:p,fitView:!0,onNodesChange:K,onNodeDragStop:q,onNodeClick:M?(e,t)=>M(t.id):void 0,onEdgeMouseEnter:(e,t)=>H(t.id),onEdgeMouseLeave:()=>H(null),onConnect:re,onEdgesDelete:ie,nodesDraggable:!0,nodesConnectable:$,elementsSelectable:!0,deleteKeyCode:N,minZoom:.1,maxZoom:4,children:[(0,r.jsx)(n.Background,{}),(0,r.jsx)(n.Controls,{}),(0,r.jsx)(n.MiniMap,{pannable:!0,zoomable:!0})]})})})})})]})}exports.HEADER_HEIGHT=e.t,exports.MermaidER=y,exports.MermaidERParseError=e.s,exports.NODE_WIDTH=e.n,exports.ROW_HEIGHT=e.r,exports.VERTICAL_PADDING=e.i,exports.estimateNodeHeight=e.a,exports.layoutER=e.o,exports.parseMermaidER=e.c;
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./core-BtdV83x9.cjs`);let t=require(`react`),n=require(`@xyflow/react`),r=require(`react/jsx-runtime`);var i=(0,t.createContext)(new Map),a=(0,t.createContext)({enabled:!1,showSelectAll:!1,selected:new Set,onToggle:()=>void 0,onToggleAll:()=>void 0}),o=(0,t.createContext)(!1),s=(0,t.createContext)({}),c={pk:{label:`PK`,bg:`#f59e0b`},fk:{label:`FK`,bg:`#3b82f6`},uk:{label:`UK`,bg:`#10b981`}};function l({tableName:e,column:t,highlighted:n,onClick:i,selectionEnabled:a,selected:o,onSelectToggle:s}){let l=[];return t.keys.pk&&l.push(c.pk),t.keys.fk&&l.push(c.fk),t.keys.uk&&l.push(c.uk),(0,r.jsxs)(`div`,{title:t.comment,onClick:i?()=>i(e,t.name):void 0,style:{display:`flex`,alignItems:`center`,gap:6,padding:`0 10px`,fontSize:12,fontFamily:`ui-monospace, SFMono-Regular, Consolas, monospace`,borderTop:`1px solid #eee`,height:22,boxSizing:`border-box`,cursor:i?`pointer`:`default`,background:n?`#fef3c7`:o?`#eff6ff`:`transparent`,transition:`background 0.15s`},children:[a&&(0,r.jsx)(`input`,{type:`checkbox`,checked:o,onChange:e=>s(e.target.checked),onClick:e=>e.stopPropagation(),style:{width:13,height:13,margin:0,flexShrink:0,cursor:`pointer`}}),(0,r.jsx)(`span`,{style:{display:`flex`,gap:2,flexShrink:0,minWidth:18},children:l.map(e=>(0,r.jsx)(`span`,{style:{display:`inline-block`,padding:`0 4px`,borderRadius:3,background:e.bg,color:`#fff`,fontSize:9,fontWeight:700,lineHeight:`14px`},children:e.label},e.label))}),(0,r.jsx)(`span`,{style:{flexShrink:0,fontWeight:t.keys.pk?600:400,color:`#1f2937`},children:t.name}),t.type&&(0,r.jsx)(`span`,{style:{flex:1,textAlign:`right`,color:`#9ca3af`,fontStyle:`italic`,overflow:`hidden`,textOverflow:`ellipsis`,whiteSpace:`nowrap`},children:t.type})]})}var u=(0,t.memo)(function({data:e}){let{table:c}=e,u=(0,t.useContext)(i),d=(0,t.useContext)(a),f=(0,t.useContext)(o),p=(0,t.useContext)(s),m=p.onColumnClick,h=u.get(c.name),g=c.group?`#1e40af`:`#374151`,_=d.enabled&&d.showSelectAll&&c.columns.length>0,v=(0,t.useMemo)(()=>c.columns.map(e=>e.name),[c.columns]),y=(0,t.useMemo)(()=>{if(!_)return 0;let e=0;for(let t of v)d.selected.has(`${c.name}.${t}`)&&e++;return e},[_,v,d.selected,c.name]),b=_&&y===v.length,x=_&&y>0&&y<v.length,S=(0,t.useRef)(null);(0,t.useEffect)(()=>{S.current&&(S.current.indeterminate=x)},[x]);let C=e=>({...e,width:f?9:6,height:f?9:6,background:f?`#3b82f6`:`transparent`,border:f?`1.5px solid #fff`:`none`,boxShadow:f?`0 0 0 1px rgba(59,130,246,0.4)`:`none`,opacity:f?.85:0,pointerEvents:f?`auto`:`none`,cursor:f?`crosshair`:`default`});return(0,r.jsxs)(`div`,{style:{background:`#fff`,border:`1px solid #c4c4c4`,borderRadius:6,boxShadow:`0 2px 6px rgba(0,0,0,0.08)`,overflow:`visible`,width:`100%`,height:`100%`,display:`flex`,flexDirection:`column`,position:`relative`},children:[(0,r.jsx)(n.Handle,{id:`__default-target`,type:`target`,position:n.Position.Left,style:C({top:32/2})}),(0,r.jsx)(n.Handle,{id:`__default-source`,type:`source`,position:n.Position.Right,style:C({top:32/2})}),(0,r.jsxs)(`div`,{style:{padding:`6px 10px`,background:g,color:`#fff`,fontWeight:600,fontSize:13,height:32,boxSizing:`border-box`,display:`flex`,alignItems:`center`,justifyContent:`space-between`,gap:8,borderTopLeftRadius:6,borderTopRightRadius:6},children:[(0,r.jsxs)(`span`,{style:{display:`flex`,alignItems:`center`,gap:6,overflow:`hidden`,minWidth:0},children:[_&&(0,r.jsx)(`input`,{ref:S,type:`checkbox`,className:`nodrag`,checked:b,onChange:e=>d.onToggleAll(c.name,v,e.target.checked),onClick:e=>e.stopPropagation(),onMouseDown:e=>e.stopPropagation(),title:b?`Deselect all columns`:x?`Some columns selected — click to select all`:`Select all columns`,style:{width:13,height:13,margin:0,flexShrink:0,cursor:`pointer`,accentColor:`#3b82f6`}}),(0,r.jsx)(`span`,{style:{overflow:`hidden`,textOverflow:`ellipsis`,whiteSpace:`nowrap`},children:c.name})]}),(0,r.jsxs)(`span`,{style:{display:`flex`,alignItems:`center`,gap:4,flexShrink:0},children:[c.group&&(0,r.jsx)(`span`,{style:{fontSize:10,opacity:.75,fontWeight:400,padding:`1px 5px`,border:`1px solid rgba(255,255,255,0.3)`,borderRadius:3},children:c.group}),p.onTableRemove&&(0,r.jsx)(`button`,{className:`nodrag`,onClick:e=>{e.stopPropagation(),p.onTableRemove?.(c.name,c.meta)},onMouseDown:e=>e.stopPropagation(),title:`Remove this table`,style:{background:`rgba(255,255,255,0.18)`,border:`none`,color:`#fff`,width:18,height:18,borderRadius:3,cursor:`pointer`,fontSize:13,fontWeight:700,padding:0,lineHeight:1,display:`flex`,alignItems:`center`,justifyContent:`center`},children:`×`})]})]}),c.columns.map((e,i)=>{let a=32+i*22+22/2,o=h?.has(e.name)??!1,s=`${c.name}.${e.name}`,u=d.enabled&&d.selected.has(s);return(0,r.jsxs)(t.Fragment,{children:[(0,r.jsx)(n.Handle,{id:`${e.name}__target`,type:`target`,position:n.Position.Left,style:C({top:a})}),(0,r.jsx)(n.Handle,{id:`${e.name}__source`,type:`source`,position:n.Position.Right,style:C({top:a})}),(0,r.jsx)(l,{tableName:c.name,column:e,highlighted:o,onClick:m,selectionEnabled:d.enabled,selected:u,onSelectToggle:t=>d.onToggle(c.name,e.name,t)})]},`${e.name}-${i}`)})]})}),d=(0,t.memo)(function({id:e,sourceX:t,sourceY:i,targetX:a,targetY:o,sourcePosition:s,targetPosition:c,data:l,selected:u}){let[d,f,p]=(0,n.getSmoothStepPath)({sourceX:t,sourceY:i,sourcePosition:s,targetX:a,targetY:o,targetPosition:c}),m=l??{},h=!!u||!!m.hovered,g=m.color||`#3b82f6`;return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.BaseEdge,{id:e,path:d,style:{stroke:g,strokeWidth:m.strokeWidth??(h?2.5:2),strokeDasharray:m.strokeDasharray??`6 3`}}),(0,r.jsx)(n.EdgeLabelRenderer,{children:(0,r.jsxs)(`div`,{className:`nodrag nopan`,style:{position:`absolute`,transform:`translate(-50%, -50%) translate(${f}px, ${p}px)`,background:g,color:`#fff`,fontSize:10,fontFamily:`ui-monospace, SFMono-Regular, Consolas, monospace`,fontWeight:700,borderRadius:3,padding:`2px 4px 2px 6px`,display:`flex`,alignItems:`center`,gap:4,pointerEvents:`all`,boxShadow:h?`0 0 0 2px rgba(0,0,0,0.4)`:`0 1px 2px rgba(0,0,0,0.15)`,userSelect:`none`},children:[(0,r.jsx)(`span`,{children:m.type}),m.onDelete&&(0,r.jsx)(`button`,{type:`button`,onClick:e=>{e.stopPropagation(),m.onDelete?.()},onMouseDown:e=>e.stopPropagation(),title:`Remove this JOIN`,style:{background:`rgba(255,255,255,0.25)`,border:`none`,color:`#fff`,width:14,height:14,borderRadius:2,cursor:`pointer`,fontSize:11,fontWeight:700,padding:0,lineHeight:1,display:`flex`,alignItems:`center`,justifyContent:`center`},children:`×`})]})})]})}),f={table:u},p={joinEdge:d};function m(t){try{return{model:e.c(t),error:null}}catch(t){if(t instanceof e.s)return{model:null,error:t};throw t}}function h(e,t){return t?`${t}__${e}`:`__default-${e}`}var g=`join:`;function _(e){if(!e||e.startsWith(`__default-`))return;let t=/^(.+)__(?:source|target)$/.exec(e);return t?t[1]:void 0}function v(e){return`${e.table}.${e.column}`}var y={INNER:`#3b82f6`,LEFT:`#8b5cf6`,RIGHT:`#a855f7`,FULL:`#ec4899`,CROSS:`#6b7280`};function b({apiRef:e,wrapperRef:r}){let i=(0,n.useReactFlow)();return(0,t.useImperativeHandle)(e,()=>({fitView:e=>i.fitView(e),getViewport:()=>i.getViewport(),setViewport:e=>i.setViewport(e),getNodesBounds:()=>i.getNodesBounds(i.getNodes()),getWrapperElement:()=>r.current,getViewportElement:()=>r.current?.querySelector(`.react-flow__viewport`)??null}),[i,r]),null}var x=(0,t.forwardRef)(function(c,l){let{source:u,model:d,algorithm:x,direction:S,aspectRatio:C,positions:w,onPositionsChange:T,showColumnCheckboxes:E,selectedColumns:D,onColumnSelectionChange:O,enableManualJoins:ee,joins:k,onJoinConnect:A,onJoinDelete:j,onJoinClick:M,joinStyle:N,onTableRemove:P,onColumnClick:F,onTableClick:I,showSelectAllPerTable:L,deleteKeyCode:te=`Delete`,className:ne,style:re,highlightReferencesOnHover:R=!0}=c,{model:z,error:B}=(0,t.useMemo)(()=>d?{model:d,error:null}:u==null?{model:null,error:null}:m(u),[u,d]),[V,H]=(0,t.useState)(null),[U,W]=(0,t.useState)(null);(0,t.useEffect)(()=>{if(!z){H(null);return}let t=!1;return e.o(z,{algorithm:x,direction:S,aspectRatio:C}).then(e=>{t||H(e)}),()=>{t=!0}},[z,x,S,C]);let G=(0,t.useMemo)(()=>{if(!V||!z)return[];let e=new Map(z.tables.map(e=>[e.name,e])),t=[];for(let n of V.nodes){let r=e.get(n.id);if(!r)continue;let i=w?.[n.id],a={table:r};t.push({id:n.id,type:`table`,position:i??{x:n.x,y:n.y},data:a,width:n.width,height:n.height,draggable:!0,deletable:!1})}return t},[V,z,w]),[ie,K,ae]=(0,n.useNodesState)(G);(0,t.useEffect)(()=>{K(G)},[G,K]);let oe=(0,t.useCallback)((e,t,n)=>{if(!T)return;let r={...w??{}};for(let e of n)r[e.id]={x:e.position.x,y:e.position.y};T(r)},[w,T]),q=(0,t.useMemo)(()=>{if(!(!U||!z))return z.relations.find(e=>e.id===U)},[U,z]),J=(0,t.useMemo)(()=>{if(!U||!k||!U.startsWith(g))return;let e=U.slice(5);return k.find(t=>t.id===e)},[U,k]),se=(0,t.useMemo)(()=>{let e=new Map;if(!R)return e;let t=(t,n)=>{if(!n)return;let r=e.get(t)??new Set;r.add(n),e.set(t,r)};return q&&(t(q.from,q.fromColumn),t(q.to,q.toColumn)),J&&(t(J.source.table,J.source.column),t(J.target.table,J.target.column)),e},[q,J,R]),Y=(0,t.useMemo)(()=>new Set((D??[]).map(v)),[D]),X=(0,t.useCallback)((e,t,n)=>{if(!O)return;let r=D??[];if(n){if(r.some(n=>n.table===e&&n.column===t))return;O([...r,{table:e,column:t}])}else O(r.filter(n=>!(n.table===e&&n.column===t)))},[D,O]),Z=(0,t.useCallback)((e,t,n)=>{if(!O)return;let r=D??[];if(n){let n=new Set(r.map(v)),i=[];for(let r of t)n.has(`${e}.${r}`)||i.push({table:e,column:r});if(i.length===0)return;O([...r,...i])}else{let n=new Set(t);O(r.filter(t=>!(t.table===e&&n.has(t.column))))}},[D,O]),ce=(0,t.useMemo)(()=>({enabled:E??!1,showSelectAll:L??!1,selected:Y,onToggle:X,onToggleAll:Z}),[E,L,Y,X,Z]),le=(0,t.useMemo)(()=>{if(!V||!z)return[];let e=new Set(z.tables.map(e=>e.name)),t=new Map(z.relations.map(e=>[e.id,e])),n=[];for(let r of V.edges){if(!e.has(r.source)||!e.has(r.target))continue;let i=t.get(r.id),a=r.id===U;n.push({id:r.id,source:r.source,target:r.target,sourceHandle:h(`source`,i?.fromColumn),targetHandle:h(`target`,i?.toColumn),type:`smoothstep`,animated:a,deletable:!1,style:{stroke:a?`#f59e0b`:`#9ca3af`,strokeWidth:a?2:1.5},label:i?.label,labelStyle:{fontSize:10,fill:`#6b7280`},labelBgStyle:{fill:`#fff`,fillOpacity:.85},labelBgPadding:[4,2],labelBgBorderRadius:3})}let r=[];for(let t of k??[]){if(!e.has(t.source.table)||!e.has(t.target.table))continue;let n=`${g}${t.id}`,i=n===U,a=N?.(t),o=a?.stroke??y[t.type]??`#3b82f6`,s={type:t.type,color:o,strokeWidth:a?.strokeWidth,strokeDasharray:a?.strokeDasharray,hovered:i,onDelete:j?()=>j(t.id,t.meta):void 0};r.push({id:n,source:t.source.table,target:t.target.table,sourceHandle:h(`source`,t.source.column),targetHandle:h(`target`,t.target.column),type:`joinEdge`,deletable:!0,data:s})}return[...n,...r]},[V,z,k,U,j,N]),ue=(0,t.useCallback)(e=>{A&&(!e.source||!e.target||A({table:e.source,column:_(e.sourceHandle)},{table:e.target,column:_(e.targetHandle)}))},[A]),de=(0,t.useCallback)(e=>{if(j)for(let t of e){if(!t.id.startsWith(g))continue;let e=t.id.slice(5),n=k?.find(t=>t.id===e);j(e,n?.meta)}},[j,k]),fe=(0,t.useCallback)((e,t)=>{if(!M||!t.id.startsWith(g))return;let n=t.id.slice(5),r=k?.find(e=>e.id===n);M(n,r?.meta)},[M,k]),Q=!!ee,pe=(0,t.useMemo)(()=>({onTableRemove:P,onColumnClick:F}),[P,F]),$=(0,t.useRef)(null);return(0,r.jsxs)(`div`,{ref:$,className:ne,style:{width:`100%`,height:`100%`,position:`relative`,...re},children:[B&&(0,r.jsx)(`div`,{style:{position:`absolute`,top:8,left:8,right:8,zIndex:10,padding:`8px 12px`,background:`#fef2f2`,border:`1px solid #fecaca`,borderRadius:6,color:`#991b1b`,fontFamily:`ui-monospace, SFMono-Regular, Consolas, monospace`,fontSize:12,whiteSpace:`pre-wrap`},children:B.message}),!B&&!V&&(0,r.jsx)(`div`,{style:{position:`absolute`,inset:0,display:`flex`,alignItems:`center`,justifyContent:`center`,color:`#9ca3af`,fontSize:13},children:`Computing layout…`}),(0,r.jsx)(i.Provider,{value:se,children:(0,r.jsx)(a.Provider,{value:ce,children:(0,r.jsx)(o.Provider,{value:Q,children:(0,r.jsx)(s.Provider,{value:pe,children:(0,r.jsxs)(n.ReactFlow,{nodes:ie,edges:le,nodeTypes:f,edgeTypes:p,fitView:!0,onNodesChange:ae,onNodeDragStop:oe,onNodeClick:I?(e,t)=>{let n=t.data?.table?.meta;I(t.id,n)}:void 0,onEdgeMouseEnter:(e,t)=>W(t.id),onEdgeMouseLeave:()=>W(null),onEdgeClick:M?fe:void 0,onConnect:ue,onEdgesDelete:de,nodesDraggable:!0,nodesConnectable:Q,elementsSelectable:!0,deleteKeyCode:te,minZoom:.1,maxZoom:4,children:[(0,r.jsx)(n.Background,{}),(0,r.jsx)(n.Controls,{}),(0,r.jsx)(n.MiniMap,{pannable:!0,zoomable:!0}),(0,r.jsx)(b,{apiRef:l,wrapperRef:$})]})})})})})]})});exports.HEADER_HEIGHT=e.t,exports.MermaidER=x,exports.MermaidERParseError=e.s,exports.NODE_WIDTH=e.n,exports.ROW_HEIGHT=e.r,exports.VERTICAL_PADDING=e.i,exports.estimateNodeHeight=e.a,exports.layoutER=e.o,exports.parseMermaidER=e.c;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":[],"sources":["../src/components/TableNode.tsx","../src/components/JoinEdge.tsx","../src/components/MermaidER.tsx"],"sourcesContent":["import { Fragment, createContext, memo, useContext } from 'react';\nimport { Handle, Position } from '@xyflow/react';\nimport type { NodeProps } from '@xyflow/react';\nimport type { Column, Table } from '../core/model';\nimport { HEADER_HEIGHT, ROW_HEIGHT } from '../core/layout';\n\nexport interface TableNodeData extends Record<string, unknown> {\n table: Table;\n}\n\n/**\n * Map from table name -> set of highlighted column names.\n * Provided by MermaidER, consumed by TableNode for hover-driven highlighting\n * without forcing the whole node array to recompute on every hover change.\n */\nexport const HighlightContext = createContext<ReadonlyMap<string, ReadonlySet<string>>>(new Map());\n\nexport interface ColumnSelectionContextValue {\n enabled: boolean;\n /** \"table.column\" keys for fast lookup. */\n selected: ReadonlySet<string>;\n onToggle: (table: string, column: string, checked: boolean) => void;\n}\n\nexport const ColumnSelectionContext = createContext<ColumnSelectionContextValue>({\n enabled: false,\n selected: new Set(),\n onToggle: () => undefined,\n});\n\n/** When true, column handles become visible/connectable for manual JOIN drawing. */\nexport const ConnectModeContext = createContext<boolean>(false);\n\nexport interface TableActionsContextValue {\n /** When provided, a delete affordance is shown on the table header. */\n onTableRemove?: (table: string) => void;\n /** Per-column click handler. Provided via context (not node data) so its\n * identity can change without invalidating the React Flow node array. */\n onColumnClick?: (table: string, column: string) => void;\n}\n\nexport const TableActionsContext = createContext<TableActionsContextValue>({});\n\nconst KEY_STYLES: Record<'pk' | 'fk' | 'uk', { label: string; bg: string }> = {\n pk: { label: 'PK', bg: '#f59e0b' },\n fk: { label: 'FK', bg: '#3b82f6' },\n uk: { label: 'UK', bg: '#10b981' },\n};\n\nfunction ColumnRow({\n tableName,\n column,\n highlighted,\n onClick,\n selectionEnabled,\n selected,\n onSelectToggle,\n}: {\n tableName: string;\n column: Column;\n highlighted: boolean;\n onClick?: (table: string, column: string) => void;\n selectionEnabled: boolean;\n selected: boolean;\n onSelectToggle: (checked: boolean) => void;\n}) {\n const badges: Array<{ label: string; bg: string }> = [];\n if (column.keys.pk) badges.push(KEY_STYLES.pk);\n if (column.keys.fk) badges.push(KEY_STYLES.fk);\n if (column.keys.uk) badges.push(KEY_STYLES.uk);\n\n return (\n <div\n title={column.comment}\n onClick={onClick ? () => onClick(tableName, column.name) : undefined}\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 6,\n padding: '0 10px',\n fontSize: 12,\n fontFamily: 'ui-monospace, SFMono-Regular, Consolas, monospace',\n borderTop: '1px solid #eee',\n height: ROW_HEIGHT,\n boxSizing: 'border-box',\n cursor: onClick ? 'pointer' : 'default',\n background: highlighted ? '#fef3c7' : selected ? '#eff6ff' : 'transparent',\n transition: 'background 0.15s',\n }}\n >\n {selectionEnabled && (\n <input\n type=\"checkbox\"\n checked={selected}\n onChange={(e) => onSelectToggle(e.target.checked)}\n onClick={(e) => e.stopPropagation()}\n style={{\n width: 13,\n height: 13,\n margin: 0,\n flexShrink: 0,\n cursor: 'pointer',\n }}\n />\n )}\n <span style={{ display: 'flex', gap: 2, flexShrink: 0, minWidth: 18 }}>\n {badges.map((b) => (\n <span\n key={b.label}\n style={{\n display: 'inline-block',\n padding: '0 4px',\n borderRadius: 3,\n background: b.bg,\n color: '#fff',\n fontSize: 9,\n fontWeight: 700,\n lineHeight: '14px',\n }}\n >\n {b.label}\n </span>\n ))}\n </span>\n <span\n style={{\n flexShrink: 0,\n fontWeight: column.keys.pk ? 600 : 400,\n color: '#1f2937',\n }}\n >\n {column.name}\n </span>\n {column.type && (\n <span\n style={{\n flex: 1,\n textAlign: 'right',\n color: '#9ca3af',\n fontStyle: 'italic',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n }}\n >\n {column.type}\n </span>\n )}\n </div>\n );\n}\n\nexport const TableNode = memo(function TableNode({ data }: NodeProps) {\n const { table } = data as TableNodeData;\n const highlightMap = useContext(HighlightContext);\n const selection = useContext(ColumnSelectionContext);\n const connectMode = useContext(ConnectModeContext);\n const tableActions = useContext(TableActionsContext);\n const onColumnClick = tableActions.onColumnClick;\n const highlightedCols = highlightMap.get(table.name);\n const headerBg = table.group ? '#1e40af' : '#374151';\n\n const handleStyle = (extra: { top?: number }): React.CSSProperties => ({\n ...extra,\n width: connectMode ? 9 : 6,\n height: connectMode ? 9 : 6,\n background: connectMode ? '#3b82f6' : 'transparent',\n border: connectMode ? '1.5px solid #fff' : 'none',\n boxShadow: connectMode ? '0 0 0 1px rgba(59,130,246,0.4)' : 'none',\n opacity: connectMode ? 0.85 : 0,\n pointerEvents: connectMode ? 'auto' : 'none',\n cursor: connectMode ? 'crosshair' : 'default',\n });\n\n return (\n <div\n style={{\n background: '#fff',\n border: '1px solid #c4c4c4',\n borderRadius: 6,\n boxShadow: '0 2px 6px rgba(0,0,0,0.08)',\n overflow: 'visible',\n width: '100%',\n height: '100%',\n display: 'flex',\n flexDirection: 'column',\n position: 'relative',\n }}\n >\n <Handle\n id=\"__default-target\"\n type=\"target\"\n position={Position.Left}\n style={handleStyle({ top: HEADER_HEIGHT / 2 })}\n />\n <Handle\n id=\"__default-source\"\n type=\"source\"\n position={Position.Right}\n style={handleStyle({ top: HEADER_HEIGHT / 2 })}\n />\n\n <div\n style={{\n padding: '6px 10px',\n background: headerBg,\n color: '#fff',\n fontWeight: 600,\n fontSize: 13,\n height: HEADER_HEIGHT,\n boxSizing: 'border-box',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: 8,\n borderTopLeftRadius: 6,\n borderTopRightRadius: 6,\n }}\n >\n <span style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>\n {table.name}\n </span>\n <span style={{ display: 'flex', alignItems: 'center', gap: 4, flexShrink: 0 }}>\n {table.group && (\n <span\n style={{\n fontSize: 10,\n opacity: 0.75,\n fontWeight: 400,\n padding: '1px 5px',\n border: '1px solid rgba(255,255,255,0.3)',\n borderRadius: 3,\n }}\n >\n {table.group}\n </span>\n )}\n {tableActions.onTableRemove && (\n <button\n className=\"nodrag\"\n onClick={(e) => {\n e.stopPropagation();\n tableActions.onTableRemove?.(table.name);\n }}\n onMouseDown={(e) => e.stopPropagation()}\n title=\"Remove this table\"\n style={{\n background: 'rgba(255,255,255,0.18)',\n border: 'none',\n color: '#fff',\n width: 18,\n height: 18,\n borderRadius: 3,\n cursor: 'pointer',\n fontSize: 13,\n fontWeight: 700,\n padding: 0,\n lineHeight: 1,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n ×\n </button>\n )}\n </span>\n </div>\n\n {table.columns.map((col, i) => {\n const handleY = HEADER_HEIGHT + i * ROW_HEIGHT + ROW_HEIGHT / 2;\n const highlighted = highlightedCols?.has(col.name) ?? false;\n const selectionKey = `${table.name}.${col.name}`;\n const selected = selection.enabled && selection.selected.has(selectionKey);\n return (\n <Fragment key={`${col.name}-${i}`}>\n <Handle\n id={`${col.name}__target`}\n type=\"target\"\n position={Position.Left}\n style={handleStyle({ top: handleY })}\n />\n <Handle\n id={`${col.name}__source`}\n type=\"source\"\n position={Position.Right}\n style={handleStyle({ top: handleY })}\n />\n <ColumnRow\n tableName={table.name}\n column={col}\n highlighted={highlighted}\n onClick={onColumnClick}\n selectionEnabled={selection.enabled}\n selected={selected}\n onSelectToggle={(checked) =>\n selection.onToggle(table.name, col.name, checked)\n }\n />\n </Fragment>\n );\n })}\n </div>\n );\n});\n","import { memo } from 'react';\nimport {\n BaseEdge,\n EdgeLabelRenderer,\n getSmoothStepPath,\n type EdgeProps,\n} from '@xyflow/react';\nimport type { JoinType } from '../core/model';\n\nexport interface JoinEdgeData extends Record<string, unknown> {\n type: JoinType;\n color: string;\n hovered?: boolean;\n onDelete?: () => void;\n}\n\nexport const JoinEdge = memo(function JoinEdge({\n id,\n sourceX,\n sourceY,\n targetX,\n targetY,\n sourcePosition,\n targetPosition,\n data,\n selected,\n}: EdgeProps) {\n const [edgePath, labelX, labelY] = getSmoothStepPath({\n sourceX,\n sourceY,\n sourcePosition,\n targetX,\n targetY,\n targetPosition,\n });\n\n const d = (data ?? {}) as JoinEdgeData;\n const emphasized = !!selected || !!d.hovered;\n const color = d.color || '#3b82f6';\n\n return (\n <>\n <BaseEdge\n id={id}\n path={edgePath}\n style={{\n stroke: color,\n strokeWidth: emphasized ? 2.5 : 2,\n strokeDasharray: '6 3',\n }}\n />\n <EdgeLabelRenderer>\n <div\n className=\"nodrag nopan\"\n style={{\n position: 'absolute',\n transform: `translate(-50%, -50%) translate(${labelX}px, ${labelY}px)`,\n background: color,\n color: '#fff',\n fontSize: 10,\n fontFamily: 'ui-monospace, SFMono-Regular, Consolas, monospace',\n fontWeight: 700,\n borderRadius: 3,\n padding: '2px 4px 2px 6px',\n display: 'flex',\n alignItems: 'center',\n gap: 4,\n pointerEvents: 'all',\n boxShadow: emphasized\n ? '0 0 0 2px rgba(0,0,0,0.4)'\n : '0 1px 2px rgba(0,0,0,0.15)',\n userSelect: 'none',\n }}\n >\n <span>{d.type}</span>\n {d.onDelete && (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n d.onDelete?.();\n }}\n onMouseDown={(e) => e.stopPropagation()}\n title=\"Remove this JOIN\"\n style={{\n background: 'rgba(255,255,255,0.25)',\n border: 'none',\n color: '#fff',\n width: 14,\n height: 14,\n borderRadius: 2,\n cursor: 'pointer',\n fontSize: 11,\n fontWeight: 700,\n padding: 0,\n lineHeight: 1,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n ×\n </button>\n )}\n </div>\n </EdgeLabelRenderer>\n </>\n );\n});\n","import {\n useCallback,\n useEffect,\n useMemo,\n useState,\n type CSSProperties,\n} from 'react';\nimport {\n ReactFlow,\n Background,\n Controls,\n MiniMap,\n useNodesState,\n type Connection,\n type Edge,\n type EdgeTypes,\n type Node,\n type NodeTypes,\n} from '@xyflow/react';\n// React Flow's CSS is intentionally NOT imported here. Consumers must add it\n// once at their app entry point: `import '@xyflow/react/dist/style.css';`.\n// Importing it from this file would cause double-injection in apps that\n// already use React Flow, and inflate this library's bundled assets.\nimport { parseMermaidER, MermaidERParseError } from '../core/parser';\nimport {\n layoutER,\n type LayoutAlgorithm,\n type LayoutDirection,\n type LayoutResult,\n} from '../core/layout';\nimport type {\n ColumnRef,\n ERModel,\n Join,\n PartialColumnRef,\n Relation,\n} from '../core/model';\nimport {\n ColumnSelectionContext,\n ConnectModeContext,\n HighlightContext,\n TableActionsContext,\n TableNode,\n type ColumnSelectionContextValue,\n type TableActionsContextValue,\n type TableNodeData,\n} from './TableNode';\nimport { JoinEdge, type JoinEdgeData } from './JoinEdge';\n\nconst nodeTypes: NodeTypes = {\n table: TableNode,\n};\n\nconst edgeTypes: EdgeTypes = {\n joinEdge: JoinEdge,\n};\n\nexport interface NodePosition {\n x: number;\n y: number;\n}\n\nexport type NodePositions = Record<string, NodePosition>;\n\nexport interface MermaidERProps {\n /** Mermaid ER source. Mutually exclusive with `model`. */\n source?: string;\n /** Pre-built ER model. Takes precedence over `source`. */\n model?: ERModel;\n layout?: 'elk';\n algorithm?: LayoutAlgorithm;\n direction?: LayoutDirection;\n aspectRatio?: number;\n positions?: NodePositions;\n onPositionsChange?: (positions: NodePositions) => void;\n showColumnCheckboxes?: boolean;\n selectedColumns?: ColumnRef[];\n onColumnSelectionChange?: (selectedColumns: ColumnRef[]) => void;\n /** Enable column-to-column / card-to-card drag for manual JOINs. */\n enableManualJoins?: boolean;\n /** Existing manual joins to render alongside FK relations. */\n joins?: Join[];\n /**\n * Fired when the user finishes a connect drag. The consumer typically opens\n * a dialog to ask for join type, then appends a complete `Join` to its state.\n * `column` may be undefined when the drag landed on a default (table-center) handle.\n */\n onJoinConnect?: (source: PartialColumnRef, target: PartialColumnRef) => void;\n /** Fired when the user removes a manual join via Delete or the trash icon. */\n onJoinDelete?: (joinId: string) => void;\n /** When provided, a small × appears on each table header to remove it from the canvas. */\n onTableRemove?: (table: string) => void;\n highlightReferencesOnHover?: boolean;\n onColumnClick?: (table: string, column: string) => void;\n onTableClick?: (table: string) => void;\n /** Override the default delete-key code(s). Default is 'Delete' (Backspace ignored to prevent accidents). */\n deleteKeyCode?: string | string[] | null;\n className?: string;\n style?: CSSProperties;\n}\n\ninterface ParseState {\n model: ERModel | null;\n error: MermaidERParseError | null;\n}\n\nfunction safeParse(source: string): ParseState {\n try {\n return { model: parseMermaidER(source), error: null };\n } catch (e) {\n if (e instanceof MermaidERParseError) {\n return { model: null, error: e };\n }\n throw e;\n }\n}\n\nfunction handleIdFor(side: 'source' | 'target', column: string | undefined): string {\n return column ? `${column}__${side}` : `__default-${side}`;\n}\n\nconst JOIN_EDGE_PREFIX = 'join:';\n\nfunction parseHandleColumn(handleId: string | null | undefined): string | undefined {\n if (!handleId) return undefined;\n if (handleId.startsWith('__default-')) return undefined;\n const m = /^(.+)__(?:source|target)$/.exec(handleId);\n return m ? m[1] : undefined;\n}\n\nfunction refKey(ref: ColumnRef): string {\n return `${ref.table}.${ref.column}`;\n}\n\nconst JOIN_TYPE_COLOR: Record<Join['type'], string> = {\n INNER: '#3b82f6',\n LEFT: '#8b5cf6',\n RIGHT: '#a855f7',\n FULL: '#ec4899',\n CROSS: '#6b7280',\n};\n\nexport function MermaidER(props: MermaidERProps) {\n const {\n source,\n model: modelProp,\n algorithm,\n direction,\n aspectRatio,\n positions,\n onPositionsChange,\n showColumnCheckboxes,\n selectedColumns,\n onColumnSelectionChange,\n enableManualJoins,\n joins,\n onJoinConnect,\n onJoinDelete,\n onTableRemove,\n onColumnClick,\n onTableClick,\n deleteKeyCode = 'Delete',\n className,\n style,\n highlightReferencesOnHover = true,\n } = props;\n\n const { model, error } = useMemo<ParseState>(() => {\n if (modelProp) return { model: modelProp, error: null };\n if (source != null) return safeParse(source);\n return { model: null, error: null };\n }, [source, modelProp]);\n\n const [layout, setLayout] = useState<LayoutResult | null>(null);\n const [hoveredEdgeId, setHoveredEdgeId] = useState<string | null>(null);\n\n useEffect(() => {\n if (!model) {\n setLayout(null);\n return;\n }\n let cancelled = false;\n layoutER(model, { algorithm, direction, aspectRatio }).then((result) => {\n if (!cancelled) setLayout(result);\n });\n return () => {\n cancelled = true;\n };\n }, [model, algorithm, direction, aspectRatio]);\n\n const baseNodes = useMemo<Node[]>(() => {\n if (!layout || !model) return [];\n const tableMap = new Map(model.tables.map((t) => [t.name, t]));\n const result: Node[] = [];\n for (const n of layout.nodes) {\n const table = tableMap.get(n.id);\n // Skip stale nodes: a model update can arrive before the new layout\n // finishes; in that gap, layout may still reference a removed table.\n if (!table) continue;\n const override = positions?.[n.id];\n const data: TableNodeData = { table };\n result.push({\n id: n.id,\n type: 'table',\n position: override ?? { x: n.x, y: n.y },\n data,\n width: n.width,\n height: n.height,\n draggable: true,\n deletable: false,\n });\n }\n return result;\n // `onColumnClick` is intentionally NOT a dep — it flows via TableActionsContext\n // so a non-stable callback identity from the parent doesn't reset React Flow\n // node state (which would clobber an in-flight drag).\n }, [layout, model, positions]);\n\n const [nodes, setNodes, onNodesChange] = useNodesState<Node>(baseNodes);\n\n useEffect(() => {\n setNodes(baseNodes);\n }, [baseNodes, setNodes]);\n\n const handleNodeDragStop = useCallback(\n (_: unknown, _primary: Node, dragged: Node[]) => {\n if (!onPositionsChange) return;\n const next: NodePositions = { ...(positions ?? {}) };\n for (const n of dragged) {\n next[n.id] = { x: n.position.x, y: n.position.y };\n }\n onPositionsChange(next);\n },\n [positions, onPositionsChange],\n );\n\n const hoveredRelation = useMemo<Relation | undefined>(() => {\n if (!hoveredEdgeId || !model) return undefined;\n return model.relations.find((r) => r.id === hoveredEdgeId);\n }, [hoveredEdgeId, model]);\n\n const hoveredJoin = useMemo<Join | undefined>(() => {\n if (!hoveredEdgeId || !joins) return undefined;\n if (!hoveredEdgeId.startsWith(JOIN_EDGE_PREFIX)) return undefined;\n const id = hoveredEdgeId.slice(JOIN_EDGE_PREFIX.length);\n return joins.find((j) => j.id === id);\n }, [hoveredEdgeId, joins]);\n\n const highlightMap = useMemo<ReadonlyMap<string, ReadonlySet<string>>>(() => {\n const map = new Map<string, Set<string>>();\n if (!highlightReferencesOnHover) return map;\n\n const add = (table: string, column: string | undefined) => {\n if (!column) return;\n const set = map.get(table) ?? new Set();\n set.add(column);\n map.set(table, set);\n };\n\n if (hoveredRelation) {\n add(hoveredRelation.from, hoveredRelation.fromColumn);\n add(hoveredRelation.to, hoveredRelation.toColumn);\n }\n if (hoveredJoin) {\n add(hoveredJoin.source.table, hoveredJoin.source.column);\n add(hoveredJoin.target.table, hoveredJoin.target.column);\n }\n return map;\n }, [hoveredRelation, hoveredJoin, highlightReferencesOnHover]);\n\n const selectionSet = useMemo<ReadonlySet<string>>(() => {\n return new Set((selectedColumns ?? []).map(refKey));\n }, [selectedColumns]);\n\n const handleColumnSelectToggle = useCallback(\n (table: string, column: string, checked: boolean) => {\n if (!onColumnSelectionChange) return;\n const list = selectedColumns ?? [];\n if (checked) {\n if (list.some((r) => r.table === table && r.column === column)) return;\n onColumnSelectionChange([...list, { table, column }]);\n } else {\n onColumnSelectionChange(\n list.filter((r) => !(r.table === table && r.column === column)),\n );\n }\n },\n [selectedColumns, onColumnSelectionChange],\n );\n\n const selectionContext = useMemo<ColumnSelectionContextValue>(\n () => ({\n enabled: showColumnCheckboxes ?? false,\n selected: selectionSet,\n onToggle: handleColumnSelectToggle,\n }),\n [showColumnCheckboxes, selectionSet, handleColumnSelectToggle],\n );\n\n const edges = useMemo<Edge[]>(() => {\n if (!layout || !model) return [];\n const tableSet = new Set(model.tables.map((t) => t.name));\n const relMap = new Map(model.relations.map((r) => [r.id, r]));\n\n const fkEdges: Edge[] = [];\n for (const e of layout.edges) {\n // Skip stale edges referencing tables removed since the layout was computed.\n if (!tableSet.has(e.source) || !tableSet.has(e.target)) continue;\n const rel = relMap.get(e.id);\n const isHovered = e.id === hoveredEdgeId;\n fkEdges.push({\n id: e.id,\n source: e.source,\n target: e.target,\n sourceHandle: handleIdFor('source', rel?.fromColumn),\n targetHandle: handleIdFor('target', rel?.toColumn),\n type: 'smoothstep',\n animated: isHovered,\n deletable: false,\n style: {\n stroke: isHovered ? '#f59e0b' : '#9ca3af',\n strokeWidth: isHovered ? 2 : 1.5,\n },\n label: rel?.label,\n labelStyle: { fontSize: 10, fill: '#6b7280' },\n labelBgStyle: { fill: '#fff', fillOpacity: 0.85 },\n labelBgPadding: [4, 2] as [number, number],\n labelBgBorderRadius: 3,\n });\n }\n\n const joinEdges: Edge[] = [];\n for (const j of joins ?? []) {\n if (!tableSet.has(j.source.table) || !tableSet.has(j.target.table)) continue;\n const edgeId = `${JOIN_EDGE_PREFIX}${j.id}`;\n const isHovered = edgeId === hoveredEdgeId;\n const color = JOIN_TYPE_COLOR[j.type] ?? '#3b82f6';\n const data: JoinEdgeData = {\n type: j.type,\n color,\n hovered: isHovered,\n onDelete: onJoinDelete ? () => onJoinDelete(j.id) : undefined,\n };\n joinEdges.push({\n id: edgeId,\n source: j.source.table,\n target: j.target.table,\n sourceHandle: handleIdFor('source', j.source.column),\n targetHandle: handleIdFor('target', j.target.column),\n type: 'joinEdge',\n deletable: true,\n data: data as unknown as Record<string, unknown>,\n });\n }\n\n return [...fkEdges, ...joinEdges];\n }, [layout, model, joins, hoveredEdgeId, onJoinDelete]);\n\n const handleConnect = useCallback(\n (conn: Connection) => {\n if (!onJoinConnect) return;\n if (!conn.source || !conn.target) return;\n onJoinConnect(\n { table: conn.source, column: parseHandleColumn(conn.sourceHandle) },\n { table: conn.target, column: parseHandleColumn(conn.targetHandle) },\n );\n },\n [onJoinConnect],\n );\n\n const handleEdgesDelete = useCallback(\n (deleted: Edge[]) => {\n if (!onJoinDelete) return;\n for (const e of deleted) {\n if (e.id.startsWith(JOIN_EDGE_PREFIX)) {\n onJoinDelete(e.id.slice(JOIN_EDGE_PREFIX.length));\n }\n }\n },\n [onJoinDelete],\n );\n\n const connectModeOn = !!enableManualJoins;\n const tableActions = useMemo<TableActionsContextValue>(\n () => ({ onTableRemove, onColumnClick }),\n [onTableRemove, onColumnClick],\n );\n\n return (\n <div\n className={className}\n style={{ width: '100%', height: '100%', position: 'relative', ...style }}\n >\n {error && (\n <div\n style={{\n position: 'absolute',\n top: 8,\n left: 8,\n right: 8,\n zIndex: 10,\n padding: '8px 12px',\n background: '#fef2f2',\n border: '1px solid #fecaca',\n borderRadius: 6,\n color: '#991b1b',\n fontFamily: 'ui-monospace, SFMono-Regular, Consolas, monospace',\n fontSize: 12,\n whiteSpace: 'pre-wrap',\n }}\n >\n {error.message}\n </div>\n )}\n {!error && !layout && (\n <div\n style={{\n position: 'absolute',\n inset: 0,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n color: '#9ca3af',\n fontSize: 13,\n }}\n >\n Computing layout…\n </div>\n )}\n <HighlightContext.Provider value={highlightMap}>\n <ColumnSelectionContext.Provider value={selectionContext}>\n <ConnectModeContext.Provider value={connectModeOn}>\n <TableActionsContext.Provider value={tableActions}>\n <ReactFlow\n nodes={nodes}\n edges={edges}\n nodeTypes={nodeTypes}\n edgeTypes={edgeTypes}\n fitView\n onNodesChange={onNodesChange}\n onNodeDragStop={handleNodeDragStop}\n onNodeClick={\n onTableClick ? (_, node) => onTableClick(node.id) : undefined\n }\n onEdgeMouseEnter={(_, edge) => setHoveredEdgeId(edge.id)}\n onEdgeMouseLeave={() => setHoveredEdgeId(null)}\n onConnect={handleConnect}\n onEdgesDelete={handleEdgesDelete}\n nodesDraggable\n nodesConnectable={connectModeOn}\n elementsSelectable\n deleteKeyCode={deleteKeyCode}\n minZoom={0.1}\n maxZoom={4}\n >\n <Background />\n <Controls />\n <MiniMap pannable zoomable />\n </ReactFlow>\n </TableActionsContext.Provider>\n </ConnectModeContext.Provider>\n </ColumnSelectionContext.Provider>\n </HighlightContext.Provider>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":[],"sources":["../src/components/TableNode.tsx","../src/components/JoinEdge.tsx","../src/components/MermaidER.tsx"],"sourcesContent":["import { Fragment, createContext, memo, useContext, useEffect, useMemo, useRef } from 'react';\nimport { Handle, Position } from '@xyflow/react';\nimport type { NodeProps } from '@xyflow/react';\nimport type { Column, Table } from '../core/model';\nimport { HEADER_HEIGHT, ROW_HEIGHT } from '../core/layout';\n\nexport interface TableNodeData extends Record<string, unknown> {\n table: Table;\n}\n\n/**\n * Map from table name -> set of highlighted column names.\n * Provided by MermaidER, consumed by TableNode for hover-driven highlighting\n * without forcing the whole node array to recompute on every hover change.\n */\nexport const HighlightContext = createContext<ReadonlyMap<string, ReadonlySet<string>>>(new Map());\n\nexport interface ColumnSelectionContextValue {\n enabled: boolean;\n /** When true, render a per-table select-all checkbox in each header. */\n showSelectAll: boolean;\n /** \"table.column\" keys for fast lookup. */\n selected: ReadonlySet<string>;\n onToggle: (table: string, column: string, checked: boolean) => void;\n onToggleAll: (table: string, columns: string[], nextState: boolean) => void;\n}\n\nexport const ColumnSelectionContext = createContext<ColumnSelectionContextValue>({\n enabled: false,\n showSelectAll: false,\n selected: new Set(),\n onToggle: () => undefined,\n onToggleAll: () => undefined,\n});\n\n/** When true, column handles become visible/connectable for manual JOIN drawing. */\nexport const ConnectModeContext = createContext<boolean>(false);\n\nexport interface TableActionsContextValue {\n /** When provided, a delete affordance is shown on the table header. */\n onTableRemove?: (table: string, meta?: unknown) => void;\n /** Per-column click handler. Provided via context (not node data) so its\n * identity can change without invalidating the React Flow node array. */\n onColumnClick?: (table: string, column: string) => void;\n}\n\nexport const TableActionsContext = createContext<TableActionsContextValue>({});\n\nconst KEY_STYLES: Record<'pk' | 'fk' | 'uk', { label: string; bg: string }> = {\n pk: { label: 'PK', bg: '#f59e0b' },\n fk: { label: 'FK', bg: '#3b82f6' },\n uk: { label: 'UK', bg: '#10b981' },\n};\n\nfunction ColumnRow({\n tableName,\n column,\n highlighted,\n onClick,\n selectionEnabled,\n selected,\n onSelectToggle,\n}: {\n tableName: string;\n column: Column;\n highlighted: boolean;\n onClick?: (table: string, column: string) => void;\n selectionEnabled: boolean;\n selected: boolean;\n onSelectToggle: (checked: boolean) => void;\n}) {\n const badges: Array<{ label: string; bg: string }> = [];\n if (column.keys.pk) badges.push(KEY_STYLES.pk);\n if (column.keys.fk) badges.push(KEY_STYLES.fk);\n if (column.keys.uk) badges.push(KEY_STYLES.uk);\n\n return (\n <div\n title={column.comment}\n onClick={onClick ? () => onClick(tableName, column.name) : undefined}\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 6,\n padding: '0 10px',\n fontSize: 12,\n fontFamily: 'ui-monospace, SFMono-Regular, Consolas, monospace',\n borderTop: '1px solid #eee',\n height: ROW_HEIGHT,\n boxSizing: 'border-box',\n cursor: onClick ? 'pointer' : 'default',\n background: highlighted ? '#fef3c7' : selected ? '#eff6ff' : 'transparent',\n transition: 'background 0.15s',\n }}\n >\n {selectionEnabled && (\n <input\n type=\"checkbox\"\n checked={selected}\n onChange={(e) => onSelectToggle(e.target.checked)}\n onClick={(e) => e.stopPropagation()}\n style={{\n width: 13,\n height: 13,\n margin: 0,\n flexShrink: 0,\n cursor: 'pointer',\n }}\n />\n )}\n <span style={{ display: 'flex', gap: 2, flexShrink: 0, minWidth: 18 }}>\n {badges.map((b) => (\n <span\n key={b.label}\n style={{\n display: 'inline-block',\n padding: '0 4px',\n borderRadius: 3,\n background: b.bg,\n color: '#fff',\n fontSize: 9,\n fontWeight: 700,\n lineHeight: '14px',\n }}\n >\n {b.label}\n </span>\n ))}\n </span>\n <span\n style={{\n flexShrink: 0,\n fontWeight: column.keys.pk ? 600 : 400,\n color: '#1f2937',\n }}\n >\n {column.name}\n </span>\n {column.type && (\n <span\n style={{\n flex: 1,\n textAlign: 'right',\n color: '#9ca3af',\n fontStyle: 'italic',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n }}\n >\n {column.type}\n </span>\n )}\n </div>\n );\n}\n\nexport const TableNode = memo(function TableNode({ data }: NodeProps) {\n const { table } = data as TableNodeData;\n const highlightMap = useContext(HighlightContext);\n const selection = useContext(ColumnSelectionContext);\n const connectMode = useContext(ConnectModeContext);\n const tableActions = useContext(TableActionsContext);\n const onColumnClick = tableActions.onColumnClick;\n const highlightedCols = highlightMap.get(table.name);\n const headerBg = table.group ? '#1e40af' : '#374151';\n\n const showSelectAllCheckbox =\n selection.enabled && selection.showSelectAll && table.columns.length > 0;\n const allColumnNames = useMemo(\n () => table.columns.map((c) => c.name),\n [table.columns],\n );\n const selectedCountInTable = useMemo(() => {\n if (!showSelectAllCheckbox) return 0;\n let n = 0;\n for (const c of allColumnNames) {\n if (selection.selected.has(`${table.name}.${c}`)) n++;\n }\n return n;\n }, [showSelectAllCheckbox, allColumnNames, selection.selected, table.name]);\n const allSelected =\n showSelectAllCheckbox && selectedCountInTable === allColumnNames.length;\n const someSelected =\n showSelectAllCheckbox &&\n selectedCountInTable > 0 &&\n selectedCountInTable < allColumnNames.length;\n const selectAllRef = useRef<HTMLInputElement | null>(null);\n useEffect(() => {\n if (selectAllRef.current) selectAllRef.current.indeterminate = someSelected;\n }, [someSelected]);\n\n const handleStyle = (extra: { top?: number }): React.CSSProperties => ({\n ...extra,\n width: connectMode ? 9 : 6,\n height: connectMode ? 9 : 6,\n background: connectMode ? '#3b82f6' : 'transparent',\n border: connectMode ? '1.5px solid #fff' : 'none',\n boxShadow: connectMode ? '0 0 0 1px rgba(59,130,246,0.4)' : 'none',\n opacity: connectMode ? 0.85 : 0,\n pointerEvents: connectMode ? 'auto' : 'none',\n cursor: connectMode ? 'crosshair' : 'default',\n });\n\n return (\n <div\n style={{\n background: '#fff',\n border: '1px solid #c4c4c4',\n borderRadius: 6,\n boxShadow: '0 2px 6px rgba(0,0,0,0.08)',\n overflow: 'visible',\n width: '100%',\n height: '100%',\n display: 'flex',\n flexDirection: 'column',\n position: 'relative',\n }}\n >\n <Handle\n id=\"__default-target\"\n type=\"target\"\n position={Position.Left}\n style={handleStyle({ top: HEADER_HEIGHT / 2 })}\n />\n <Handle\n id=\"__default-source\"\n type=\"source\"\n position={Position.Right}\n style={handleStyle({ top: HEADER_HEIGHT / 2 })}\n />\n\n <div\n style={{\n padding: '6px 10px',\n background: headerBg,\n color: '#fff',\n fontWeight: 600,\n fontSize: 13,\n height: HEADER_HEIGHT,\n boxSizing: 'border-box',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: 8,\n borderTopLeftRadius: 6,\n borderTopRightRadius: 6,\n }}\n >\n <span\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 6,\n overflow: 'hidden',\n minWidth: 0,\n }}\n >\n {showSelectAllCheckbox && (\n <input\n ref={selectAllRef}\n type=\"checkbox\"\n className=\"nodrag\"\n checked={allSelected}\n onChange={(e) =>\n selection.onToggleAll(table.name, allColumnNames, e.target.checked)\n }\n onClick={(e) => e.stopPropagation()}\n onMouseDown={(e) => e.stopPropagation()}\n title={\n allSelected\n ? 'Deselect all columns'\n : someSelected\n ? 'Some columns selected — click to select all'\n : 'Select all columns'\n }\n style={{\n width: 13,\n height: 13,\n margin: 0,\n flexShrink: 0,\n cursor: 'pointer',\n accentColor: '#3b82f6',\n }}\n />\n )}\n <span\n style={{\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n }}\n >\n {table.name}\n </span>\n </span>\n <span style={{ display: 'flex', alignItems: 'center', gap: 4, flexShrink: 0 }}>\n {table.group && (\n <span\n style={{\n fontSize: 10,\n opacity: 0.75,\n fontWeight: 400,\n padding: '1px 5px',\n border: '1px solid rgba(255,255,255,0.3)',\n borderRadius: 3,\n }}\n >\n {table.group}\n </span>\n )}\n {tableActions.onTableRemove && (\n <button\n className=\"nodrag\"\n onClick={(e) => {\n e.stopPropagation();\n tableActions.onTableRemove?.(table.name, table.meta);\n }}\n onMouseDown={(e) => e.stopPropagation()}\n title=\"Remove this table\"\n style={{\n background: 'rgba(255,255,255,0.18)',\n border: 'none',\n color: '#fff',\n width: 18,\n height: 18,\n borderRadius: 3,\n cursor: 'pointer',\n fontSize: 13,\n fontWeight: 700,\n padding: 0,\n lineHeight: 1,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n ×\n </button>\n )}\n </span>\n </div>\n\n {table.columns.map((col, i) => {\n const handleY = HEADER_HEIGHT + i * ROW_HEIGHT + ROW_HEIGHT / 2;\n const highlighted = highlightedCols?.has(col.name) ?? false;\n const selectionKey = `${table.name}.${col.name}`;\n const selected = selection.enabled && selection.selected.has(selectionKey);\n return (\n <Fragment key={`${col.name}-${i}`}>\n <Handle\n id={`${col.name}__target`}\n type=\"target\"\n position={Position.Left}\n style={handleStyle({ top: handleY })}\n />\n <Handle\n id={`${col.name}__source`}\n type=\"source\"\n position={Position.Right}\n style={handleStyle({ top: handleY })}\n />\n <ColumnRow\n tableName={table.name}\n column={col}\n highlighted={highlighted}\n onClick={onColumnClick}\n selectionEnabled={selection.enabled}\n selected={selected}\n onSelectToggle={(checked) =>\n selection.onToggle(table.name, col.name, checked)\n }\n />\n </Fragment>\n );\n })}\n </div>\n );\n});\n","import { memo } from 'react';\nimport {\n BaseEdge,\n EdgeLabelRenderer,\n getSmoothStepPath,\n type EdgeProps,\n} from '@xyflow/react';\nimport type { JoinType } from '../core/model';\n\nexport interface JoinEdgeData extends Record<string, unknown> {\n type: JoinType;\n color: string;\n /** Optional override for the edge stroke width. Defaults to 2 / 2.5 (when emphasized). */\n strokeWidth?: number;\n /** Optional override for the edge dasharray. Defaults to '6 3' (dashed). Pass '' for solid. */\n strokeDasharray?: string;\n hovered?: boolean;\n onDelete?: () => void;\n}\n\nexport const JoinEdge = memo(function JoinEdge({\n id,\n sourceX,\n sourceY,\n targetX,\n targetY,\n sourcePosition,\n targetPosition,\n data,\n selected,\n}: EdgeProps) {\n const [edgePath, labelX, labelY] = getSmoothStepPath({\n sourceX,\n sourceY,\n sourcePosition,\n targetX,\n targetY,\n targetPosition,\n });\n\n const d = (data ?? {}) as JoinEdgeData;\n const emphasized = !!selected || !!d.hovered;\n const color = d.color || '#3b82f6';\n\n return (\n <>\n <BaseEdge\n id={id}\n path={edgePath}\n style={{\n stroke: color,\n strokeWidth: d.strokeWidth ?? (emphasized ? 2.5 : 2),\n strokeDasharray: d.strokeDasharray ?? '6 3',\n }}\n />\n <EdgeLabelRenderer>\n <div\n className=\"nodrag nopan\"\n style={{\n position: 'absolute',\n transform: `translate(-50%, -50%) translate(${labelX}px, ${labelY}px)`,\n background: color,\n color: '#fff',\n fontSize: 10,\n fontFamily: 'ui-monospace, SFMono-Regular, Consolas, monospace',\n fontWeight: 700,\n borderRadius: 3,\n padding: '2px 4px 2px 6px',\n display: 'flex',\n alignItems: 'center',\n gap: 4,\n pointerEvents: 'all',\n boxShadow: emphasized\n ? '0 0 0 2px rgba(0,0,0,0.4)'\n : '0 1px 2px rgba(0,0,0,0.15)',\n userSelect: 'none',\n }}\n >\n <span>{d.type}</span>\n {d.onDelete && (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n d.onDelete?.();\n }}\n onMouseDown={(e) => e.stopPropagation()}\n title=\"Remove this JOIN\"\n style={{\n background: 'rgba(255,255,255,0.25)',\n border: 'none',\n color: '#fff',\n width: 14,\n height: 14,\n borderRadius: 2,\n cursor: 'pointer',\n fontSize: 11,\n fontWeight: 700,\n padding: 0,\n lineHeight: 1,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n ×\n </button>\n )}\n </div>\n </EdgeLabelRenderer>\n </>\n );\n});\n","import {\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n type CSSProperties,\n type Ref,\n} from 'react';\nimport {\n ReactFlow,\n Background,\n Controls,\n MiniMap,\n useNodesState,\n useReactFlow,\n type Connection,\n type Edge,\n type EdgeTypes,\n type FitViewOptions,\n type Node,\n type NodeTypes,\n type Rect,\n type Viewport,\n} from '@xyflow/react';\n// React Flow's CSS is intentionally NOT imported here. Consumers must add it\n// once at their app entry point: `import '@xyflow/react/dist/style.css';`.\n// Importing it from this file would cause double-injection in apps that\n// already use React Flow, and inflate this library's bundled assets.\nimport { parseMermaidER, MermaidERParseError } from '../core/parser';\nimport {\n layoutER,\n type LayoutAlgorithm,\n type LayoutDirection,\n type LayoutResult,\n} from '../core/layout';\nimport type {\n ColumnRef,\n ERModel,\n Join,\n PartialColumnRef,\n Relation,\n} from '../core/model';\nimport {\n ColumnSelectionContext,\n ConnectModeContext,\n HighlightContext,\n TableActionsContext,\n TableNode,\n type ColumnSelectionContextValue,\n type TableActionsContextValue,\n type TableNodeData,\n} from './TableNode';\nimport { JoinEdge, type JoinEdgeData } from './JoinEdge';\n\nconst nodeTypes: NodeTypes = {\n table: TableNode,\n};\n\nconst edgeTypes: EdgeTypes = {\n joinEdge: JoinEdge,\n};\n\nexport interface NodePosition {\n x: number;\n y: number;\n}\n\nexport type NodePositions = Record<string, NodePosition>;\n\n/**\n * Imperative API exposed via `ref`. Designed to give consumers the primitives\n * needed for image export (fit → snapshot → restore) without baking any\n * specific export library into this package. Methods that change the viewport\n * return Promise<boolean> matching React Flow's underlying API.\n */\nexport interface MermaidERHandle {\n /** Fit all nodes into the visible viewport. */\n fitView: (options?: FitViewOptions) => Promise<boolean>;\n /** Read the current viewport (x, y, zoom) — capture before export to restore later. */\n getViewport: () => Viewport;\n /** Restore (or set) viewport. */\n setViewport: (viewport: Viewport) => Promise<boolean>;\n /** Bounding box of all current nodes. Useful for sizing offscreen canvases. */\n getNodesBounds: () => Rect;\n /** Outer wrapper element (the div that receives `className` / `style`). */\n getWrapperElement: () => HTMLDivElement | null;\n /**\n * The internal `.react-flow__viewport` element. Typical snapshot target\n * when you want to exclude `<Controls>` and `<MiniMap>` from the image.\n */\n getViewportElement: () => HTMLElement | null;\n}\n\nexport interface MermaidERProps {\n /** Mermaid ER source. Mutually exclusive with `model`. */\n source?: string;\n /** Pre-built ER model. Takes precedence over `source`. */\n model?: ERModel;\n layout?: 'elk';\n algorithm?: LayoutAlgorithm;\n direction?: LayoutDirection;\n aspectRatio?: number;\n positions?: NodePositions;\n onPositionsChange?: (positions: NodePositions) => void;\n showColumnCheckboxes?: boolean;\n selectedColumns?: ColumnRef[];\n onColumnSelectionChange?: (selectedColumns: ColumnRef[]) => void;\n /** Enable column-to-column / card-to-card drag for manual JOINs. */\n enableManualJoins?: boolean;\n /** Existing manual joins to render alongside FK relations. */\n joins?: Join[];\n /**\n * Fired when the user finishes a connect drag. The consumer typically opens\n * a dialog to ask for join type, then appends a complete `Join` to its state.\n * `column` may be undefined when the drag landed on a default (table-center) handle.\n */\n onJoinConnect?: (source: PartialColumnRef, target: PartialColumnRef) => void;\n /**\n * Fired when the user removes a manual join via Delete or the trash icon.\n * `meta` is the opaque value attached to `Join.meta` (if any), provided so\n * the consumer can map the joinId back to its own domain object directly.\n */\n onJoinDelete?: (joinId: string, meta?: unknown) => void;\n /**\n * Fired when the user clicks an existing manual join edge. Use this to open\n * an in-app edit dialog (change join type / pivot columns) without forcing\n * the user to delete-and-recreate the connection.\n */\n onJoinClick?: (joinId: string, meta?: unknown) => void;\n /**\n * Per-edge style override for manual joins. Returning `undefined` (or\n * omitting fields) keeps the default style. Useful e.g. to color\n * auto-detected vs user-drawn joins differently.\n */\n joinStyle?: (\n join: Join,\n ) =>\n | { stroke?: string; strokeWidth?: number; strokeDasharray?: string }\n | undefined;\n /**\n * When provided, a small × appears on each table header to remove it.\n * `meta` mirrors `Table.meta` so the consumer can resolve to its own node id.\n */\n onTableRemove?: (table: string, meta?: unknown) => void;\n highlightReferencesOnHover?: boolean;\n onColumnClick?: (table: string, column: string) => void;\n onTableClick?: (table: string, meta?: unknown) => void;\n /**\n * When `showColumnCheckboxes` is enabled, also render a per-table\n * select-all checkbox in the header (with indeterminate state for partial\n * selection). Toggles all of that table's columns at once.\n */\n showSelectAllPerTable?: boolean;\n /** Override the default delete-key code(s). Default is 'Delete' (Backspace ignored to prevent accidents). */\n deleteKeyCode?: string | string[] | null;\n className?: string;\n style?: CSSProperties;\n}\n\ninterface ParseState {\n model: ERModel | null;\n error: MermaidERParseError | null;\n}\n\nfunction safeParse(source: string): ParseState {\n try {\n return { model: parseMermaidER(source), error: null };\n } catch (e) {\n if (e instanceof MermaidERParseError) {\n return { model: null, error: e };\n }\n throw e;\n }\n}\n\nfunction handleIdFor(side: 'source' | 'target', column: string | undefined): string {\n return column ? `${column}__${side}` : `__default-${side}`;\n}\n\nconst JOIN_EDGE_PREFIX = 'join:';\n\nfunction parseHandleColumn(handleId: string | null | undefined): string | undefined {\n if (!handleId) return undefined;\n if (handleId.startsWith('__default-')) return undefined;\n const m = /^(.+)__(?:source|target)$/.exec(handleId);\n return m ? m[1] : undefined;\n}\n\nfunction refKey(ref: ColumnRef): string {\n return `${ref.table}.${ref.column}`;\n}\n\nconst JOIN_TYPE_COLOR: Record<Join['type'], string> = {\n INNER: '#3b82f6',\n LEFT: '#8b5cf6',\n RIGHT: '#a855f7',\n FULL: '#ec4899',\n CROSS: '#6b7280',\n};\n\n/**\n * Bridge: `useReactFlow()` only works inside the <ReactFlow> provider, but the\n * imperative ref must be attached to MermaidER (which is the *parent* of\n * <ReactFlow>). This null-rendering child runs the hook in the right scope and\n * forwards the methods back out.\n */\nfunction HandleBridge({\n apiRef,\n wrapperRef,\n}: {\n apiRef: Ref<MermaidERHandle> | undefined;\n wrapperRef: React.RefObject<HTMLDivElement | null>;\n}) {\n const rf = useReactFlow();\n useImperativeHandle(\n apiRef,\n () => ({\n fitView: (options) => rf.fitView(options),\n getViewport: () => rf.getViewport(),\n setViewport: (viewport) => rf.setViewport(viewport),\n getNodesBounds: () => rf.getNodesBounds(rf.getNodes()),\n getWrapperElement: () => wrapperRef.current,\n getViewportElement: () =>\n wrapperRef.current?.querySelector<HTMLElement>('.react-flow__viewport') ?? null,\n }),\n [rf, wrapperRef],\n );\n return null;\n}\n\nexport const MermaidER = forwardRef<MermaidERHandle, MermaidERProps>(function MermaidER(\n props,\n ref,\n) {\n const {\n source,\n model: modelProp,\n algorithm,\n direction,\n aspectRatio,\n positions,\n onPositionsChange,\n showColumnCheckboxes,\n selectedColumns,\n onColumnSelectionChange,\n enableManualJoins,\n joins,\n onJoinConnect,\n onJoinDelete,\n onJoinClick,\n joinStyle,\n onTableRemove,\n onColumnClick,\n onTableClick,\n showSelectAllPerTable,\n deleteKeyCode = 'Delete',\n className,\n style,\n highlightReferencesOnHover = true,\n } = props;\n\n const { model, error } = useMemo<ParseState>(() => {\n if (modelProp) return { model: modelProp, error: null };\n if (source != null) return safeParse(source);\n return { model: null, error: null };\n }, [source, modelProp]);\n\n const [layout, setLayout] = useState<LayoutResult | null>(null);\n const [hoveredEdgeId, setHoveredEdgeId] = useState<string | null>(null);\n\n useEffect(() => {\n if (!model) {\n setLayout(null);\n return;\n }\n let cancelled = false;\n layoutER(model, { algorithm, direction, aspectRatio }).then((result) => {\n if (!cancelled) setLayout(result);\n });\n return () => {\n cancelled = true;\n };\n }, [model, algorithm, direction, aspectRatio]);\n\n const baseNodes = useMemo<Node[]>(() => {\n if (!layout || !model) return [];\n const tableMap = new Map(model.tables.map((t) => [t.name, t]));\n const result: Node[] = [];\n for (const n of layout.nodes) {\n const table = tableMap.get(n.id);\n // Skip stale nodes: a model update can arrive before the new layout\n // finishes; in that gap, layout may still reference a removed table.\n if (!table) continue;\n const override = positions?.[n.id];\n const data: TableNodeData = { table };\n result.push({\n id: n.id,\n type: 'table',\n position: override ?? { x: n.x, y: n.y },\n data,\n width: n.width,\n height: n.height,\n draggable: true,\n deletable: false,\n });\n }\n return result;\n // `onColumnClick` is intentionally NOT a dep — it flows via TableActionsContext\n // so a non-stable callback identity from the parent doesn't reset React Flow\n // node state (which would clobber an in-flight drag).\n }, [layout, model, positions]);\n\n const [nodes, setNodes, onNodesChange] = useNodesState<Node>(baseNodes);\n\n useEffect(() => {\n setNodes(baseNodes);\n }, [baseNodes, setNodes]);\n\n const handleNodeDragStop = useCallback(\n (_: unknown, _primary: Node, dragged: Node[]) => {\n if (!onPositionsChange) return;\n const next: NodePositions = { ...(positions ?? {}) };\n for (const n of dragged) {\n next[n.id] = { x: n.position.x, y: n.position.y };\n }\n onPositionsChange(next);\n },\n [positions, onPositionsChange],\n );\n\n const hoveredRelation = useMemo<Relation | undefined>(() => {\n if (!hoveredEdgeId || !model) return undefined;\n return model.relations.find((r) => r.id === hoveredEdgeId);\n }, [hoveredEdgeId, model]);\n\n const hoveredJoin = useMemo<Join | undefined>(() => {\n if (!hoveredEdgeId || !joins) return undefined;\n if (!hoveredEdgeId.startsWith(JOIN_EDGE_PREFIX)) return undefined;\n const id = hoveredEdgeId.slice(JOIN_EDGE_PREFIX.length);\n return joins.find((j) => j.id === id);\n }, [hoveredEdgeId, joins]);\n\n const highlightMap = useMemo<ReadonlyMap<string, ReadonlySet<string>>>(() => {\n const map = new Map<string, Set<string>>();\n if (!highlightReferencesOnHover) return map;\n\n const add = (table: string, column: string | undefined) => {\n if (!column) return;\n const set = map.get(table) ?? new Set();\n set.add(column);\n map.set(table, set);\n };\n\n if (hoveredRelation) {\n add(hoveredRelation.from, hoveredRelation.fromColumn);\n add(hoveredRelation.to, hoveredRelation.toColumn);\n }\n if (hoveredJoin) {\n add(hoveredJoin.source.table, hoveredJoin.source.column);\n add(hoveredJoin.target.table, hoveredJoin.target.column);\n }\n return map;\n }, [hoveredRelation, hoveredJoin, highlightReferencesOnHover]);\n\n const selectionSet = useMemo<ReadonlySet<string>>(() => {\n return new Set((selectedColumns ?? []).map(refKey));\n }, [selectedColumns]);\n\n const handleColumnSelectToggle = useCallback(\n (table: string, column: string, checked: boolean) => {\n if (!onColumnSelectionChange) return;\n const list = selectedColumns ?? [];\n if (checked) {\n if (list.some((r) => r.table === table && r.column === column)) return;\n onColumnSelectionChange([...list, { table, column }]);\n } else {\n onColumnSelectionChange(\n list.filter((r) => !(r.table === table && r.column === column)),\n );\n }\n },\n [selectedColumns, onColumnSelectionChange],\n );\n\n const handleSelectAllToggle = useCallback(\n (table: string, columns: string[], nextState: boolean) => {\n if (!onColumnSelectionChange) return;\n const list = selectedColumns ?? [];\n if (nextState) {\n const existing = new Set(list.map(refKey));\n const additions: ColumnRef[] = [];\n for (const c of columns) {\n if (!existing.has(`${table}.${c}`)) additions.push({ table, column: c });\n }\n if (additions.length === 0) return;\n onColumnSelectionChange([...list, ...additions]);\n } else {\n const drop = new Set(columns);\n onColumnSelectionChange(\n list.filter((r) => !(r.table === table && drop.has(r.column))),\n );\n }\n },\n [selectedColumns, onColumnSelectionChange],\n );\n\n const selectionContext = useMemo<ColumnSelectionContextValue>(\n () => ({\n enabled: showColumnCheckboxes ?? false,\n showSelectAll: showSelectAllPerTable ?? false,\n selected: selectionSet,\n onToggle: handleColumnSelectToggle,\n onToggleAll: handleSelectAllToggle,\n }),\n [\n showColumnCheckboxes,\n showSelectAllPerTable,\n selectionSet,\n handleColumnSelectToggle,\n handleSelectAllToggle,\n ],\n );\n\n const edges = useMemo<Edge[]>(() => {\n if (!layout || !model) return [];\n const tableSet = new Set(model.tables.map((t) => t.name));\n const relMap = new Map(model.relations.map((r) => [r.id, r]));\n\n const fkEdges: Edge[] = [];\n for (const e of layout.edges) {\n // Skip stale edges referencing tables removed since the layout was computed.\n if (!tableSet.has(e.source) || !tableSet.has(e.target)) continue;\n const rel = relMap.get(e.id);\n const isHovered = e.id === hoveredEdgeId;\n fkEdges.push({\n id: e.id,\n source: e.source,\n target: e.target,\n sourceHandle: handleIdFor('source', rel?.fromColumn),\n targetHandle: handleIdFor('target', rel?.toColumn),\n type: 'smoothstep',\n animated: isHovered,\n deletable: false,\n style: {\n stroke: isHovered ? '#f59e0b' : '#9ca3af',\n strokeWidth: isHovered ? 2 : 1.5,\n },\n label: rel?.label,\n labelStyle: { fontSize: 10, fill: '#6b7280' },\n labelBgStyle: { fill: '#fff', fillOpacity: 0.85 },\n labelBgPadding: [4, 2] as [number, number],\n labelBgBorderRadius: 3,\n });\n }\n\n const joinEdges: Edge[] = [];\n for (const j of joins ?? []) {\n if (!tableSet.has(j.source.table) || !tableSet.has(j.target.table)) continue;\n const edgeId = `${JOIN_EDGE_PREFIX}${j.id}`;\n const isHovered = edgeId === hoveredEdgeId;\n const styleOverride = joinStyle?.(j);\n const color = styleOverride?.stroke ?? JOIN_TYPE_COLOR[j.type] ?? '#3b82f6';\n const data: JoinEdgeData = {\n type: j.type,\n color,\n strokeWidth: styleOverride?.strokeWidth,\n strokeDasharray: styleOverride?.strokeDasharray,\n hovered: isHovered,\n onDelete: onJoinDelete ? () => onJoinDelete(j.id, j.meta) : undefined,\n };\n joinEdges.push({\n id: edgeId,\n source: j.source.table,\n target: j.target.table,\n sourceHandle: handleIdFor('source', j.source.column),\n targetHandle: handleIdFor('target', j.target.column),\n type: 'joinEdge',\n deletable: true,\n data: data as unknown as Record<string, unknown>,\n });\n }\n\n return [...fkEdges, ...joinEdges];\n }, [layout, model, joins, hoveredEdgeId, onJoinDelete, joinStyle]);\n\n const handleConnect = useCallback(\n (conn: Connection) => {\n if (!onJoinConnect) return;\n if (!conn.source || !conn.target) return;\n onJoinConnect(\n { table: conn.source, column: parseHandleColumn(conn.sourceHandle) },\n { table: conn.target, column: parseHandleColumn(conn.targetHandle) },\n );\n },\n [onJoinConnect],\n );\n\n const handleEdgesDelete = useCallback(\n (deleted: Edge[]) => {\n if (!onJoinDelete) return;\n for (const e of deleted) {\n if (!e.id.startsWith(JOIN_EDGE_PREFIX)) continue;\n const joinId = e.id.slice(JOIN_EDGE_PREFIX.length);\n const join = joins?.find((j) => j.id === joinId);\n onJoinDelete(joinId, join?.meta);\n }\n },\n [onJoinDelete, joins],\n );\n\n const handleEdgeClick = useCallback(\n (_: unknown, edge: Edge) => {\n if (!onJoinClick) return;\n if (!edge.id.startsWith(JOIN_EDGE_PREFIX)) return;\n const joinId = edge.id.slice(JOIN_EDGE_PREFIX.length);\n const join = joins?.find((j) => j.id === joinId);\n onJoinClick(joinId, join?.meta);\n },\n [onJoinClick, joins],\n );\n\n const connectModeOn = !!enableManualJoins;\n const tableActions = useMemo<TableActionsContextValue>(\n () => ({ onTableRemove, onColumnClick }),\n [onTableRemove, onColumnClick],\n );\n\n const wrapperRef = useRef<HTMLDivElement>(null);\n\n return (\n <div\n ref={wrapperRef}\n className={className}\n style={{ width: '100%', height: '100%', position: 'relative', ...style }}\n >\n {error && (\n <div\n style={{\n position: 'absolute',\n top: 8,\n left: 8,\n right: 8,\n zIndex: 10,\n padding: '8px 12px',\n background: '#fef2f2',\n border: '1px solid #fecaca',\n borderRadius: 6,\n color: '#991b1b',\n fontFamily: 'ui-monospace, SFMono-Regular, Consolas, monospace',\n fontSize: 12,\n whiteSpace: 'pre-wrap',\n }}\n >\n {error.message}\n </div>\n )}\n {!error && !layout && (\n <div\n style={{\n position: 'absolute',\n inset: 0,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n color: '#9ca3af',\n fontSize: 13,\n }}\n >\n Computing layout…\n </div>\n )}\n <HighlightContext.Provider value={highlightMap}>\n <ColumnSelectionContext.Provider value={selectionContext}>\n <ConnectModeContext.Provider value={connectModeOn}>\n <TableActionsContext.Provider value={tableActions}>\n <ReactFlow\n nodes={nodes}\n edges={edges}\n nodeTypes={nodeTypes}\n edgeTypes={edgeTypes}\n fitView\n onNodesChange={onNodesChange}\n onNodeDragStop={handleNodeDragStop}\n onNodeClick={\n onTableClick\n ? (_, node) => {\n const meta = (node.data as TableNodeData | undefined)?.table?.meta;\n onTableClick(node.id, meta);\n }\n : undefined\n }\n onEdgeMouseEnter={(_, edge) => setHoveredEdgeId(edge.id)}\n onEdgeMouseLeave={() => setHoveredEdgeId(null)}\n onEdgeClick={onJoinClick ? handleEdgeClick : undefined}\n onConnect={handleConnect}\n onEdgesDelete={handleEdgesDelete}\n nodesDraggable\n nodesConnectable={connectModeOn}\n elementsSelectable\n deleteKeyCode={deleteKeyCode}\n minZoom={0.1}\n maxZoom={4}\n >\n <Background />\n <Controls />\n <MiniMap pannable zoomable />\n <HandleBridge apiRef={ref} wrapperRef={wrapperRef} />\n </ReactFlow>\n </TableActionsContext.Provider>\n </ConnectModeContext.Provider>\n </ColumnSelectionContext.Provider>\n </HighlightContext.Provider>\n </div>\n );\n});\n"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { MermaidER } from './components/MermaidER';
|
|
2
|
-
export type { MermaidERProps, NodePosition, NodePositions, } from './components/MermaidER';
|
|
2
|
+
export type { MermaidERHandle, MermaidERProps, NodePosition, NodePositions, } from './components/MermaidER';
|
|
3
3
|
export type { TableNodeData } from './components/TableNode';
|
|
4
4
|
export type { JoinEdgeData } from './components/JoinEdge';
|
|
5
5
|
export * from './core';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,YAAY,EACV,cAAc,EACd,YAAY,EACZ,aAAa,GACd,MAAM,wBAAwB,CAAC;AAKhC,YAAY,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC5D,YAAY,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC1D,cAAc,QAAQ,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,YAAY,EACV,eAAe,EACf,cAAc,EACd,YAAY,EACZ,aAAa,GACd,MAAM,wBAAwB,CAAC;AAKhC,YAAY,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC5D,YAAY,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC1D,cAAc,QAAQ,CAAC"}
|