@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/dist/index.js CHANGED
@@ -9,8 +9,8 @@ import {
9
9
  repickHandleSides,
10
10
  toDbml,
11
11
  toMermaid,
12
- transformDomain
13
- } from "./chunk-IAFK7ZZV.js";
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
- transformDomain
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 `DisplayDomain` the way the VS Code extension's canvas shows 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 { DisplayDomain } from '@erd-studio/core';
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: DisplayDomain;
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 toRenderableDomain(domain: DisplayDomain): DisplayDomain;
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 { ModelFlowNode, FkFlowEdge, AnnotationFlowNode, AnnotationFlowEdge } from '../types/graph.js';
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: (ModelFlowNode | AnnotationFlowNode)[], edges: (FkFlowEdge | AnnotationFlowEdge)[]) => void;
27
+ onTransformed?: (nodes: (TableFlowNode | AnnotationFlowNode)[], edges: (FkFlowEdge | AnnotationFlowEdge)[]) => void;
28
28
  }
29
29
  export interface UseCanvasGraphResult {
30
- nodes: (ModelFlowNode | AnnotationFlowNode)[];
30
+ nodes: (TableFlowNode | AnnotationFlowNode)[];
31
31
  edges: (FkFlowEdge | AnnotationFlowEdge)[];
32
- onNodeClick: (event: React.MouseEvent, node: ModelFlowNode | AnnotationFlowNode) => void;
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 "Table name" row of the detail panel's metadata.
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 { ModelRole } from '@erd-studio/core';
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?: 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
- * ModelRationale — collapsible section for all design rationale fields.
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, ModelRole } from '@erd-studio/core';
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 ModelRationaleProps {
20
+ interface TableRationaleProps {
21
21
  modelName: string;
22
22
  rationale?: Rationale;
23
- modelRole?: ModelRole;
23
+ modelRole?: TableRole;
24
24
  grain?: string;
25
25
  }
26
- export declare function ModelRationale({ modelName, rationale, modelRole, grain }: ModelRationaleProps): import("react/jsx-runtime").JSX.Element | null;
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 ModelRole options.
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 { ModelRole } from '@erd-studio/core';
7
+ import type { TableRole } from '@erd-studio/core';
8
8
  interface RoleEditorProps {
9
9
  modelName: string;
10
- modelRole?: 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 ModelNode's `overflow: hidden`. Positioned with `position: fixed`
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
- * ModelNode — custom React Flow node for displaying a semantic model card.
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 { ModelFlowNode } from '../../types/graph.js';
17
+ import type { TableFlowNode } from '../../types/graph.js';
18
18
  import './ModelNode.css';
19
- declare function ModelNodeComponent({ data, selected }: NodeProps<ModelFlowNode>): import("react/jsx-runtime").JSX.Element;
20
- export declare const ModelNode: import("react").MemoExoticComponent<typeof ModelNodeComponent>;
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 ModelNode actually renders. Positioned in the bottom-left corner, collapsible
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 { ModelRole } from '@erd-studio/core';
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?: 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. */
@@ -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 { ModelNode } from './components/Graph/ModelNode.js';
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 { computeModelLabels, matchesModelSearch, type LabelledModel } from './lib/modelLabels.js';
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 ModelNode (ColumnRow rows)
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 {
@@ -1,6 +1,6 @@
1
1
  export { ErdCanvas, type ErdCanvasProps, type ErdCanvasHandle } from './ErdCanvas.js';
2
- export { transformDomain, pickHandleSides, type TransformResult, type TransformOptions, type NodeRect, type NodeDimensions, } from './lib/graphTransformer.js';
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 { DisplayDomain, DisplayModel, DisplayColumn, DisplayRelationship, PhysicalColumnSource, PhysicalProvenance, Annotation, AnnotationColor, Cardinality, Layer, ModelRole, NodePosition, Rationale, Stage, ViewConfig, LayerConfig, } from '@erd-studio/core';
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 { ModelFlowNode, ModelNodeData, FkFlowEdge, FkEdgeData, AnnotationFlowNode, AnnotationFlowEdge, ColumnDisplay, } from './types/graph.js';
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 ModelNode because the Legend explains exactly
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
- * `transformDomain` chooses the handle side at each end of an edge from the
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 `transformDomain` too: a node's size is its measured
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 DisplayDomain into React Flow nodes and edges.
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 DisplayModel → ModelFlowNode (with position + columns)
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 { DisplayDomain } from '@erd-studio/core';
11
+ import type { DisplaySubjectArea } from '@erd-studio/core';
12
12
  import type { DiscrepancyReport } from '@erd-studio/core';
13
- import type { ModelFlowNode, FkFlowEdge, AnnotationFlowNode, AnnotationFlowEdge } from '../types/graph.js';
13
+ import type { TableFlowNode, FkFlowEdge, AnnotationFlowNode, AnnotationFlowEdge } from '../types/graph.js';
14
14
  export interface TransformResult {
15
- nodes: (ModelFlowNode | AnnotationFlowNode)[];
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 DisplayDomain into React Flow nodes and edges.
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 transformDomain(domain: DisplayDomain, options?: TransformOptions): TransformResult;
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 LabelledModel {
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 computeModelLabels(models: readonly LabelledModel[]): Map<string, string>;
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 matchesModelSearch(data: {
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 `transformDomain`:
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
- * `ModelNode` / `FkEdge` components skip re-rendering. When nothing changed
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 { ModelFlowNode, FkFlowEdge, AnnotationFlowNode, AnnotationFlowEdge } from '../types/graph.js';
19
- export type GraphNode = ModelFlowNode | AnnotationFlowNode;
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 ModelNode CSS).
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 { ModelFlowNode, ModelNodeData } from '../types/graph.js';
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 ModelNode actually renders in its columns section.
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<ModelNodeData, 'columns' | 'isStub' | 'isExpanded'>): number;
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<ModelFlowNode, 'data' | 'measured'>): {
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<ModelNodeData, 'modelName' | 'label' | 'columns' | 'provenance'>): number;
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 { DisplayDomain, ExistingModelPreview } from '@erd-studio/core';
18
- import type { ModelFlowNode, FkFlowEdge, FkEdgeData, AnnotationFlowNode, AnnotationFlowEdge } from '../types/graph.js';
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: DisplayDomain | null;
73
+ domain: DisplaySubjectArea | null;
74
74
  /** React Flow nodes (local state for selection/drag). */
75
- nodes: (ModelFlowNode | AnnotationFlowNode)[];
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: ExistingModelPreview[];
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: DisplayDomain) => void;
114
- setNodes: (nodes: (ModelFlowNode | AnnotationFlowNode)[]) => void;
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: ExistingModelPreview[]) => void;
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 DisplayDomain data into
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, ModelLoadError, ModelLoadWarning, ModelRole, Stage } from '@erd-studio/core';
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 { ModelDiscrepancy } from '@erd-studio/core';
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 ModelNode. */
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 ModelNode React Flow node. */
34
- export type ModelNodeData = {
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 `computeModelLabels`.
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?: 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?: ModelLoadError;
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?: ModelLoadWarning;
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?: ModelDiscrepancy;
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 ModelNode ships as dead payload — which is
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 ModelFlowNode = Node<ModelNodeData, 'model'>;
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.1.4",
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.1.4",
50
+ "@erd-studio/core": "0.3.0",
50
51
  "zustand": "^5.0.0"
51
52
  },
52
53
  "peerDependencies": {