@erd-studio/renderer 0.1.4 → 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-IAFK7ZZV.js → chunk-HWA32XG5.js} +126 -50
- package/dist/editor.js +9 -9
- package/dist/index.js +3 -3
- package/dist/styles.css +56 -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 +18 -13
- package/package.json +3 -2
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
|
@@ -918,6 +918,45 @@
|
|
|
918
918
|
background: var(--button-bg);
|
|
919
919
|
color: var(--button-fg);
|
|
920
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
|
+
}
|
|
921
960
|
|
|
922
961
|
/* src/components/Graph/AnnotationNode.css */
|
|
923
962
|
.annotation-node {
|
|
@@ -2830,6 +2869,23 @@ body[data-vscode-theme-kind=vscode-high-contrast] .annotation-node__link-badge {
|
|
|
2830
2869
|
padding: 3px 8px;
|
|
2831
2870
|
font-size: 10px;
|
|
2832
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
|
+
}
|
|
2833
2889
|
|
|
2834
2890
|
/* src/components/Legend/Legend.css */
|
|
2835
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. */
|
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
* Types for React Flow graph nodes and edges.
|
|
3
3
|
*
|
|
4
4
|
* These types define the data payloads for custom React Flow node and edge
|
|
5
|
-
* components. The graph transformer converts
|
|
5
|
+
* components. The graph transformer converts DisplaySubjectArea data into
|
|
6
6
|
* these shapes.
|
|
7
7
|
*/
|
|
8
8
|
import type { Node, Edge } from '@xyflow/react';
|
|
9
|
-
import type { AnnotationColor, Cardinality, ColumnPair, DbtKeyHint, Layer, Meta,
|
|
9
|
+
import type { AnnotationColor, Cardinality, ColumnPair, DbtKeyHint, Layer, Meta, TableLoadError, TableLoadWarning, TableRole, Stage } from '@erd-studio/core';
|
|
10
10
|
import type { LayerConfig } from '@erd-studio/core';
|
|
11
|
-
import type {
|
|
11
|
+
import type { TableDiscrepancy } from '@erd-studio/core';
|
|
12
12
|
import type { PhysicalProvenance } from '@erd-studio/core';
|
|
13
|
-
/** Column data enriched with PK/FK/NK indicators for display in
|
|
13
|
+
/** Column data enriched with PK/FK/NK indicators for display in TableNode. */
|
|
14
14
|
export interface ColumnDisplay {
|
|
15
15
|
name: string;
|
|
16
16
|
dataType: string;
|
|
@@ -30,14 +30,14 @@ export interface ColumnDisplay {
|
|
|
30
30
|
/** What dbt's tests say about the column (editable logical canvas only) — one line of its hover text. */
|
|
31
31
|
dbtKey?: DbtKeyHint;
|
|
32
32
|
}
|
|
33
|
-
/** Data payload for a
|
|
34
|
-
export type
|
|
33
|
+
/** Data payload for a TableNode React Flow node. */
|
|
34
|
+
export type TableNodeData = {
|
|
35
35
|
/** Model name (unique within a domain). */
|
|
36
36
|
modelName: string;
|
|
37
37
|
/**
|
|
38
38
|
* Header label when it differs from `modelName`: the model's table name
|
|
39
39
|
* (`alias`), qualified by schema when another model on the canvas would read
|
|
40
|
-
* the same. See `
|
|
40
|
+
* the same. See `computeTableLabels`.
|
|
41
41
|
*/
|
|
42
42
|
label?: string;
|
|
43
43
|
/** The active design stage. */
|
|
@@ -65,7 +65,7 @@ export type ModelNodeData = {
|
|
|
65
65
|
/** Grain statement — "One row per ___". Shown as subtitle on node. */
|
|
66
66
|
grain?: string;
|
|
67
67
|
/** Model's role in the data warehouse architecture. Shown as badge on node. */
|
|
68
|
-
modelRole?:
|
|
68
|
+
modelRole?: TableRole;
|
|
69
69
|
/** Structured metadata (`meta:`) — shown in the name's hover tip. Absent when empty. */
|
|
70
70
|
meta?: Meta;
|
|
71
71
|
/** Whether this stage is read-only (physical). */
|
|
@@ -93,16 +93,16 @@ export type ModelNodeData = {
|
|
|
93
93
|
* The model's file exists but could not be read (logical stage only): the
|
|
94
94
|
* node shows the error and an "Open file" button instead of "No columns".
|
|
95
95
|
*/
|
|
96
|
-
loadError?:
|
|
96
|
+
loadError?: TableLoadError;
|
|
97
97
|
/**
|
|
98
98
|
* The model's file was read but needs fixing (logical stage only): a key
|
|
99
99
|
* written twice, whose last value is shown (#164). Absent from an older core.
|
|
100
100
|
*/
|
|
101
|
-
loadWarning?:
|
|
101
|
+
loadWarning?: TableLoadWarning;
|
|
102
102
|
/** Whether this model is in stub display mode (PK/NK columns only). */
|
|
103
103
|
isStub: boolean;
|
|
104
104
|
/** Per-model discrepancy data when a cross-stage comparison report is active. */
|
|
105
|
-
discrepancy?:
|
|
105
|
+
discrepancy?: TableDiscrepancy;
|
|
106
106
|
/** The stage currently being viewed (set when discrepancy overlay is active). */
|
|
107
107
|
discrepancySourceStage?: Stage;
|
|
108
108
|
/** The stage being compared against (set when discrepancy overlay is active). */
|
|
@@ -111,14 +111,14 @@ export type ModelNodeData = {
|
|
|
111
111
|
* Index signature required by React Flow's Node generic.
|
|
112
112
|
*
|
|
113
113
|
* It also means an unknown or misspelled key type-checks, and a field written
|
|
114
|
-
* here but never destructured in
|
|
114
|
+
* here but never destructured in TableNode ships as dead payload — which is
|
|
115
115
|
* exactly how `hasRationale` and `modelRole` gained matching dead CSS. Add a
|
|
116
116
|
* field here only together with the code that reads it.
|
|
117
117
|
*/
|
|
118
118
|
[key: string]: unknown;
|
|
119
119
|
};
|
|
120
120
|
/** Typed React Flow node for a semantic model. */
|
|
121
|
-
export type
|
|
121
|
+
export type TableFlowNode = Node<TableNodeData, 'model'>;
|
|
122
122
|
/** Data payload for an FkEdge React Flow edge. */
|
|
123
123
|
export type FkEdgeData = {
|
|
124
124
|
fromModel: string;
|
|
@@ -135,6 +135,11 @@ export type FkEdgeData = {
|
|
|
135
135
|
pairs?: ColumnPair[];
|
|
136
136
|
/** The composite's `compositeKey` name, alongside `pairs`. */
|
|
137
137
|
compositeKey?: string;
|
|
138
|
+
/**
|
|
139
|
+
* The keys contradict its direction (`DisplayRelationship.keysContradict`,
|
|
140
|
+
* #163): drawn with a ⚠ and Turn round, except for viewers.
|
|
141
|
+
*/
|
|
142
|
+
keysContradict?: true;
|
|
138
143
|
/** Stage of the owning domain canvas — drives CSS colour class. */
|
|
139
144
|
stage?: Stage;
|
|
140
145
|
/** Discrepancy status for ghost/extra/mismatch edges. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@erd-studio/renderer",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "ERD Studio's React Flow canvas: the entity-relationship diagram renderer shared by the VS Code extension, with a read-only viewer mode.",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"repository": {
|
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
},
|
|
37
37
|
"files": [
|
|
38
38
|
"dist",
|
|
39
|
+
"CHANGELOG.md",
|
|
39
40
|
"LICENSE",
|
|
40
41
|
"README.md"
|
|
41
42
|
],
|
|
@@ -46,7 +47,7 @@
|
|
|
46
47
|
"prepack": "npm run build"
|
|
47
48
|
},
|
|
48
49
|
"dependencies": {
|
|
49
|
-
"@erd-studio/core": "0.
|
|
50
|
+
"@erd-studio/core": "0.3.0",
|
|
50
51
|
"zustand": "^5.0.0"
|
|
51
52
|
},
|
|
52
53
|
"peerDependencies": {
|