@erd-studio/renderer 0.1.3 → 0.3.0
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/CHANGELOG.md +26 -0
- package/README.md +9 -9
- package/dist/{chunk-H2ACJRPZ.js → chunk-HWA32XG5.js} +146 -50
- package/dist/editor.js +9 -9
- package/dist/index.js +3 -3
- package/dist/styles.css +70 -0
- package/dist/types/ErdCanvas.d.ts +4 -4
- package/dist/types/canvas/useCanvasGraph.d.ts +4 -4
- package/dist/types/components/DetailPanel/AliasEditor.d.ts +1 -1
- package/dist/types/components/DetailPanel/ColumnEditor.d.ts +2 -2
- package/dist/types/components/DetailPanel/ModelRationale.d.ts +5 -5
- package/dist/types/components/DetailPanel/RoleEditor.d.ts +3 -3
- package/dist/types/components/Graph/ColumnTooltip.d.ts +1 -1
- package/dist/types/components/Graph/ModelNode.d.ts +4 -4
- package/dist/types/components/Legend/Legend.d.ts +1 -1
- package/dist/types/components/common/ColumnRowEditor.d.ts +2 -2
- package/dist/types/editor.d.ts +2 -2
- package/dist/types/hooks/useColumnReorder.d.ts +1 -1
- package/dist/types/index.d.ts +3 -3
- package/dist/types/lib/badgeLabels.d.ts +1 -1
- package/dist/types/lib/dragHandleSides.d.ts +2 -2
- package/dist/types/lib/graphTransformer.d.ts +7 -7
- package/dist/types/lib/modelLabels.d.ts +3 -3
- package/dist/types/lib/nodeOverlays.d.ts +4 -4
- package/dist/types/lib/nodeSizing.d.ts +6 -6
- package/dist/types/store/editorStore.d.ts +8 -8
- package/dist/types/types/graph.d.ts +22 -12
- package/package.json +3 -2
package/dist/editor.js
CHANGED
|
@@ -18,7 +18,6 @@ import {
|
|
|
18
18
|
KeyBadge,
|
|
19
19
|
KeyBadgeGroup,
|
|
20
20
|
Legend,
|
|
21
|
-
ModelNode,
|
|
22
21
|
NOOP_CANVAS_HOST,
|
|
23
22
|
SCD_BADGE,
|
|
24
23
|
SCD_TITLE,
|
|
@@ -27,17 +26,18 @@ import {
|
|
|
27
26
|
SOURCE_ORDER,
|
|
28
27
|
SOURCE_PHRASE,
|
|
29
28
|
STAGE_HEX,
|
|
29
|
+
TableNode,
|
|
30
30
|
applyNodeOverlays,
|
|
31
31
|
canvasEdgeTypes,
|
|
32
32
|
canvasNodeTypes,
|
|
33
33
|
columnPairs,
|
|
34
|
-
|
|
34
|
+
computeTableLabels,
|
|
35
35
|
diagramExportFileName,
|
|
36
36
|
edgeHoverText,
|
|
37
37
|
exportDiagram,
|
|
38
38
|
foldComposites,
|
|
39
39
|
getDataTypeColor,
|
|
40
|
-
|
|
40
|
+
matchesTableSearch,
|
|
41
41
|
nodeRect,
|
|
42
42
|
pickHandleSides,
|
|
43
43
|
relationshipDisplayKey,
|
|
@@ -47,7 +47,7 @@ import {
|
|
|
47
47
|
swapCardinality,
|
|
48
48
|
toDbml,
|
|
49
49
|
toMermaid,
|
|
50
|
-
|
|
50
|
+
transformSubjectArea,
|
|
51
51
|
useCanvasGraph,
|
|
52
52
|
useCanvasHost,
|
|
53
53
|
useColumnReorder,
|
|
@@ -55,7 +55,7 @@ import {
|
|
|
55
55
|
useIsViewer,
|
|
56
56
|
useLongPressDrag,
|
|
57
57
|
useSend
|
|
58
|
-
} from "./chunk-
|
|
58
|
+
} from "./chunk-HWA32XG5.js";
|
|
59
59
|
import "./chunk-QZGU5NZH.js";
|
|
60
60
|
import "./chunk-6XQXDZ4R.js";
|
|
61
61
|
import {
|
|
@@ -97,7 +97,6 @@ export {
|
|
|
97
97
|
KeyBadge,
|
|
98
98
|
KeyBadgeGroup,
|
|
99
99
|
Legend,
|
|
100
|
-
ModelNode,
|
|
101
100
|
NODE_THRESHOLD,
|
|
102
101
|
NODE_WIDTH,
|
|
103
102
|
NOOP_CANVAS_HOST,
|
|
@@ -108,11 +107,12 @@ export {
|
|
|
108
107
|
SOURCE_ORDER,
|
|
109
108
|
SOURCE_PHRASE,
|
|
110
109
|
STAGE_HEX,
|
|
110
|
+
TableNode,
|
|
111
111
|
applyNodeOverlays,
|
|
112
112
|
canvasEdgeTypes,
|
|
113
113
|
canvasNodeTypes,
|
|
114
114
|
columnPairs,
|
|
115
|
-
|
|
115
|
+
computeTableLabels,
|
|
116
116
|
countVisibleColumnRows,
|
|
117
117
|
createCanvasSlice,
|
|
118
118
|
createCanvasStore,
|
|
@@ -123,7 +123,7 @@ export {
|
|
|
123
123
|
exportDiagram,
|
|
124
124
|
foldComposites,
|
|
125
125
|
getDataTypeColor,
|
|
126
|
-
|
|
126
|
+
matchesTableSearch,
|
|
127
127
|
nodeRect,
|
|
128
128
|
pickHandleSides,
|
|
129
129
|
relationshipDisplayKey,
|
|
@@ -134,7 +134,7 @@ export {
|
|
|
134
134
|
swapCardinality,
|
|
135
135
|
toDbml,
|
|
136
136
|
toMermaid,
|
|
137
|
-
|
|
137
|
+
transformSubjectArea,
|
|
138
138
|
useCanvasGraph,
|
|
139
139
|
useCanvasHost,
|
|
140
140
|
useColumnExpansion,
|
package/dist/index.js
CHANGED
|
@@ -9,8 +9,8 @@ import {
|
|
|
9
9
|
repickHandleSides,
|
|
10
10
|
toDbml,
|
|
11
11
|
toMermaid,
|
|
12
|
-
|
|
13
|
-
} from "./chunk-
|
|
12
|
+
transformSubjectArea
|
|
13
|
+
} from "./chunk-HWA32XG5.js";
|
|
14
14
|
import "./chunk-DUQ2TTQH.js";
|
|
15
15
|
import "./chunk-WOTSQZCQ.js";
|
|
16
16
|
export {
|
|
@@ -24,5 +24,5 @@ export {
|
|
|
24
24
|
repickHandleSides,
|
|
25
25
|
toDbml,
|
|
26
26
|
toMermaid,
|
|
27
|
-
|
|
27
|
+
transformSubjectArea
|
|
28
28
|
};
|
package/dist/styles.css
CHANGED
|
@@ -693,6 +693,20 @@
|
|
|
693
693
|
color: var(--warning-fg);
|
|
694
694
|
text-align: center;
|
|
695
695
|
}
|
|
696
|
+
.model-node__load-warning {
|
|
697
|
+
display: flex;
|
|
698
|
+
align-items: center;
|
|
699
|
+
gap: 8px;
|
|
700
|
+
padding: 4px 10px;
|
|
701
|
+
background: var(--warning-bg);
|
|
702
|
+
color: var(--warning-fg);
|
|
703
|
+
border-bottom: 1px solid var(--warning-fg);
|
|
704
|
+
}
|
|
705
|
+
.model-node__load-warning-text {
|
|
706
|
+
flex: 1;
|
|
707
|
+
font-size: 11px;
|
|
708
|
+
line-height: 1.4;
|
|
709
|
+
}
|
|
696
710
|
.model-node__load-error-text {
|
|
697
711
|
font-size: 11px;
|
|
698
712
|
line-height: 1.4;
|
|
@@ -904,6 +918,45 @@
|
|
|
904
918
|
background: var(--button-bg);
|
|
905
919
|
color: var(--button-fg);
|
|
906
920
|
}
|
|
921
|
+
.fk-edge__backwards {
|
|
922
|
+
position: absolute;
|
|
923
|
+
display: flex;
|
|
924
|
+
align-items: center;
|
|
925
|
+
gap: 4px;
|
|
926
|
+
pointer-events: all;
|
|
927
|
+
}
|
|
928
|
+
.fk-edge__backwards--dimmed {
|
|
929
|
+
opacity: 0.25;
|
|
930
|
+
}
|
|
931
|
+
.fk-edge__backwards-icon {
|
|
932
|
+
display: flex;
|
|
933
|
+
align-items: center;
|
|
934
|
+
justify-content: center;
|
|
935
|
+
width: 18px;
|
|
936
|
+
height: 18px;
|
|
937
|
+
border-radius: 50%;
|
|
938
|
+
background: var(--warning-bg);
|
|
939
|
+
color: var(--warning-fg);
|
|
940
|
+
font-size: 12px;
|
|
941
|
+
line-height: 1;
|
|
942
|
+
cursor: help;
|
|
943
|
+
}
|
|
944
|
+
.fk-edge__backwards-btn {
|
|
945
|
+
padding: 2px 6px;
|
|
946
|
+
border: 1px solid var(--warning-fg);
|
|
947
|
+
border-radius: 4px;
|
|
948
|
+
background: var(--panel-bg);
|
|
949
|
+
color: var(--editor-fg);
|
|
950
|
+
font-size: 11px;
|
|
951
|
+
line-height: 1.3;
|
|
952
|
+
white-space: nowrap;
|
|
953
|
+
cursor: pointer;
|
|
954
|
+
}
|
|
955
|
+
.fk-edge__backwards-btn:hover {
|
|
956
|
+
border-color: var(--focus-border);
|
|
957
|
+
background: var(--button-bg);
|
|
958
|
+
color: var(--button-fg);
|
|
959
|
+
}
|
|
907
960
|
|
|
908
961
|
/* src/components/Graph/AnnotationNode.css */
|
|
909
962
|
.annotation-node {
|
|
@@ -2816,6 +2869,23 @@ body[data-vscode-theme-kind=vscode-high-contrast] .annotation-node__link-badge {
|
|
|
2816
2869
|
padding: 3px 8px;
|
|
2817
2870
|
font-size: 10px;
|
|
2818
2871
|
}
|
|
2872
|
+
.detail-panel__rel-backwards {
|
|
2873
|
+
flex-shrink: 0;
|
|
2874
|
+
padding: 1px 6px;
|
|
2875
|
+
border: 1px solid var(--warning-fg);
|
|
2876
|
+
border-radius: 3px;
|
|
2877
|
+
background: var(--warning-bg);
|
|
2878
|
+
color: var(--warning-fg);
|
|
2879
|
+
font-size: 11px;
|
|
2880
|
+
line-height: 1.4;
|
|
2881
|
+
white-space: nowrap;
|
|
2882
|
+
cursor: pointer;
|
|
2883
|
+
}
|
|
2884
|
+
.detail-panel__rel-backwards:hover {
|
|
2885
|
+
border-color: var(--focus-border);
|
|
2886
|
+
background: var(--button-bg);
|
|
2887
|
+
color: var(--button-fg);
|
|
2888
|
+
}
|
|
2819
2889
|
|
|
2820
2890
|
/* src/components/Legend/Legend.css */
|
|
2821
2891
|
.legend-toggle {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* ErdCanvas — the diagram as a self-contained, read-only React component.
|
|
3
3
|
*
|
|
4
|
-
* Renders a `
|
|
4
|
+
* Renders a `DisplaySubjectArea` the way the VS Code extension's canvas shows a
|
|
5
5
|
* read-only domain: model nodes, FK edges, annotations, the minimap, the
|
|
6
6
|
* detail panel a click on a model opens, and the legend. There are no editing
|
|
7
7
|
* affordances (the canvas runs in viewer mode) and nothing is ever sent
|
|
@@ -22,10 +22,10 @@
|
|
|
22
22
|
* keeping its React Flow configuration.
|
|
23
23
|
*/
|
|
24
24
|
import { type CSSProperties } from 'react';
|
|
25
|
-
import type {
|
|
25
|
+
import type { DisplaySubjectArea } from '@erd-studio/core';
|
|
26
26
|
export interface ErdCanvasProps {
|
|
27
27
|
/** The domain to render. It is shown read-only whatever its `readOnly` flag says. */
|
|
28
|
-
domain:
|
|
28
|
+
domain: DisplaySubjectArea;
|
|
29
29
|
/** Let readers drag model and annotation nodes. Moves are never saved. Default false. */
|
|
30
30
|
nodesDraggable?: boolean;
|
|
31
31
|
/**
|
|
@@ -50,5 +50,5 @@ export interface ErdCanvasHandle {
|
|
|
50
50
|
* model's columns, each column's data type). Objects with nothing missing are
|
|
51
51
|
* reused as they are.
|
|
52
52
|
*/
|
|
53
|
-
export declare function
|
|
53
|
+
export declare function toRenderableSubjectArea(domain: DisplaySubjectArea): DisplaySubjectArea;
|
|
54
54
|
export declare const ErdCanvas: import("react").ForwardRefExoticComponent<ErdCanvasProps & import("react").RefAttributes<ErdCanvasHandle>>;
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
*/
|
|
15
15
|
import type { OnSelectionChangeFunc } from '@xyflow/react';
|
|
16
16
|
import type { DiscrepancyReport } from '@erd-studio/core';
|
|
17
|
-
import type {
|
|
17
|
+
import type { TableFlowNode, FkFlowEdge, AnnotationFlowNode, AnnotationFlowEdge } from '../types/graph.js';
|
|
18
18
|
export interface UseCanvasGraphOptions {
|
|
19
19
|
/** Whether the cross-stage discrepancy overlay is shown. */
|
|
20
20
|
discrepancyVisible?: boolean;
|
|
@@ -24,12 +24,12 @@ export interface UseCanvasGraphOptions {
|
|
|
24
24
|
* Called with the rebuilt nodes and edges each time the transform effect
|
|
25
25
|
* runs, just before they are written to the store.
|
|
26
26
|
*/
|
|
27
|
-
onTransformed?: (nodes: (
|
|
27
|
+
onTransformed?: (nodes: (TableFlowNode | AnnotationFlowNode)[], edges: (FkFlowEdge | AnnotationFlowEdge)[]) => void;
|
|
28
28
|
}
|
|
29
29
|
export interface UseCanvasGraphResult {
|
|
30
|
-
nodes: (
|
|
30
|
+
nodes: (TableFlowNode | AnnotationFlowNode)[];
|
|
31
31
|
edges: (FkFlowEdge | AnnotationFlowEdge)[];
|
|
32
|
-
onNodeClick: (event: React.MouseEvent, node:
|
|
32
|
+
onNodeClick: (event: React.MouseEvent, node: TableFlowNode | AnnotationFlowNode) => void;
|
|
33
33
|
onEdgeClick: (event: React.MouseEvent, edge: FkFlowEdge | AnnotationFlowEdge) => void;
|
|
34
34
|
onPaneClick: () => void;
|
|
35
35
|
onSelectionChange: OnSelectionChangeFunc;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* AliasEditor — the "
|
|
2
|
+
* AliasEditor — the "Warehouse name" row of the detail panel's metadata.
|
|
3
3
|
*
|
|
4
4
|
* A model's name is its identity; its alias is the table dbt builds it as.
|
|
5
5
|
* Setting one is how two layers can each have a `date` table: the models are
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* Uses ColumnRowEditor for consistent column row rendering.
|
|
7
7
|
*/
|
|
8
8
|
import type { DisplayColumn } from '@erd-studio/core';
|
|
9
|
-
import type {
|
|
9
|
+
import type { TableRole } from '@erd-studio/core';
|
|
10
10
|
import './ColumnEditor.css';
|
|
11
11
|
export interface ColumnEditorProps {
|
|
12
12
|
modelName: string;
|
|
@@ -14,6 +14,6 @@ export interface ColumnEditorProps {
|
|
|
14
14
|
/** Whether this model/stage is read-only. */
|
|
15
15
|
readOnly?: boolean;
|
|
16
16
|
/** Parent model's role — passed to column rows for conditional SCD/additive dropdowns. */
|
|
17
|
-
modelRole?:
|
|
17
|
+
modelRole?: TableRole;
|
|
18
18
|
}
|
|
19
19
|
export declare function ColumnEditor({ modelName, columns, readOnly, modelRole }: ColumnEditorProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* TableRationale — collapsible section for all design rationale fields.
|
|
3
3
|
*
|
|
4
4
|
* Renders a clickable "Design Rationale" heading that toggles the body.
|
|
5
5
|
* Each field has its own add/edit/read lifecycle and sends independent
|
|
@@ -14,14 +14,14 @@
|
|
|
14
14
|
* When no rationale exists and no conditional fields are visible,
|
|
15
15
|
* shows a dashed "Add Rationale" button that opens the section.
|
|
16
16
|
*/
|
|
17
|
-
import type { Rationale,
|
|
17
|
+
import type { Rationale, TableRole } from '@erd-studio/core';
|
|
18
18
|
/** Whether any rationale field has text. */
|
|
19
19
|
export declare function hasRationaleContent(rationale: Rationale | undefined): boolean;
|
|
20
|
-
interface
|
|
20
|
+
interface TableRationaleProps {
|
|
21
21
|
modelName: string;
|
|
22
22
|
rationale?: Rationale;
|
|
23
|
-
modelRole?:
|
|
23
|
+
modelRole?: TableRole;
|
|
24
24
|
grain?: string;
|
|
25
25
|
}
|
|
26
|
-
export declare function
|
|
26
|
+
export declare function TableRationale({ modelName, rationale, modelRole, grain }: TableRationaleProps): import("react/jsx-runtime").JSX.Element | null;
|
|
27
27
|
export {};
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* RoleEditor — always-visible dropdown for setting a model's role.
|
|
3
3
|
*
|
|
4
|
-
* Displays a native <select> element with all
|
|
4
|
+
* Displays a native <select> element with all TableRole options.
|
|
5
5
|
* When "No role" is selected, the modelRole key is removed from JSON.
|
|
6
6
|
*/
|
|
7
|
-
import type {
|
|
7
|
+
import type { TableRole } from '@erd-studio/core';
|
|
8
8
|
interface RoleEditorProps {
|
|
9
9
|
modelName: string;
|
|
10
|
-
modelRole?:
|
|
10
|
+
modelRole?: TableRole;
|
|
11
11
|
}
|
|
12
12
|
export declare function RoleEditor({ modelName, modelRole }: RoleEditorProps): import("react/jsx-runtime").JSX.Element;
|
|
13
13
|
export {};
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* ColumnTooltip — hover tooltip showing column details on the canvas.
|
|
3
3
|
*
|
|
4
4
|
* Renders via a React Portal to document.body so it is never clipped by
|
|
5
|
-
* the
|
|
5
|
+
* the TableNode's `overflow: hidden`. Positioned with `position: fixed`
|
|
6
6
|
* using the anchor element's bounding rect. Automatically flips below
|
|
7
7
|
* the row if there isn't enough space above.
|
|
8
8
|
*
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* TableNode — custom React Flow node for displaying a semantic model card.
|
|
3
3
|
*
|
|
4
4
|
* Shows model name with a layer badge, a list of columns with PK/FK
|
|
5
5
|
* indicators and data types, and a footer with the total column count.
|
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
* 3. Release to open the relationship dialog with prefilled data
|
|
15
15
|
*/
|
|
16
16
|
import { type NodeProps } from '@xyflow/react';
|
|
17
|
-
import type {
|
|
17
|
+
import type { TableFlowNode } from '../../types/graph.js';
|
|
18
18
|
import './ModelNode.css';
|
|
19
|
-
declare function
|
|
20
|
-
export declare const
|
|
19
|
+
declare function TableNodeComponent({ data, selected }: NodeProps<TableFlowNode>): import("react/jsx-runtime").JSX.Element;
|
|
20
|
+
export declare const TableNode: import("react").MemoExoticComponent<typeof TableNodeComponent>;
|
|
21
21
|
export {};
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Shows stage colours, relationship types, cardinality notation, the node
|
|
5
5
|
* header badges (schema abbreviation and physical provenance chips) and the
|
|
6
6
|
* column badges. The badge vocabulary is imported from lib/badgeLabels so the
|
|
7
|
-
* legend cannot fall out of step with what
|
|
7
|
+
* legend cannot fall out of step with what TableNode actually renders. Positioned in the bottom-left corner, collapsible
|
|
8
8
|
* to a `?` icon button.
|
|
9
9
|
*/
|
|
10
10
|
import './Legend.css';
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* Uses useFocusWithinRow hook for robust focus tracking that eliminates
|
|
8
8
|
* flicker when switching between fields within the same row.
|
|
9
9
|
*/
|
|
10
|
-
import type {
|
|
10
|
+
import type { TableRole } from '@erd-studio/core';
|
|
11
11
|
import type { UpdateColumnPayloadColumn } from '@erd-studio/core';
|
|
12
12
|
import './ColumnRowEditor.css';
|
|
13
13
|
export interface ColumnRowEditorColumn {
|
|
@@ -52,7 +52,7 @@ export interface ColumnRowEditorProps {
|
|
|
52
52
|
/** Show warning if multiple PKs exist in model. */
|
|
53
53
|
showMultiplePKWarning?: boolean;
|
|
54
54
|
/** Parent model's role — determines whether SCD/additive dropdowns are shown. */
|
|
55
|
-
modelRole?:
|
|
55
|
+
modelRole?: TableRole;
|
|
56
56
|
/** Whether the description area is expanded. */
|
|
57
57
|
expanded?: boolean;
|
|
58
58
|
/** Callback when the expand/collapse chevron is clicked. */
|
package/dist/types/editor.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export { NOOP_CANVAS_HOST, CanvasEnvironmentProvider, useCanvasHost, useSend, us
|
|
|
5
5
|
export { useCanvasGraph } from './canvas/useCanvasGraph.js';
|
|
6
6
|
export { CanvasBackdrop, ANNOTATION_MINIMAP_COLORS } from './canvas/CanvasBackdrop.js';
|
|
7
7
|
export { canvasNodeTypes, canvasEdgeTypes } from './canvas/flowTypes.js';
|
|
8
|
-
export {
|
|
8
|
+
export { TableNode } from './components/Graph/ModelNode.js';
|
|
9
9
|
export { FkEdge } from './components/Graph/FkEdge.js';
|
|
10
10
|
export { AnnotationNode } from './components/Graph/AnnotationNode.js';
|
|
11
11
|
export { AnnotationEdge } from './components/Graph/AnnotationEdge.js';
|
|
@@ -25,5 +25,5 @@ export * from './lib/dataTypeColors.js';
|
|
|
25
25
|
export * from './lib/badgeLabels.js';
|
|
26
26
|
export { swapCardinality } from './lib/cardinalityUtils.js';
|
|
27
27
|
export { columnPairs, foldComposites, relationshipDisplayKey, relationshipEdgeId } from './lib/relationshipDisplayKey.js';
|
|
28
|
-
export {
|
|
28
|
+
export { computeTableLabels, matchesTableSearch, type LabelledTable } from './lib/modelLabels.js';
|
|
29
29
|
export { ANNOTATION_COLORS } from './lib/annotationColors.js';
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Uses imperative mouse events (matching the existing useLongPressDrag pattern).
|
|
5
5
|
* Returns drag state, handle props for each row, and the optimistic display order.
|
|
6
6
|
*
|
|
7
|
-
* Works in both DetailPanel (ColumnRowEditor rows) and
|
|
7
|
+
* Works in both DetailPanel (ColumnRowEditor rows) and TableNode (ColumnRow rows)
|
|
8
8
|
* by accepting configurable CSS selectors for the container and row elements.
|
|
9
9
|
*/
|
|
10
10
|
interface Column {
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { ErdCanvas, type ErdCanvasProps, type ErdCanvasHandle } from './ErdCanvas.js';
|
|
2
|
-
export {
|
|
2
|
+
export { transformSubjectArea, pickHandleSides, type TransformResult, type TransformOptions, type NodeRect, type NodeDimensions, } from './lib/graphTransformer.js';
|
|
3
3
|
export { repickHandleSides, nodeRect } from './lib/dragHandleSides.js';
|
|
4
|
-
export type {
|
|
4
|
+
export type { DisplaySubjectArea, DisplayTable, DisplayColumn, DisplayRelationship, PhysicalColumnSource, PhysicalProvenance, Annotation, AnnotationColor, Cardinality, Layer, TableRole, NodePosition, Rationale, Stage, ViewConfig, LayerConfig, } from '@erd-studio/core';
|
|
5
5
|
export { toMermaid, toDbml, exportDiagram, diagramExportFileName, DIAGRAM_EXPORT_FORMATS, DIAGRAM_EXPORT_FILE_EXTENSIONS, type DiagramExportFormat, } from '@erd-studio/core';
|
|
6
|
-
export type {
|
|
6
|
+
export type { TableFlowNode, TableNodeData, FkFlowEdge, FkEdgeData, AnnotationFlowNode, AnnotationFlowEdge, ColumnDisplay, } from './types/graph.js';
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* badgeLabels — the abbreviations and symbols the canvas stamps on nodes and
|
|
3
3
|
* columns, and the prose that decodes them.
|
|
4
4
|
*
|
|
5
|
-
* These live here rather than in
|
|
5
|
+
* These live here rather than in TableNode because the Legend explains exactly
|
|
6
6
|
* this vocabulary. Two copies of "WH means the warehouse catalog" is two things
|
|
7
7
|
* to keep in step, and the legend is precisely the copy nobody edits when the
|
|
8
8
|
* node changes. Both ends import these maps, so a new source or a renamed chip
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Handle sides for edges after nodes are moved on the canvas.
|
|
3
3
|
*
|
|
4
|
-
* `
|
|
4
|
+
* `transformSubjectArea` chooses the handle side at each end of an edge from the
|
|
5
5
|
* saved positions: `pickHandleSides` compares the two node rectangles, and a
|
|
6
6
|
* self-referencing relationship always uses the top (source) and right
|
|
7
7
|
* (target) handles. A canvas that lets nodes be dragged without rebuilding the
|
|
8
8
|
* domain has to make that choice again for the edges on the dragged nodes, or
|
|
9
9
|
* those edges stay attached to the side that faced the old position.
|
|
10
10
|
*
|
|
11
|
-
* The rectangles follow `
|
|
11
|
+
* The rectangles follow `transformSubjectArea` too: a node's size is its measured
|
|
12
12
|
* size when React Flow has one, otherwise the model-node estimate from
|
|
13
13
|
* `resolveNodeDimensions`, or an annotation's own (or default) size.
|
|
14
14
|
*/
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Graph transformer — converts a
|
|
2
|
+
* Graph transformer — converts a DisplaySubjectArea into React Flow nodes and edges.
|
|
3
3
|
*
|
|
4
4
|
* This is a pure function with no side effects, making it easy to unit test.
|
|
5
5
|
* It handles:
|
|
6
|
-
* 1. Mapping each
|
|
6
|
+
* 1. Mapping each DisplayTable → TableFlowNode (with position + columns)
|
|
7
7
|
* 2. Mapping each DisplayRelationship → FkFlowEdge (with handle side selection)
|
|
8
8
|
* 3. Selecting optimal handle sides based on relative node positions
|
|
9
9
|
* 4. Injecting discrepancy data and ghost nodes/edges when a comparison report is active
|
|
10
10
|
*/
|
|
11
|
-
import type {
|
|
11
|
+
import type { DisplaySubjectArea } from '@erd-studio/core';
|
|
12
12
|
import type { DiscrepancyReport } from '@erd-studio/core';
|
|
13
|
-
import type {
|
|
13
|
+
import type { TableFlowNode, FkFlowEdge, AnnotationFlowNode, AnnotationFlowEdge } from '../types/graph.js';
|
|
14
14
|
export interface TransformResult {
|
|
15
|
-
nodes: (
|
|
15
|
+
nodes: (TableFlowNode | AnnotationFlowNode)[];
|
|
16
16
|
edges: (FkFlowEdge | AnnotationFlowEdge)[];
|
|
17
17
|
}
|
|
18
18
|
/** Width/height of a rendered node, in canvas pixels. */
|
|
@@ -55,11 +55,11 @@ export declare function pickHandleSides(source: NodeRect, target: NodeRect): {
|
|
|
55
55
|
targetSide: Side;
|
|
56
56
|
};
|
|
57
57
|
/**
|
|
58
|
-
* Convert a
|
|
58
|
+
* Convert a DisplaySubjectArea into React Flow nodes and edges.
|
|
59
59
|
*
|
|
60
60
|
* @param domain — the display domain from extension host
|
|
61
61
|
* @param options — optional discrepancy report and ghost positions
|
|
62
62
|
* @returns nodes and edges ready for React Flow's `<ReactFlow>` component
|
|
63
63
|
*/
|
|
64
|
-
export declare function
|
|
64
|
+
export declare function transformSubjectArea(domain: DisplaySubjectArea, options?: TransformOptions): TransformResult;
|
|
65
65
|
export {};
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* same are told apart by schema (`silver.date`, `gold.date`).
|
|
9
9
|
*/
|
|
10
10
|
/** The fields a label is computed from. */
|
|
11
|
-
export interface
|
|
11
|
+
export interface LabelledTable {
|
|
12
12
|
name: string;
|
|
13
13
|
schema?: string;
|
|
14
14
|
alias?: string;
|
|
@@ -18,9 +18,9 @@ export interface LabelledModel {
|
|
|
18
18
|
* name. A model absent from the map is labelled with its name, exactly as
|
|
19
19
|
* before aliases existed.
|
|
20
20
|
*/
|
|
21
|
-
export declare function
|
|
21
|
+
export declare function computeTableLabels(models: readonly LabelledTable[]): Map<string, string>;
|
|
22
22
|
/** Whether a search query (already lower-cased) matches a model by name or label. */
|
|
23
|
-
export declare function
|
|
23
|
+
export declare function matchesTableSearch(data: {
|
|
24
24
|
modelName: string;
|
|
25
25
|
label?: string;
|
|
26
26
|
}, query: string): boolean;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Node/edge overlays — ephemeral per-node presentation state layered on top
|
|
3
|
-
* of the graph produced by `
|
|
3
|
+
* of the graph produced by `transformSubjectArea`:
|
|
4
4
|
*
|
|
5
5
|
* - `dimmed`: search-miss or not-connected-to-selection dimming (F402)
|
|
6
6
|
* - `isExpanded` / `onToggleExpansion`: column expansion (F405)
|
|
@@ -8,15 +8,15 @@
|
|
|
8
8
|
* `applyNodeOverlays` is a pure function that preserves object identity for
|
|
9
9
|
* every node/edge whose overlay values did not change, so React Flow's
|
|
10
10
|
* `adoptUserNodes` short-circuits on unchanged nodes and memoised
|
|
11
|
-
* `
|
|
11
|
+
* `TableNode` / `FkEdge` components skip re-rendering. When nothing changed
|
|
12
12
|
* at all, the *same arrays* are returned so callers can skip `setNodes`.
|
|
13
13
|
*
|
|
14
14
|
* This lets selection / search / expansion changes avoid re-running the full
|
|
15
15
|
* domain transform (which would also drop `measured` and force React Flow to
|
|
16
16
|
* re-measure every node).
|
|
17
17
|
*/
|
|
18
|
-
import type {
|
|
19
|
-
export type GraphNode =
|
|
18
|
+
import type { TableFlowNode, FkFlowEdge, AnnotationFlowNode, AnnotationFlowEdge } from '../types/graph.js';
|
|
19
|
+
export type GraphNode = TableFlowNode | AnnotationFlowNode;
|
|
20
20
|
export type GraphEdge = FkFlowEdge | AnnotationFlowEdge;
|
|
21
21
|
export interface OverlayState {
|
|
22
22
|
/** Currently selected model (drives connected-node dimming). */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Model node size estimation (matches
|
|
2
|
+
* Model node size estimation (matches TableNode CSS).
|
|
3
3
|
*
|
|
4
4
|
* The width and height a model node will render at, estimated from its
|
|
5
5
|
* content, for code that needs node sizes before React Flow has measured the
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* Kept free of elkjs and React Flow runtime imports so it can be loaded on its
|
|
10
10
|
* own.
|
|
11
11
|
*/
|
|
12
|
-
import type {
|
|
12
|
+
import type { TableFlowNode, TableNodeData } from '../types/graph.js';
|
|
13
13
|
/** Default width — used as fallback by edgeDistribution.ts. */
|
|
14
14
|
export declare const NODE_WIDTH = 280;
|
|
15
15
|
/**
|
|
@@ -18,7 +18,7 @@ export declare const NODE_WIDTH = 280;
|
|
|
18
18
|
*/
|
|
19
19
|
export declare function estimateNodeHeight(rowCount: number, hasGrain: boolean): number;
|
|
20
20
|
/**
|
|
21
|
-
* Number of rows
|
|
21
|
+
* Number of rows TableNode actually renders in its columns section.
|
|
22
22
|
*
|
|
23
23
|
* Mirrors the rendering rules in `ModelNode.tsx`:
|
|
24
24
|
* - stub models show only PK/NK columns
|
|
@@ -29,12 +29,12 @@ export declare function estimateNodeHeight(rowCount: number, hasGrain: boolean):
|
|
|
29
29
|
* Using the full column count (the old behaviour) over-reserved
|
|
30
30
|
* `(columns - 5) * rowHeight` per node on auto-collapsed domains (≥30 models).
|
|
31
31
|
*/
|
|
32
|
-
export declare function countVisibleColumnRows(data: Pick<
|
|
32
|
+
export declare function countVisibleColumnRows(data: Pick<TableNodeData, 'columns' | 'isStub' | 'isExpanded'>): number;
|
|
33
33
|
/**
|
|
34
34
|
* Best-known size for a model node: React Flow's measured DOM size when
|
|
35
35
|
* available, otherwise an estimate from the rows that will be rendered.
|
|
36
36
|
*/
|
|
37
|
-
export declare function resolveNodeDimensions(node: Pick<
|
|
37
|
+
export declare function resolveNodeDimensions(node: Pick<TableFlowNode, 'data' | 'measured'>): {
|
|
38
38
|
width: number;
|
|
39
39
|
height: number;
|
|
40
40
|
};
|
|
@@ -47,4 +47,4 @@ export declare function resolveNodeDimensions(node: Pick<ModelFlowNode, 'data' |
|
|
|
47
47
|
* slightly more space than the minimum estimate, preventing overlap
|
|
48
48
|
* when font rendering or badge widths differ from the approximation.
|
|
49
49
|
*/
|
|
50
|
-
export declare function estimateNodeWidth(data: Pick<
|
|
50
|
+
export declare function estimateNodeWidth(data: Pick<TableNodeData, 'modelName' | 'label' | 'columns' | 'provenance'>): number;
|
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
*/
|
|
15
15
|
import { type ReactNode } from 'react';
|
|
16
16
|
import { type StoreApi } from 'zustand';
|
|
17
|
-
import type {
|
|
18
|
-
import type {
|
|
17
|
+
import type { DisplaySubjectArea, ExistingTablePreview } from '@erd-studio/core';
|
|
18
|
+
import type { TableFlowNode, FkFlowEdge, FkEdgeData, AnnotationFlowNode, AnnotationFlowEdge } from '../types/graph.js';
|
|
19
19
|
/** Context menu state for edge right-click. */
|
|
20
20
|
export interface EdgeContextMenu {
|
|
21
21
|
type: 'edge';
|
|
@@ -70,15 +70,15 @@ export interface CanvasState {
|
|
|
70
70
|
/** Whether a delete confirmation is pending (triggered by Delete key). */
|
|
71
71
|
pendingDeleteConfirmation: boolean;
|
|
72
72
|
/** The loaded domain data from the extension host (already reconciled with manifest). */
|
|
73
|
-
domain:
|
|
73
|
+
domain: DisplaySubjectArea | null;
|
|
74
74
|
/** React Flow nodes (local state for selection/drag). */
|
|
75
|
-
nodes: (
|
|
75
|
+
nodes: (TableFlowNode | AnnotationFlowNode)[];
|
|
76
76
|
/** React Flow edges. */
|
|
77
77
|
edges: (FkFlowEdge | AnnotationFlowEdge)[];
|
|
78
78
|
/** Annotation currently being edited (auto-focus textarea), or null. */
|
|
79
79
|
editingAnnotationId: string | null;
|
|
80
80
|
/** Models available to add from logical-models/ and manifest. */
|
|
81
|
-
existingModels:
|
|
81
|
+
existingModels: ExistingTablePreview[];
|
|
82
82
|
/** Context menu state (position and target), or null if closed. */
|
|
83
83
|
contextMenu: ContextMenuState;
|
|
84
84
|
/** Whether the legend panel is visible. */
|
|
@@ -110,12 +110,12 @@ export interface CanvasActions {
|
|
|
110
110
|
setDetailPanelOpen: (open: boolean) => void;
|
|
111
111
|
/** Set pending delete confirmation state (triggered by Delete key). */
|
|
112
112
|
setPendingDeleteConfirmation: (pending: boolean) => void;
|
|
113
|
-
setDomain: (domain:
|
|
114
|
-
setNodes: (nodes: (
|
|
113
|
+
setDomain: (domain: DisplaySubjectArea) => void;
|
|
114
|
+
setNodes: (nodes: (TableFlowNode | AnnotationFlowNode)[]) => void;
|
|
115
115
|
setEdges: (edges: (FkFlowEdge | AnnotationFlowEdge)[]) => void;
|
|
116
116
|
/** Set the annotation currently being edited (auto-focus). */
|
|
117
117
|
setEditingAnnotationId: (id: string | null) => void;
|
|
118
|
-
setExistingModels: (models:
|
|
118
|
+
setExistingModels: (models: ExistingTablePreview[]) => void;
|
|
119
119
|
/** Open context menu for an edge at the given position. */
|
|
120
120
|
openEdgeContextMenu: (x: number, y: number, data: FkEdgeData) => void;
|
|
121
121
|
/** Open context menu for a node at the given position. */
|