orcasvn-react-diagrams 0.2.2 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/CHANGELOG.md +51 -0
  2. package/README.md +11 -3
  3. package/dist/cjs/examples.js +1768 -161
  4. package/dist/cjs/index.js +786 -120
  5. package/dist/cjs/types/api/createDiagramEditor.d.ts +19 -1
  6. package/dist/cjs/types/api/index.d.ts +1 -1
  7. package/dist/cjs/types/api/types.d.ts +32 -0
  8. package/dist/cjs/types/displaybox/DisplayBoxControls.d.ts +5 -1
  9. package/dist/cjs/types/displaybox/demos/AsymmetricPortMultiAnchorDemoTab.d.ts +3 -0
  10. package/dist/cjs/types/displaybox/demos/LayoutLabelReservedSpaceDemoTab.d.ts +3 -0
  11. package/dist/cjs/types/displaybox/demos/VertexControlLinkSessionDemoTab.d.ts +3 -0
  12. package/dist/cjs/types/displaybox/demos/asymmetricPortMultiAnchorDemo.d.ts +31 -0
  13. package/dist/cjs/types/displaybox/demos/layoutLabelReservedSpaceDemo.d.ts +11 -0
  14. package/dist/cjs/types/displaybox/demos/vertexControlLinkSessionDemo.d.ts +12 -0
  15. package/dist/cjs/types/displaybox/useDemoControls.d.ts +4 -0
  16. package/dist/cjs/types/engine/AutoLayoutService.d.ts +2 -0
  17. package/dist/cjs/types/engine/DiagramEngine.d.ts +5 -0
  18. package/dist/cjs/types/engine/LinkRoutingService.d.ts +9 -1
  19. package/dist/cjs/types/models/PortModel.d.ts +5 -0
  20. package/dist/cjs/types/renderer/RenderTypes.d.ts +3 -1
  21. package/dist/cjs/types/renderer/konva/KonvaInteraction.d.ts +14 -0
  22. package/dist/cjs/types/renderer/konva/KonvaNodeFactory.d.ts +1 -0
  23. package/dist/cjs/types/renderer/konva/KonvaRenderer.d.ts +0 -1
  24. package/dist/cjs/types/shapes/BuiltInShapes.d.ts +3 -1
  25. package/dist/cjs/types/utils/__tests__/portGeometry.test.d.ts +1 -0
  26. package/dist/cjs/types/utils/portGeometry.d.ts +44 -0
  27. package/dist/esm/examples.js +1769 -162
  28. package/dist/esm/examples.js.map +1 -1
  29. package/dist/esm/index.js +786 -120
  30. package/dist/esm/index.js.map +1 -1
  31. package/dist/esm/types/api/createDiagramEditor.d.ts +19 -1
  32. package/dist/esm/types/api/index.d.ts +1 -1
  33. package/dist/esm/types/api/types.d.ts +32 -0
  34. package/dist/esm/types/displaybox/DisplayBoxControls.d.ts +5 -1
  35. package/dist/esm/types/displaybox/demos/AsymmetricPortMultiAnchorDemoTab.d.ts +3 -0
  36. package/dist/esm/types/displaybox/demos/LayoutLabelReservedSpaceDemoTab.d.ts +3 -0
  37. package/dist/esm/types/displaybox/demos/VertexControlLinkSessionDemoTab.d.ts +3 -0
  38. package/dist/esm/types/displaybox/demos/asymmetricPortMultiAnchorDemo.d.ts +31 -0
  39. package/dist/esm/types/displaybox/demos/layoutLabelReservedSpaceDemo.d.ts +11 -0
  40. package/dist/esm/types/displaybox/demos/vertexControlLinkSessionDemo.d.ts +12 -0
  41. package/dist/esm/types/displaybox/useDemoControls.d.ts +4 -0
  42. package/dist/esm/types/engine/AutoLayoutService.d.ts +2 -0
  43. package/dist/esm/types/engine/DiagramEngine.d.ts +5 -0
  44. package/dist/esm/types/engine/LinkRoutingService.d.ts +9 -1
  45. package/dist/esm/types/models/PortModel.d.ts +5 -0
  46. package/dist/esm/types/renderer/RenderTypes.d.ts +3 -1
  47. package/dist/esm/types/renderer/konva/KonvaInteraction.d.ts +14 -0
  48. package/dist/esm/types/renderer/konva/KonvaNodeFactory.d.ts +1 -0
  49. package/dist/esm/types/renderer/konva/KonvaRenderer.d.ts +0 -1
  50. package/dist/esm/types/shapes/BuiltInShapes.d.ts +3 -1
  51. package/dist/esm/types/utils/__tests__/portGeometry.test.d.ts +1 -0
  52. package/dist/esm/types/utils/portGeometry.d.ts +44 -0
  53. package/dist/examples.d.ts +50 -0
  54. package/dist/index.d.ts +58 -1
  55. package/package.json +11 -10
  56. package/src/displaybox/demos/AsymmetricPortMultiAnchorDemoTab.tsx +269 -0
  57. package/src/displaybox/demos/AutoLayoutDemoTab.tsx +113 -11
  58. package/src/displaybox/demos/DeletionEventsDemoTab.tsx +6 -1
  59. package/src/displaybox/demos/EngineEventsDemoTab.tsx +5 -0
  60. package/src/displaybox/demos/EventHandlersDemoTab.tsx +5 -0
  61. package/src/displaybox/demos/ExternalDragDropDemoTab.tsx +5 -0
  62. package/src/displaybox/demos/LayoutLabelReservedSpaceDemoTab.tsx +291 -0
  63. package/src/displaybox/demos/LinkCancelDemoTab.tsx +5 -0
  64. package/src/displaybox/demos/ShapeHoverControlsDemoTab.tsx +6 -1
  65. package/src/displaybox/demos/SimpleDemo.tsx +5 -0
  66. package/src/displaybox/demos/SvgPathDemoTab.tsx +5 -0
  67. package/src/displaybox/demos/TextLayoutDemoTab.tsx +6 -1
  68. package/src/displaybox/demos/VertexControlLinkSessionDemoTab.tsx +302 -0
  69. package/src/displaybox/demos/asymmetricPortMultiAnchorDemo.ts +357 -0
  70. package/src/displaybox/demos/autoLayoutDemo.ts +23 -5
  71. package/src/displaybox/demos/index.tsx +91 -75
  72. package/src/displaybox/demos/layoutLabelReservedSpaceDemo.ts +121 -0
  73. package/src/displaybox/demos/vertexControlLinkSessionDemo.ts +145 -0
@@ -1,4 +1,4 @@
1
- import { DiagramEngineHandle, DiagramState, ElementShapeHoverControlActivationEvent, ElementShapeHoverControlInteractionEvent, ElementShapeHoverControls, EngineChangeEvent, EngineSelectionEvent } from './types';
1
+ import { DiagramEngineHandle, Point, DiagramState, ElementShapeHoverControlActivationEvent, ElementShapeHoverControlInteractionEvent, ElementShapeHoverControls, EngineChangeEvent, EngineSelectionEvent } from './types';
2
2
  import { type BuiltInShapeKind } from '../shapes';
3
3
  export type SimpleShape = {
4
4
  id: string;
@@ -19,7 +19,25 @@ export type DiagramEditorConfig = {
19
19
  onChange?: (event: EngineChangeEvent) => void;
20
20
  onSelection?: (event: EngineSelectionEvent) => void;
21
21
  };
22
+ export type DiagramImageExportOptions = {
23
+ mimeType?: string;
24
+ quality?: number;
25
+ pixelRatio?: number;
26
+ x?: number;
27
+ y?: number;
28
+ width?: number;
29
+ height?: number;
30
+ fitToContent?: boolean | {
31
+ padding?: number;
32
+ };
33
+ };
22
34
  export type DiagramEditorHandle = DiagramEngineHandle & {
35
+ startLinkFromPort: (sourcePortId: string, pointer?: Point) => void;
36
+ updateLinkPreview: (pointer: Point) => void;
37
+ completeLinkToPort: (targetPortId: string) => void;
38
+ completeLinkToElement: (targetElementId: string, pointer: Point) => void;
39
+ cancelLink: () => void;
40
+ exportImage: (options?: DiagramImageExportOptions) => string;
23
41
  resize: (width: number, height: number) => void;
24
42
  setElementShapeHoverControls: (controls?: ElementShapeHoverControls) => void;
25
43
  destroy: () => void;
@@ -1,4 +1,4 @@
1
1
  export * from './types';
2
2
  export { createDiagramEngine } from '../engine/DiagramEngine';
3
3
  export { createDiagramEditor } from './createDiagramEditor';
4
- export type { DiagramEditorConfig, DiagramEditorHandle, SimpleShape } from './createDiagramEditor';
4
+ export type { DiagramEditorConfig, DiagramEditorHandle, DiagramImageExportOptions, SimpleShape, } from './createDiagramEditor';
@@ -22,6 +22,7 @@ export type DiagramContainer = {
22
22
  export type MoveConstraint = 'free' | 'inside' | 'border';
23
23
  export type BorderSide = 'left' | 'right' | 'top' | 'bottom';
24
24
  export type HostAnchorPreset = 'vertices' | 'cardinal';
25
+ export type PortLinkAttachMode = 'external' | 'internal';
25
26
  export type PortAnchor = {
26
27
  id: string;
27
28
  position: Point;
@@ -29,6 +30,20 @@ export type PortAnchor = {
29
30
  normal?: Point;
30
31
  meta?: Record<string, unknown>;
31
32
  };
33
+ export type PortBorderTransformContext = {
34
+ side: BorderSide;
35
+ normal: Point;
36
+ hostRect: Rect;
37
+ attachMode: PortLinkAttachMode;
38
+ effectiveLinkAttachPoint: Point;
39
+ placementPoint: Point;
40
+ rotationPivot: Point;
41
+ portSize?: Size;
42
+ };
43
+ export type PortBorderTransformResult = {
44
+ rotation?: number;
45
+ offset?: Point;
46
+ };
32
47
  export type PortAnchorConstraint = {
33
48
  preset: HostAnchorPreset;
34
49
  fallback?: 'nearest';
@@ -153,6 +168,15 @@ export type ElementLayoutMode = 'manual' | 'horizontal' | 'vertical';
153
168
  export type ElementLayoutAlign = 'start' | 'center' | 'end';
154
169
  export type ElementLayoutChildFitMainAxis = 'none' | 'distribute';
155
170
  export type ElementLayoutChildFitCrossAxis = 'none' | 'stretch';
171
+ export type ElementLayoutLabelReservedSpaceMode = 'none' | 'fixed' | 'flexible';
172
+ export type ElementLayoutLabelReservedSpacePlacement = 'top';
173
+ export type ElementLayoutLabelReservedSpace = {
174
+ mode?: ElementLayoutLabelReservedSpaceMode;
175
+ placement?: ElementLayoutLabelReservedSpacePlacement;
176
+ size?: number;
177
+ minSize?: number;
178
+ maxSize?: number;
179
+ };
156
180
  export type TextLayoutBoundsMode = 'owner-width' | 'owner-box' | 'fixed';
157
181
  export type TextLayoutWrapMode = 'none' | 'word' | 'char';
158
182
  export type TextLayoutOverflowMode = 'clip' | 'ellipsis-end' | 'ellipsis-middle' | 'ellipsis-start';
@@ -168,6 +192,7 @@ export type ElementLayout = {
168
192
  childFitCrossAxis?: ElementLayoutChildFitCrossAxis;
169
193
  childFitMinSize?: Partial<Size>;
170
194
  childFitMaxSize?: Partial<Size>;
195
+ labelReservedSpace?: ElementLayoutLabelReservedSpace;
171
196
  };
172
197
  export type TextLayout = {
173
198
  boundsMode?: TextLayoutBoundsMode;
@@ -222,6 +247,11 @@ export type PortData = {
222
247
  moveMode?: MoveConstraint;
223
248
  anchorCenter?: boolean;
224
249
  orientToHostBorder?: boolean;
250
+ placementPoint?: Point;
251
+ linkAttachPoint?: Point;
252
+ externalLinkAttachPoint?: Point;
253
+ internalLinkAttachPoint?: Point;
254
+ rotationPivot?: Point;
225
255
  currentAnchorId?: string;
226
256
  };
227
257
  export type ShapeDrawContext = {
@@ -441,7 +471,9 @@ export type DiagramEngineHandle = {
441
471
  svgSize?: Size;
442
472
  projectToBorder?: (point: Point, rect: Rect) => Point;
443
473
  resolveBorderSide?: (point: Point, rect: Rect) => BorderSide;
474
+ resolveBorderNormal?: (point: Point, rect: Rect) => Point;
444
475
  resolvePortAnchors?: (rect: Rect, options: ResolvePortAnchorsOptions) => PortAnchor[];
476
+ resolvePortBorderTransform?: (context: PortBorderTransformContext) => PortBorderTransformResult | undefined;
445
477
  resolveHoverGeometry?: (rect: Rect) => ShapeHoverGeometry | undefined;
446
478
  resolveEllipseMidPoints?: (rect: Rect) => ShapeEllipseMidPointTarget[] | undefined;
447
479
  }) => void;
@@ -13,6 +13,10 @@ type ControlsProps = {
13
13
  onManualRender: () => void;
14
14
  onToggleLinkRouting: () => void;
15
15
  onAction: (action: DemoAction) => void;
16
+ onExportImage?: () => void;
17
+ onClearExportPreview?: () => void;
18
+ exportPreviewDataUrl?: string | null;
19
+ exportError?: string | null;
16
20
  };
17
- declare const DisplayBoxControls: ({ actions, snapEnabled, selectedLinkRouting, canToggleLinkRouting, onReload, onZoomIn, onZoomOut, onResetViewport, onToggleSnap, onManualRender, onToggleLinkRouting, onAction, }: ControlsProps) => React.JSX.Element;
21
+ declare const DisplayBoxControls: ({ actions, snapEnabled, selectedLinkRouting, canToggleLinkRouting, onReload, onZoomIn, onZoomOut, onResetViewport, onToggleSnap, onManualRender, onToggleLinkRouting, onAction, onExportImage, onClearExportPreview, exportPreviewDataUrl, exportError, }: ControlsProps) => React.JSX.Element;
18
22
  export default DisplayBoxControls;
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ declare const AsymmetricPortMultiAnchorDemo: () => React.JSX.Element;
3
+ export default AsymmetricPortMultiAnchorDemo;
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ declare const LayoutLabelReservedSpaceDemo: () => React.JSX.Element;
3
+ export default LayoutLabelReservedSpaceDemo;
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ declare const VertexControlLinkSessionDemo: () => React.JSX.Element;
3
+ export default VertexControlLinkSessionDemo;
@@ -0,0 +1,31 @@
1
+ import type { DiagramState, Point } from '../../api';
2
+ import type { DemoConfig } from '../types';
3
+ export declare const asymmetricPortMultiAnchorDemoId = "asymmetric-port-multi-anchor";
4
+ export declare const asymmetricPortDefaultVariantId = "classic";
5
+ export type AsymmetricPortShapeVariant = {
6
+ id: string;
7
+ label: string;
8
+ description: string;
9
+ shapeId: string;
10
+ svgPath: string;
11
+ svgSize: {
12
+ width: number;
13
+ height: number;
14
+ };
15
+ placementPoint: Point;
16
+ externalLinkAttachPoint: Point;
17
+ internalLinkAttachPoint: Point;
18
+ rotationPivot: Point;
19
+ };
20
+ export declare const asymmetricPortShapeVariants: AsymmetricPortShapeVariant[];
21
+ export declare const resolveAsymmetricPortShapeVariant: (variantId?: string) => AsymmetricPortShapeVariant;
22
+ export declare const asymmetricPortMultiAnchorShapeId: string;
23
+ export declare const asymmetricPortMultiAnchorShapeSvgPath: string;
24
+ export declare const asymmetricPortMultiAnchorShapeSize: {
25
+ width: number;
26
+ height: number;
27
+ };
28
+ export declare const multiAnchorHostId = "multi-anchor-host";
29
+ export declare const multiAnchorExternalPortId = "multi-anchor-port-external";
30
+ export declare const createAsymmetricPortMultiAnchorState: (showLegacyComparison?: boolean, variantId?: string) => DiagramState;
31
+ export declare const asymmetricPortMultiAnchorDemoConfig: DemoConfig;
@@ -0,0 +1,11 @@
1
+ import type { DemoConfig } from '../types';
2
+ export declare const layoutReservedDemoIds: {
3
+ readonly parent: "layout-lane-parent";
4
+ readonly childA: "layout-lane-child-a";
5
+ readonly childB: "layout-lane-child-b";
6
+ readonly nestedParent: "layout-lane-nested-parent";
7
+ readonly nestedChildA: "layout-lane-nested-child-a";
8
+ readonly nestedChildB: "layout-lane-nested-child-b";
9
+ readonly parentLabel: "layout-lane-parent-label";
10
+ };
11
+ export declare const layoutLabelReservedSpaceDemoConfig: DemoConfig;
@@ -0,0 +1,12 @@
1
+ import type { DemoConfig } from '../types';
2
+ export declare const vertexSessionDemoIds: {
3
+ readonly source: "vertex-session-source";
4
+ readonly portTarget: "vertex-session-port-target";
5
+ readonly elementTarget: "vertex-session-element-target";
6
+ readonly nativeSource: "vertex-session-native-source";
7
+ readonly nativeTarget: "vertex-session-native-target";
8
+ readonly existingTargetPort: "vertex-session-existing-target-port";
9
+ readonly nativeSourcePort: "vertex-session-native-source-port";
10
+ readonly nativeTargetPort: "vertex-session-native-target-port";
11
+ };
12
+ export declare const vertexControlLinkSessionDemoConfig: DemoConfig;
@@ -13,6 +13,8 @@ type UseDemoControlsArgs = {
13
13
  declare const useDemoControls: ({ demo, editorRef, diagramState, selection, snapEnabled, setSnapEnabled, actionHelpers, }: UseDemoControlsArgs) => {
14
14
  selectedLinkRouting: import("../api").LinkRoutingMode;
15
15
  canToggleLinkRouting: boolean;
16
+ exportPreviewDataUrl: string | null;
17
+ exportError: string | null;
16
18
  handleAction: (action: DemoAction) => void;
17
19
  handleReload: () => void;
18
20
  handleZoomIn: () => void;
@@ -21,6 +23,8 @@ declare const useDemoControls: ({ demo, editorRef, diagramState, selection, snap
21
23
  handleToggleSnap: () => void;
22
24
  handleManualRender: () => void;
23
25
  handleToggleLinkRouting: () => void;
26
+ handleExportImage: () => void;
27
+ handleClearExportPreview: () => void;
24
28
  snapEnabled: boolean;
25
29
  };
26
30
  export default useDemoControls;
@@ -19,6 +19,8 @@ export default class AutoLayoutService {
19
19
  applyLayoutCascade(startParentId: string | null): AutoLayoutResult;
20
20
  applyAllLayouts(): AutoLayoutResult;
21
21
  private resolveLayoutPadding;
22
+ private resolveLabelReservedTopLane;
23
+ private resolveFlexibleLabelLaneFromText;
22
24
  private clampLayoutSize;
23
25
  private distributeLayoutSizes;
24
26
  }
@@ -78,6 +78,10 @@ export default class DiagramEngine {
78
78
  height: number;
79
79
  };
80
80
  getPortWorldPosition(id: string): Point | null;
81
+ getPortLinkWorldPosition(id: string, options?: {
82
+ oppositePortId?: string;
83
+ attachMode?: 'external' | 'internal';
84
+ }): Point | null;
81
85
  getTextWorldPosition(id: string): Point | null;
82
86
  getPortElementId(portId: string): string | null;
83
87
  deleteSelection(): void;
@@ -121,6 +125,7 @@ export default class DiagramEngine {
121
125
  private applyLayoutForParent;
122
126
  private applyLayoutCascade;
123
127
  private applyAllLayouts;
128
+ private hasFlexibleLabelReservedSpace;
124
129
  private updateLinksForPorts;
125
130
  private collectElementPortIds;
126
131
  private computeAutoRoute;
@@ -1,4 +1,4 @@
1
- import { DiagramPatch, LinkData, Point } from '../api/types';
1
+ import { DiagramPatch, LinkData, Point, PortLinkAttachMode } from '../api/types';
2
2
  import DiagramModel from '../models/DiagramModel';
3
3
  import { ShapeRegistry } from '../renderer/RenderTypes';
4
4
  import { RouterStrategy } from '../strategies/RouterStrategy';
@@ -18,8 +18,13 @@ export default class LinkRoutingService {
18
18
  setRouter(router: RouterStrategy): void;
19
19
  updateLinksForPorts(portIds: string[]): DiagramPatch[];
20
20
  routeLinksWithEmptyPoints(): DiagramPatch[];
21
+ getPortLinkWorldPosition(portId: string, options?: {
22
+ oppositePortId?: string;
23
+ attachMode?: PortLinkAttachMode;
24
+ }): Point | null;
21
25
  computeAutoRoute(link: LinkData, source: Point, target: Point): Point[];
22
26
  private resolveLinkPointsForUpdate;
27
+ private resolveLinkEndpoints;
23
28
  private updateManualRoute;
24
29
  private buildRouteContext;
25
30
  private resolveEndpointGeometry;
@@ -27,6 +32,9 @@ export default class LinkRoutingService {
27
32
  private resolveElementShape;
28
33
  private isPointOnProjectedBorder;
29
34
  private getElementRect;
35
+ private resolveHostForPort;
36
+ private resolveAttachModeForPorts;
37
+ private hasAncestorRelation;
30
38
  private getAncestorChain;
31
39
  private getAncestorExclusions;
32
40
  private resolveRouteBounds;
@@ -10,6 +10,11 @@ export default class PortModel {
10
10
  moveMode?: MoveConstraint;
11
11
  anchorCenter?: boolean;
12
12
  orientToHostBorder: boolean;
13
+ placementPoint?: Point;
14
+ linkAttachPoint?: Point;
15
+ externalLinkAttachPoint?: Point;
16
+ internalLinkAttachPoint?: Point;
17
+ rotationPivot?: Point;
13
18
  currentAnchorId?: string;
14
19
  constructor(data: PortData);
15
20
  setPosition(position: Point): void;
@@ -1,4 +1,4 @@
1
- import { ElementData, Point, PortAnchor, PortData, Rect, ResolvePortAnchorsOptions, ShapeEllipseMidPointTarget, ShapeDrawContext, ShapeHoverGeometry } from '../api/types';
1
+ import { ElementData, Point, PortBorderTransformContext, PortBorderTransformResult, PortAnchor, PortData, Rect, ResolvePortAnchorsOptions, ShapeEllipseMidPointTarget, ShapeDrawContext, ShapeHoverGeometry } from '../api/types';
2
2
  import { BorderSide } from '../utils/borderGeometry';
3
3
  export type ShapeNodeSizeUpdateContext = {
4
4
  size: {
@@ -38,7 +38,9 @@ export type ShapeDefinition = {
38
38
  };
39
39
  projectToBorder?: (point: Point, rect: Rect) => Point;
40
40
  resolveBorderSide?: (point: Point, rect: Rect) => BorderSide;
41
+ resolveBorderNormal?: (point: Point, rect: Rect) => Point;
41
42
  resolvePortAnchors?: (rect: Rect, options: ResolvePortAnchorsOptions) => PortAnchor[];
43
+ resolvePortBorderTransform?: (context: PortBorderTransformContext) => PortBorderTransformResult | undefined;
42
44
  resolveHoverGeometry?: (rect: Rect) => ShapeHoverGeometry | undefined;
43
45
  resolveEllipseMidPoints?: (rect: Rect) => ShapeEllipseMidPointTarget[] | undefined;
44
46
  };
@@ -56,6 +56,7 @@ export default class KonvaInteraction {
56
56
  private onShapeHoverControlInteracted?;
57
57
  private onShapeHoverControlActivated?;
58
58
  private linkDragContext;
59
+ private programmaticLinkSession;
59
60
  private bound;
60
61
  private handlers;
61
62
  private windowHandlers;
@@ -70,9 +71,16 @@ export default class KonvaInteraction {
70
71
  private textEditor;
71
72
  private readonly dragThreshold;
72
73
  private readonly panSpeed;
74
+ private readonly occupiedVertexTolerance;
75
+ private emittingElementLinkEnded;
73
76
  private panKey;
74
77
  constructor(engine: DiagramEngine, config?: InteractionConfig);
75
78
  setShapeHoverControls(controls?: ElementShapeHoverControls): void;
79
+ startLinkFromPort(sourcePortId: string, pointer?: Point): void;
80
+ updateLinkPreview(pointer: Point): void;
81
+ completeLinkToPort(targetPortId: string): void;
82
+ completeLinkToElement(targetElementId: string, pointer: Point): void;
83
+ cancelLink(): void;
76
84
  private buildPointerInfo;
77
85
  bind(stage?: KonvaStageLike): void;
78
86
  dispose(): void;
@@ -102,6 +110,7 @@ export default class KonvaInteraction {
102
110
  private resolveTargetHoverCandidate;
103
111
  private resolveElementHoverCandidate;
104
112
  private resolveEligibleTargetIndices;
113
+ private resolveOccupiedVertexIndices;
105
114
  private resolveEligibleEllipseMidPoints;
106
115
  private resolveRotatedHoverGeometry;
107
116
  private resolveRotatedEllipseMidPoints;
@@ -122,7 +131,12 @@ export default class KonvaInteraction {
122
131
  private projectPointOnSegment;
123
132
  private applyMarqueeSelection;
124
133
  private applyPortConstraints;
134
+ private resolveLinkPreviewSource;
135
+ private resolveActiveLinkSession;
136
+ private finishLinkDragSession;
137
+ private emitElementLinkEndedSafely;
125
138
  private tryCreateLinkToPort;
139
+ private tryCreateLinkToElement;
126
140
  private createPortForLink;
127
141
  private createPlaceholderPort;
128
142
  private getElementById;
@@ -79,5 +79,6 @@ export default class KonvaNodeFactory {
79
79
  }): KonvaNodeLike;
80
80
  private createDrawNode;
81
81
  private createSvgPathNode;
82
+ private resolveShapeRotation;
82
83
  private applyShapeBehaviorAttrs;
83
84
  }
@@ -120,7 +120,6 @@ export default class KonvaRenderer implements Renderer {
120
120
  private syncTexts;
121
121
  private updatePosition;
122
122
  private applyPortOrientation;
123
- private resolvePortBorderRotation;
124
123
  private resolveHostElement;
125
124
  private getNodeAttr;
126
125
  private updateSize;
@@ -1,4 +1,4 @@
1
- import { Point, PortAnchor, Rect, ResolvePortAnchorsOptions, ShapeEllipseMidPointTarget, ShapeHoverGeometry } from '../api/types';
1
+ import { Point, PortBorderTransformContext, PortBorderTransformResult, PortAnchor, Rect, ResolvePortAnchorsOptions, ShapeEllipseMidPointTarget, ShapeHoverGeometry } from '../api/types';
2
2
  import { ShapeNodeSizeUpdater, ShapeResizeNormalizeContext } from '../renderer/RenderTypes';
3
3
  import { BorderSide } from '../utils/borderGeometry';
4
4
  export type BuiltInShapeKind = 'rect' | 'circle' | 'ellipse' | 'diamond' | 'triangle' | 'pentagon' | 'hexagon';
@@ -46,7 +46,9 @@ export declare abstract class BuiltInShape {
46
46
  abstract createNode(context: ShapeCreateContext): unknown;
47
47
  projectToBorder(point: Point, rect: Rect): Point;
48
48
  resolveBorderSide(point: Point, rect: Rect): BorderSide;
49
+ resolveBorderNormal(point: Point, rect: Rect): Point;
49
50
  resolvePortAnchors(_rect: Rect, _options: ResolvePortAnchorsOptions): PortAnchor[];
51
+ resolvePortBorderTransform(_context: PortBorderTransformContext): PortBorderTransformResult | undefined;
50
52
  resolveHoverGeometry(_rect: Rect): ShapeHoverGeometry | undefined;
51
53
  resolveEllipseMidPoints(_rect: Rect): ShapeEllipseMidPointTarget[] | undefined;
52
54
  protected resolveShapeName(isPort: boolean): string;
@@ -0,0 +1,44 @@
1
+ import { BorderSide, Point, PortData, PortLinkAttachMode } from '../api/types';
2
+ import { ShapeRegistry } from '../renderer/RenderTypes';
3
+ type HostElementLike = {
4
+ id: string;
5
+ position: Point;
6
+ size: {
7
+ width: number;
8
+ height: number;
9
+ };
10
+ shapeId: string;
11
+ };
12
+ export type PortGeometryPoints = {
13
+ placementPoint: Point;
14
+ sharedLinkAttachPoint: Point;
15
+ effectiveLinkAttachPoint: Point;
16
+ rotationPivot: Point;
17
+ };
18
+ export type PortOrientationContext = {
19
+ localRotation: number;
20
+ rotation: number;
21
+ offset: Point;
22
+ nodeAnchorPoint: Point;
23
+ side?: BorderSide;
24
+ normal?: Point;
25
+ };
26
+ export declare const borderSideToNormal: (side: BorderSide) => Point;
27
+ export declare const resolvePortGeometryPoints: (port: Pick<PortData, 'placementPoint' | 'linkAttachPoint' | 'externalLinkAttachPoint' | 'internalLinkAttachPoint' | 'rotationPivot'>, attachMode: PortLinkAttachMode) => PortGeometryPoints;
28
+ export declare const resolvePortOrientationContext: (options: {
29
+ port: Pick<PortData, 'shapeId' | 'style' | 'moveMode' | 'orientToHostBorder' | 'anchorCenter' | 'placementPoint' | 'linkAttachPoint' | 'externalLinkAttachPoint' | 'internalLinkAttachPoint' | 'rotationPivot' | 'size'>;
30
+ worldPlacement: Point;
31
+ host: HostElementLike | null;
32
+ shapeRegistry: ShapeRegistry;
33
+ attachMode: PortLinkAttachMode;
34
+ }) => PortOrientationContext;
35
+ export declare const resolvePortWorldTransform: (options: {
36
+ port: Pick<PortData, 'placementPoint' | 'linkAttachPoint' | 'externalLinkAttachPoint' | 'internalLinkAttachPoint' | 'rotationPivot'>;
37
+ worldPlacement: Point;
38
+ attachMode: PortLinkAttachMode;
39
+ orientation: Pick<PortOrientationContext, 'localRotation' | 'rotation' | 'offset' | 'nodeAnchorPoint'>;
40
+ }) => {
41
+ nodePosition: Point;
42
+ linkAttachWorld: Point;
43
+ };
44
+ export {};
@@ -24,6 +24,7 @@ type DiagramContainer = {
24
24
  type MoveConstraint = 'free' | 'inside' | 'border';
25
25
  type BorderSide = 'left' | 'right' | 'top' | 'bottom';
26
26
  type HostAnchorPreset = 'vertices' | 'cardinal';
27
+ type PortLinkAttachMode = 'external' | 'internal';
27
28
  type PortAnchor = {
28
29
  id: string;
29
30
  position: Point;
@@ -31,6 +32,20 @@ type PortAnchor = {
31
32
  normal?: Point;
32
33
  meta?: Record<string, unknown>;
33
34
  };
35
+ type PortBorderTransformContext = {
36
+ side: BorderSide;
37
+ normal: Point;
38
+ hostRect: Rect;
39
+ attachMode: PortLinkAttachMode;
40
+ effectiveLinkAttachPoint: Point;
41
+ placementPoint: Point;
42
+ rotationPivot: Point;
43
+ portSize?: Size;
44
+ };
45
+ type PortBorderTransformResult = {
46
+ rotation?: number;
47
+ offset?: Point;
48
+ };
34
49
  type PortAnchorConstraint = {
35
50
  preset: HostAnchorPreset;
36
51
  fallback?: 'nearest';
@@ -126,6 +141,15 @@ type ElementLayoutMode = 'manual' | 'horizontal' | 'vertical';
126
141
  type ElementLayoutAlign = 'start' | 'center' | 'end';
127
142
  type ElementLayoutChildFitMainAxis = 'none' | 'distribute';
128
143
  type ElementLayoutChildFitCrossAxis = 'none' | 'stretch';
144
+ type ElementLayoutLabelReservedSpaceMode = 'none' | 'fixed' | 'flexible';
145
+ type ElementLayoutLabelReservedSpacePlacement = 'top';
146
+ type ElementLayoutLabelReservedSpace = {
147
+ mode?: ElementLayoutLabelReservedSpaceMode;
148
+ placement?: ElementLayoutLabelReservedSpacePlacement;
149
+ size?: number;
150
+ minSize?: number;
151
+ maxSize?: number;
152
+ };
129
153
  type TextLayoutBoundsMode = 'owner-width' | 'owner-box' | 'fixed';
130
154
  type TextLayoutWrapMode = 'none' | 'word' | 'char';
131
155
  type TextLayoutOverflowMode = 'clip' | 'ellipsis-end' | 'ellipsis-middle' | 'ellipsis-start';
@@ -141,6 +165,7 @@ type ElementLayout = {
141
165
  childFitCrossAxis?: ElementLayoutChildFitCrossAxis;
142
166
  childFitMinSize?: Partial<Size>;
143
167
  childFitMaxSize?: Partial<Size>;
168
+ labelReservedSpace?: ElementLayoutLabelReservedSpace;
144
169
  };
145
170
  type TextLayout = {
146
171
  boundsMode?: TextLayoutBoundsMode;
@@ -195,6 +220,11 @@ type PortData = {
195
220
  moveMode?: MoveConstraint;
196
221
  anchorCenter?: boolean;
197
222
  orientToHostBorder?: boolean;
223
+ placementPoint?: Point;
224
+ linkAttachPoint?: Point;
225
+ externalLinkAttachPoint?: Point;
226
+ internalLinkAttachPoint?: Point;
227
+ rotationPivot?: Point;
198
228
  currentAnchorId?: string;
199
229
  };
200
230
  type ShapeDrawContext = {
@@ -414,7 +444,9 @@ type DiagramEngineHandle = {
414
444
  svgSize?: Size;
415
445
  projectToBorder?: (point: Point, rect: Rect) => Point;
416
446
  resolveBorderSide?: (point: Point, rect: Rect) => BorderSide;
447
+ resolveBorderNormal?: (point: Point, rect: Rect) => Point;
417
448
  resolvePortAnchors?: (rect: Rect, options: ResolvePortAnchorsOptions) => PortAnchor[];
449
+ resolvePortBorderTransform?: (context: PortBorderTransformContext) => PortBorderTransformResult | undefined;
418
450
  resolveHoverGeometry?: (rect: Rect) => ShapeHoverGeometry | undefined;
419
451
  resolveEllipseMidPoints?: (rect: Rect) => ShapeEllipseMidPointTarget[] | undefined;
420
452
  }) => void;
@@ -450,7 +482,25 @@ type SimpleShape = {
450
482
  kind: BuiltInShapeKind;
451
483
  style?: Record<string, unknown>;
452
484
  };
485
+ type DiagramImageExportOptions = {
486
+ mimeType?: string;
487
+ quality?: number;
488
+ pixelRatio?: number;
489
+ x?: number;
490
+ y?: number;
491
+ width?: number;
492
+ height?: number;
493
+ fitToContent?: boolean | {
494
+ padding?: number;
495
+ };
496
+ };
453
497
  type DiagramEditorHandle = DiagramEngineHandle & {
498
+ startLinkFromPort: (sourcePortId: string, pointer?: Point) => void;
499
+ updateLinkPreview: (pointer: Point) => void;
500
+ completeLinkToPort: (targetPortId: string) => void;
501
+ completeLinkToElement: (targetElementId: string, pointer: Point) => void;
502
+ cancelLink: () => void;
503
+ exportImage: (options?: DiagramImageExportOptions) => string;
454
504
  resize: (width: number, height: number) => void;
455
505
  setElementShapeHoverControls: (controls?: ElementShapeHoverControls) => void;
456
506
  destroy: () => void;