@coral-viz/viz 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 (191) hide show
  1. package/LICENSE +4 -0
  2. package/README.md +11 -0
  3. package/dist/compatibility/CompatibilityEdge.d.ts +106 -0
  4. package/dist/compatibility/CompatibilityEdge.d.ts.map +1 -0
  5. package/dist/compatibility/CompatibilityEdge.js +233 -0
  6. package/dist/compatibility/CompatibilityEdge.js.map +1 -0
  7. package/dist/compatibility/IncompatibilityTooltip.d.ts +44 -0
  8. package/dist/compatibility/IncompatibilityTooltip.d.ts.map +1 -0
  9. package/dist/compatibility/IncompatibilityTooltip.js +145 -0
  10. package/dist/compatibility/IncompatibilityTooltip.js.map +1 -0
  11. package/dist/compatibility/index.d.ts +10 -0
  12. package/dist/compatibility/index.d.ts.map +1 -0
  13. package/dist/compatibility/index.js +10 -0
  14. package/dist/compatibility/index.js.map +1 -0
  15. package/dist/compatibility/useEdgeCompatibility.d.ts +82 -0
  16. package/dist/compatibility/useEdgeCompatibility.d.ts.map +1 -0
  17. package/dist/compatibility/useEdgeCompatibility.js +170 -0
  18. package/dist/compatibility/useEdgeCompatibility.js.map +1 -0
  19. package/dist/compatibility/validateConnection.d.ts +56 -0
  20. package/dist/compatibility/validateConnection.d.ts.map +1 -0
  21. package/dist/compatibility/validateConnection.js +382 -0
  22. package/dist/compatibility/validateConnection.js.map +1 -0
  23. package/dist/components/EditContext.d.ts +45 -0
  24. package/dist/components/EditContext.d.ts.map +1 -0
  25. package/dist/components/EditContext.js +41 -0
  26. package/dist/components/EditContext.js.map +1 -0
  27. package/dist/components/ShapeRenderer.d.ts +35 -0
  28. package/dist/components/ShapeRenderer.d.ts.map +1 -0
  29. package/dist/components/ShapeRenderer.js +77 -0
  30. package/dist/components/ShapeRenderer.js.map +1 -0
  31. package/dist/components/SymbolNode.d.ts +53 -0
  32. package/dist/components/SymbolNode.d.ts.map +1 -0
  33. package/dist/components/SymbolNode.js +333 -0
  34. package/dist/components/SymbolNode.js.map +1 -0
  35. package/dist/components/index.d.ts +8 -0
  36. package/dist/components/index.d.ts.map +1 -0
  37. package/dist/components/index.js +10 -0
  38. package/dist/components/index.js.map +1 -0
  39. package/dist/components/nodes.d.ts +43 -0
  40. package/dist/components/nodes.d.ts.map +1 -0
  41. package/dist/components/nodes.js +111 -0
  42. package/dist/components/nodes.js.map +1 -0
  43. package/dist/editor/CoralEditor.d.ts +29 -0
  44. package/dist/editor/CoralEditor.d.ts.map +1 -0
  45. package/dist/editor/CoralEditor.js +112 -0
  46. package/dist/editor/CoralEditor.js.map +1 -0
  47. package/dist/editor/FileControls.d.ts +34 -0
  48. package/dist/editor/FileControls.d.ts.map +1 -0
  49. package/dist/editor/FileControls.js +139 -0
  50. package/dist/editor/FileControls.js.map +1 -0
  51. package/dist/editor/LayoutControls.d.ts +41 -0
  52. package/dist/editor/LayoutControls.d.ts.map +1 -0
  53. package/dist/editor/LayoutControls.js +124 -0
  54. package/dist/editor/LayoutControls.js.map +1 -0
  55. package/dist/editor/converter.d.ts +37 -0
  56. package/dist/editor/converter.d.ts.map +1 -0
  57. package/dist/editor/converter.js +256 -0
  58. package/dist/editor/converter.js.map +1 -0
  59. package/dist/editor/index.d.ts +8 -0
  60. package/dist/editor/index.d.ts.map +1 -0
  61. package/dist/editor/index.js +8 -0
  62. package/dist/editor/index.js.map +1 -0
  63. package/dist/file/deserialize.d.ts +15 -0
  64. package/dist/file/deserialize.d.ts.map +1 -0
  65. package/dist/file/deserialize.js +145 -0
  66. package/dist/file/deserialize.js.map +1 -0
  67. package/dist/file/index.d.ts +15 -0
  68. package/dist/file/index.d.ts.map +1 -0
  69. package/dist/file/index.js +20 -0
  70. package/dist/file/index.js.map +1 -0
  71. package/dist/file/migrate.d.ts +29 -0
  72. package/dist/file/migrate.d.ts.map +1 -0
  73. package/dist/file/migrate.js +103 -0
  74. package/dist/file/migrate.js.map +1 -0
  75. package/dist/file/schema.d.ts +385 -0
  76. package/dist/file/schema.d.ts.map +1 -0
  77. package/dist/file/schema.js +180 -0
  78. package/dist/file/schema.js.map +1 -0
  79. package/dist/file/serialize.d.ts +30 -0
  80. package/dist/file/serialize.d.ts.map +1 -0
  81. package/dist/file/serialize.js +218 -0
  82. package/dist/file/serialize.js.map +1 -0
  83. package/dist/file/validate.d.ts +21 -0
  84. package/dist/file/validate.d.ts.map +1 -0
  85. package/dist/file/validate.js +165 -0
  86. package/dist/file/validate.js.map +1 -0
  87. package/dist/index.d.ts +24 -0
  88. package/dist/index.d.ts.map +1 -0
  89. package/dist/index.js +42 -0
  90. package/dist/index.js.map +1 -0
  91. package/dist/layout/elk.d.ts +77 -0
  92. package/dist/layout/elk.d.ts.map +1 -0
  93. package/dist/layout/elk.js +379 -0
  94. package/dist/layout/elk.js.map +1 -0
  95. package/dist/layout/index.d.ts +12 -0
  96. package/dist/layout/index.d.ts.map +1 -0
  97. package/dist/layout/index.js +12 -0
  98. package/dist/layout/index.js.map +1 -0
  99. package/dist/layout/nodeSizing.d.ts +65 -0
  100. package/dist/layout/nodeSizing.d.ts.map +1 -0
  101. package/dist/layout/nodeSizing.js +319 -0
  102. package/dist/layout/nodeSizing.js.map +1 -0
  103. package/dist/layout/positionStability.d.ts +73 -0
  104. package/dist/layout/positionStability.d.ts.map +1 -0
  105. package/dist/layout/positionStability.js +199 -0
  106. package/dist/layout/positionStability.js.map +1 -0
  107. package/dist/layout/useAxisConstrain.d.ts +20 -0
  108. package/dist/layout/useAxisConstrain.d.ts.map +1 -0
  109. package/dist/layout/useAxisConstrain.js +106 -0
  110. package/dist/layout/useAxisConstrain.js.map +1 -0
  111. package/dist/layout/useDiagramState.d.ts +92 -0
  112. package/dist/layout/useDiagramState.d.ts.map +1 -0
  113. package/dist/layout/useDiagramState.js +256 -0
  114. package/dist/layout/useDiagramState.js.map +1 -0
  115. package/dist/layout/useLayoutHistory.d.ts +53 -0
  116. package/dist/layout/useLayoutHistory.d.ts.map +1 -0
  117. package/dist/layout/useLayoutHistory.js +124 -0
  118. package/dist/layout/useLayoutHistory.js.map +1 -0
  119. package/dist/properties/NodePropertiesPanel.d.ts +47 -0
  120. package/dist/properties/NodePropertiesPanel.d.ts.map +1 -0
  121. package/dist/properties/NodePropertiesPanel.js +199 -0
  122. package/dist/properties/NodePropertiesPanel.js.map +1 -0
  123. package/dist/properties/index.d.ts +10 -0
  124. package/dist/properties/index.d.ts.map +1 -0
  125. package/dist/properties/index.js +10 -0
  126. package/dist/properties/index.js.map +1 -0
  127. package/dist/properties/propertyUtils.d.ts +60 -0
  128. package/dist/properties/propertyUtils.d.ts.map +1 -0
  129. package/dist/properties/propertyUtils.js +89 -0
  130. package/dist/properties/propertyUtils.js.map +1 -0
  131. package/dist/settings/FontSettingsForm.d.ts +28 -0
  132. package/dist/settings/FontSettingsForm.d.ts.map +1 -0
  133. package/dist/settings/FontSettingsForm.js +129 -0
  134. package/dist/settings/FontSettingsForm.js.map +1 -0
  135. package/dist/settings/LayoutSettingsForm.d.ts +37 -0
  136. package/dist/settings/LayoutSettingsForm.d.ts.map +1 -0
  137. package/dist/settings/LayoutSettingsForm.js +165 -0
  138. package/dist/settings/LayoutSettingsForm.js.map +1 -0
  139. package/dist/settings/SettingsPanel.d.ts +55 -0
  140. package/dist/settings/SettingsPanel.d.ts.map +1 -0
  141. package/dist/settings/SettingsPanel.js +84 -0
  142. package/dist/settings/SettingsPanel.js.map +1 -0
  143. package/dist/settings/index.d.ts +13 -0
  144. package/dist/settings/index.d.ts.map +1 -0
  145. package/dist/settings/index.js +13 -0
  146. package/dist/settings/index.js.map +1 -0
  147. package/dist/settings/useSettings.d.ts +51 -0
  148. package/dist/settings/useSettings.d.ts.map +1 -0
  149. package/dist/settings/useSettings.js +154 -0
  150. package/dist/settings/useSettings.js.map +1 -0
  151. package/dist/text-editor/SplitEditor.d.ts +72 -0
  152. package/dist/text-editor/SplitEditor.d.ts.map +1 -0
  153. package/dist/text-editor/SplitEditor.js +172 -0
  154. package/dist/text-editor/SplitEditor.js.map +1 -0
  155. package/dist/text-editor/TextEditor.d.ts +53 -0
  156. package/dist/text-editor/TextEditor.d.ts.map +1 -0
  157. package/dist/text-editor/TextEditor.js +181 -0
  158. package/dist/text-editor/TextEditor.js.map +1 -0
  159. package/dist/text-editor/hooks/useBidirectionalSync.d.ts +106 -0
  160. package/dist/text-editor/hooks/useBidirectionalSync.d.ts.map +1 -0
  161. package/dist/text-editor/hooks/useBidirectionalSync.js +151 -0
  162. package/dist/text-editor/hooks/useBidirectionalSync.js.map +1 -0
  163. package/dist/text-editor/index.d.ts +9 -0
  164. package/dist/text-editor/index.d.ts.map +1 -0
  165. package/dist/text-editor/index.js +11 -0
  166. package/dist/text-editor/index.js.map +1 -0
  167. package/dist/types.d.ts +242 -0
  168. package/dist/types.d.ts.map +1 -0
  169. package/dist/types.js +5 -0
  170. package/dist/types.js.map +1 -0
  171. package/dist/waypoints/index.d.ts +8 -0
  172. package/dist/waypoints/index.d.ts.map +1 -0
  173. package/dist/waypoints/index.js +7 -0
  174. package/dist/waypoints/index.js.map +1 -0
  175. package/dist/waypoints/operations.d.ts +29 -0
  176. package/dist/waypoints/operations.d.ts.map +1 -0
  177. package/dist/waypoints/operations.js +85 -0
  178. package/dist/waypoints/operations.js.map +1 -0
  179. package/dist/waypoints/router.d.ts +23 -0
  180. package/dist/waypoints/router.d.ts.map +1 -0
  181. package/dist/waypoints/router.js +109 -0
  182. package/dist/waypoints/router.js.map +1 -0
  183. package/dist/waypoints/types.d.ts +15 -0
  184. package/dist/waypoints/types.d.ts.map +1 -0
  185. package/dist/waypoints/types.js +5 -0
  186. package/dist/waypoints/types.js.map +1 -0
  187. package/dist/waypoints/useWaypointManager.d.ts +38 -0
  188. package/dist/waypoints/useWaypointManager.d.ts.map +1 -0
  189. package/dist/waypoints/useWaypointManager.js +106 -0
  190. package/dist/waypoints/useWaypointManager.js.map +1 -0
  191. package/package.json +76 -0
package/LICENSE ADDED
@@ -0,0 +1,4 @@
1
+ Copyright 2026 Coral contributors
2
+
3
+ Licensed under the Apache License, Version 2.0. You may obtain a copy at
4
+ https://www.apache.org/licenses/LICENSE-2.0
package/README.md ADDED
@@ -0,0 +1,11 @@
1
+ # @coral-viz/viz
2
+
3
+ React Flow components, ELK layout, GraphIR projection, file persistence, and
4
+ editing helpers for Coral diagrams. See the
5
+ [Coral repository](https://github.com/coreyt/coral) for setup and examples.
6
+
7
+ Applications that render the editor must import React Flow's stylesheet once:
8
+
9
+ ```ts
10
+ import '@xyflow/react/dist/style.css';
11
+ ```
@@ -0,0 +1,106 @@
1
+ /**
2
+ * CompatibilityEdge Component (CORAL-REQ-010)
3
+ *
4
+ * A custom React Flow edge component that displays visual feedback
5
+ * for edge compatibility status (incompatible, warning, compatible).
6
+ */
7
+ import { type CSSProperties } from 'react';
8
+ import { type EdgeProps, type Edge } from '@xyflow/react';
9
+ import type { EdgeCompatibilityStatus, ConnectionValidation, Position } from '../types.js';
10
+ /**
11
+ * Build an SVG path string from routed bend points.
12
+ * Produces orthogonal (right-angle) line segments.
13
+ */
14
+ export declare function buildRoutedPath(startPoint: Position, endPoint: Position, bendPoints: Position[]): string;
15
+ /**
16
+ * Edge style configuration for each compatibility status
17
+ */
18
+ export interface EdgeStyleConfig {
19
+ stroke: string;
20
+ strokeWidth: number;
21
+ strokeDasharray?: string;
22
+ animated?: boolean;
23
+ }
24
+ /**
25
+ * Get edge style based on compatibility status
26
+ */
27
+ export declare function getEdgeStyleForStatus(status: EdgeCompatibilityStatus | undefined, baseStyle?: CSSProperties): CSSProperties;
28
+ /**
29
+ * Waypoint data for rendering handles on edges (CORAL-REQ-015)
30
+ */
31
+ export interface WaypointHandleData {
32
+ id: string;
33
+ x: number;
34
+ y: number;
35
+ type: 'corner' | 'smooth';
36
+ }
37
+ /**
38
+ * Extended edge data for compatibility-aware edges
39
+ */
40
+ export interface CompatibilityEdgeData {
41
+ /** Compatibility status */
42
+ compatibilityStatus?: EdgeCompatibilityStatus;
43
+ /** Validation result with message */
44
+ validation?: ConnectionValidation;
45
+ /** Edge label */
46
+ label?: string;
47
+ /** Endpoint labels, so the edge can name its connection for a screen reader */
48
+ sourceLabel?: string;
49
+ targetLabel?: string;
50
+ /** Force tooltip to be visible (e.g. when hovering a diagnostics log entry) */
51
+ forceShowTooltip?: boolean;
52
+ /** Waypoints for manual edge routing (CORAL-REQ-015) */
53
+ waypoints?: WaypointHandleData[];
54
+ /** Callback when user double-clicks edge to add a waypoint */
55
+ onWaypointAdd?: (edgeId: string, position: Position) => void;
56
+ /** Callback when user right-clicks a waypoint to remove it */
57
+ onWaypointRemove?: (edgeId: string, waypointId: string) => void;
58
+ /** Callback when user starts dragging a waypoint */
59
+ onWaypointDrag?: (edgeId: string, waypointId: string, position: Position) => void;
60
+ /** Custom properties */
61
+ [key: string]: unknown;
62
+ }
63
+ /**
64
+ * Props for the CompatibilityEdge component
65
+ */
66
+ export interface CompatibilityEdgeProps extends EdgeProps<Edge<CompatibilityEdgeData>> {
67
+ /** Path type for the edge */
68
+ pathType?: 'bezier' | 'smoothstep';
69
+ }
70
+ /**
71
+ * CompatibilityEdge - React Flow edge with compatibility feedback
72
+ *
73
+ * This component renders an edge with visual styling based on its
74
+ * compatibility status (from notation rules). Incompatible edges
75
+ * are shown in red, warnings in amber, and compatible in the default color.
76
+ *
77
+ * A tooltip is shown on hover for incompatible/warning edges explaining
78
+ * the issue.
79
+ *
80
+ * @example
81
+ * ```tsx
82
+ * // In your React Flow configuration
83
+ * const edgeTypes = {
84
+ * compatibility: CompatibilityEdge,
85
+ * };
86
+ *
87
+ * // Usage with useEdgeCompatibility hook
88
+ * const { edgeCompatibility } = useEdgeCompatibility({ nodes, edges, notationId });
89
+ *
90
+ * const styledEdges = edges.map(edge => {
91
+ * const compat = edgeCompatibility.find(ec => ec.edgeId === edge.id);
92
+ * return {
93
+ * ...edge,
94
+ * type: 'compatibility',
95
+ * data: {
96
+ * ...edge.data,
97
+ * compatibilityStatus: compat?.status,
98
+ * validation: compat?.validation,
99
+ * },
100
+ * };
101
+ * });
102
+ * ```
103
+ */
104
+ export declare const CompatibilityEdge: import("react").MemoExoticComponent<({ id, sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition, data, markerEnd, style, selected, pathType, }: CompatibilityEdgeProps) => import("react").JSX.Element>;
105
+ export default CompatibilityEdge;
106
+ //# sourceMappingURL=CompatibilityEdge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CompatibilityEdge.d.ts","sourceRoot":"","sources":["../../src/compatibility/CompatibilityEdge.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAA+B,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AACxE,OAAO,EAKL,KAAK,SAAS,EACd,KAAK,IAAI,EACV,MAAM,eAAe,CAAC;AAEvB,OAAO,KAAK,EAAE,uBAAuB,EAAE,oBAAoB,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE3F;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,UAAU,EAAE,QAAQ,EACpB,QAAQ,EAAE,QAAQ,EAClB,UAAU,EAAE,QAAQ,EAAE,GACrB,MAAM,CAOR;AAqBD;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,uBAAuB,GAAG,SAAS,EAC3C,SAAS,CAAC,EAAE,aAAa,GACxB,aAAa,CA0Bf;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,IAAI,EAAE,QAAQ,GAAG,QAAQ,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,2BAA2B;IAC3B,mBAAmB,CAAC,EAAE,uBAAuB,CAAC;IAC9C,qCAAqC;IACrC,UAAU,CAAC,EAAE,oBAAoB,CAAC;IAClC,iBAAiB;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+EAA+E;IAC/E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+EAA+E;IAC/E,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,wDAAwD;IACxD,SAAS,CAAC,EAAE,kBAAkB,EAAE,CAAC;IACjC,8DAA8D;IAC9D,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,KAAK,IAAI,CAAC;IAC7D,8DAA8D;IAC9D,gBAAgB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IAChE,oDAAoD;IACpD,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,KAAK,IAAI,CAAC;IAClF,wBAAwB;IACxB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,sBAAuB,SAAQ,SAAS,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;IACpF,6BAA6B;IAC7B,QAAQ,CAAC,EAAE,QAAQ,GAAG,YAAY,CAAC;CACpC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,eAAO,MAAM,iBAAiB,gKAa3B,sBAAsB,iCA8NvB,CAAC;AAEH,eAAe,iBAAiB,CAAC"}
@@ -0,0 +1,233 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ /**
3
+ * CompatibilityEdge Component (CORAL-REQ-010)
4
+ *
5
+ * A custom React Flow edge component that displays visual feedback
6
+ * for edge compatibility status (incompatible, warning, compatible).
7
+ */
8
+ import { memo, useState, useCallback } from 'react';
9
+ import { BaseEdge, EdgeLabelRenderer, getBezierPath, getSmoothStepPath, } from '@xyflow/react';
10
+ import { IncompatibilityTooltip } from './IncompatibilityTooltip.js';
11
+ /**
12
+ * Build an SVG path string from routed bend points.
13
+ * Produces orthogonal (right-angle) line segments.
14
+ */
15
+ export function buildRoutedPath(startPoint, endPoint, bendPoints) {
16
+ const allPoints = [startPoint, ...bendPoints, endPoint];
17
+ const parts = [`M ${allPoints[0].x} ${allPoints[0].y}`];
18
+ for (let i = 1; i < allPoints.length; i++) {
19
+ parts.push(`L ${allPoints[i].x} ${allPoints[i].y}`);
20
+ }
21
+ return parts.join(' ');
22
+ }
23
+ /**
24
+ * Compute the midpoint of a routed path for label placement.
25
+ */
26
+ function routedPathMidpoint(startPoint, endPoint, bendPoints) {
27
+ const allPoints = [startPoint, ...bendPoints, endPoint];
28
+ const midIdx = Math.floor(allPoints.length / 2);
29
+ if (allPoints.length % 2 === 0) {
30
+ // Even number of points: midpoint between two middle points
31
+ const a = allPoints[midIdx - 1];
32
+ const b = allPoints[midIdx];
33
+ return { x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 };
34
+ }
35
+ return allPoints[midIdx];
36
+ }
37
+ /**
38
+ * Get edge style based on compatibility status
39
+ */
40
+ export function getEdgeStyleForStatus(status, baseStyle) {
41
+ const baseStroke = baseStyle?.stroke || '#666666';
42
+ const baseWidth = baseStyle?.strokeWidth || 1.5;
43
+ switch (status) {
44
+ case 'incompatible':
45
+ return {
46
+ ...baseStyle,
47
+ stroke: '#ef4444', // red-500
48
+ strokeWidth: baseWidth + 0.5,
49
+ };
50
+ case 'warning':
51
+ return {
52
+ ...baseStyle,
53
+ stroke: '#f59e0b', // amber-500
54
+ strokeWidth: baseWidth + 0.5,
55
+ strokeDasharray: '5,3',
56
+ };
57
+ case 'compatible':
58
+ default:
59
+ return {
60
+ ...baseStyle,
61
+ stroke: baseStroke,
62
+ strokeWidth: baseWidth,
63
+ };
64
+ }
65
+ }
66
+ /**
67
+ * CompatibilityEdge - React Flow edge with compatibility feedback
68
+ *
69
+ * This component renders an edge with visual styling based on its
70
+ * compatibility status (from notation rules). Incompatible edges
71
+ * are shown in red, warnings in amber, and compatible in the default color.
72
+ *
73
+ * A tooltip is shown on hover for incompatible/warning edges explaining
74
+ * the issue.
75
+ *
76
+ * @example
77
+ * ```tsx
78
+ * // In your React Flow configuration
79
+ * const edgeTypes = {
80
+ * compatibility: CompatibilityEdge,
81
+ * };
82
+ *
83
+ * // Usage with useEdgeCompatibility hook
84
+ * const { edgeCompatibility } = useEdgeCompatibility({ nodes, edges, notationId });
85
+ *
86
+ * const styledEdges = edges.map(edge => {
87
+ * const compat = edgeCompatibility.find(ec => ec.edgeId === edge.id);
88
+ * return {
89
+ * ...edge,
90
+ * type: 'compatibility',
91
+ * data: {
92
+ * ...edge.data,
93
+ * compatibilityStatus: compat?.status,
94
+ * validation: compat?.validation,
95
+ * },
96
+ * };
97
+ * });
98
+ * ```
99
+ */
100
+ export const CompatibilityEdge = memo(function CompatibilityEdge({ id, sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition, data, markerEnd, style, selected, pathType = 'smoothstep', }) {
101
+ const [showTooltip, setShowTooltip] = useState(false);
102
+ const status = data?.compatibilityStatus;
103
+ const validation = data?.validation;
104
+ const label = data?.label;
105
+ const isTooltipVisible = showTooltip || (data?.forceShowTooltip ?? false);
106
+ // Waypoint data (CORAL-REQ-015)
107
+ const waypoints = data?.waypoints;
108
+ const onWaypointAdd = data?.onWaypointAdd;
109
+ const onWaypointRemove = data?.onWaypointRemove;
110
+ const onWaypointDrag = data?.onWaypointDrag;
111
+ // Check for routed path data (from edge router or ELK sections)
112
+ const routedPath = data?.routedPath;
113
+ // Compute edge path — use routed bend points when available, else smoothstep/bezier
114
+ let edgePath;
115
+ let labelX;
116
+ let labelY;
117
+ // Check if routed path is still valid (endpoints near current handle positions).
118
+ // After a node drag, ELK's absolute coordinates become stale — fall back to smoothstep.
119
+ const STALE_THRESHOLD = 5;
120
+ const isRoutedPathFresh = routedPath &&
121
+ Math.abs(routedPath.startPoint.x - sourceX) < STALE_THRESHOLD &&
122
+ Math.abs(routedPath.startPoint.y - sourceY) < STALE_THRESHOLD &&
123
+ Math.abs(routedPath.endPoint.x - targetX) < STALE_THRESHOLD &&
124
+ Math.abs(routedPath.endPoint.y - targetY) < STALE_THRESHOLD;
125
+ if (isRoutedPathFresh) {
126
+ // Use ELK's full computed path (startPoint, bendPoints, endPoint).
127
+ // These coordinates are consistent with each other since ELK computed them
128
+ // as a unified route.
129
+ edgePath = buildRoutedPath(routedPath.startPoint, routedPath.endPoint, routedPath.bendPoints);
130
+ const mid = routedPathMidpoint(routedPath.startPoint, routedPath.endPoint, routedPath.bendPoints);
131
+ labelX = mid.x;
132
+ labelY = mid.y;
133
+ }
134
+ else {
135
+ const [computedPath, lx, ly] = pathType === 'smoothstep'
136
+ ? getSmoothStepPath({
137
+ sourceX,
138
+ sourceY,
139
+ sourcePosition,
140
+ targetX,
141
+ targetY,
142
+ targetPosition,
143
+ })
144
+ : getBezierPath({
145
+ sourceX,
146
+ sourceY,
147
+ sourcePosition,
148
+ targetX,
149
+ targetY,
150
+ targetPosition,
151
+ });
152
+ edgePath = computedPath;
153
+ labelX = lx;
154
+ labelY = ly;
155
+ }
156
+ // Apply compatibility styling
157
+ const edgeStyle = getEdgeStyleForStatus(status, style);
158
+ // Show tooltip on hover for incompatible/warning edges
159
+ const handleMouseEnter = useCallback(() => {
160
+ if (status === 'incompatible' || status === 'warning') {
161
+ setShowTooltip(true);
162
+ }
163
+ }, [status]);
164
+ const handleMouseLeave = useCallback(() => {
165
+ setShowTooltip(false);
166
+ }, []);
167
+ // Double-click on edge to add waypoint (CORAL-REQ-015)
168
+ const handleDoubleClick = useCallback((e) => {
169
+ if (!onWaypointAdd)
170
+ return;
171
+ // Get click position in SVG coordinates
172
+ const svg = e.target.closest?.('svg');
173
+ if (!svg || typeof svg.createSVGPoint !== 'function') {
174
+ onWaypointAdd(id, { x: e.clientX, y: e.clientY });
175
+ return;
176
+ }
177
+ const pt = svg.createSVGPoint();
178
+ pt.x = e.clientX;
179
+ pt.y = e.clientY;
180
+ const ctm = svg.getScreenCTM();
181
+ if (ctm) {
182
+ const svgPt = pt.matrixTransform(ctm.inverse());
183
+ onWaypointAdd(id, { x: svgPt.x, y: svgPt.y });
184
+ }
185
+ else {
186
+ onWaypointAdd(id, { x: e.clientX, y: e.clientY });
187
+ }
188
+ }, [id, onWaypointAdd]);
189
+ return (_jsxs(_Fragment, { children: [_jsx("path", { d: edgePath, fill: "none", strokeWidth: 20, stroke: "transparent", style: { cursor: 'pointer' }, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, onDoubleClick: handleDoubleClick }), _jsx(BaseEdge, { id: id, path: edgePath, markerEnd: markerEnd, style: edgeStyle, interactionWidth: 0, "aria-label": `Connection from ${data?.sourceLabel ?? 'source'} to ${data?.targetLabel ?? 'target'}` +
190
+ (label ? `, ${label}` : '') +
191
+ (status === 'incompatible'
192
+ ? ', not allowed by this notation'
193
+ : status === 'warning'
194
+ ? ', has a warning'
195
+ : '') }), (label || isTooltipVisible) && (_jsx(EdgeLabelRenderer, { children: _jsx("div", { style: {
196
+ position: 'absolute',
197
+ transform: `translate(-50%, -50%) translate(${labelX}px,${labelY}px)`,
198
+ pointerEvents: 'all',
199
+ }, className: "nodrag nopan", onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, children: _jsxs(IncompatibilityTooltip, { status: status, validation: validation, show: isTooltipVisible, position: "top", children: [label && (_jsx("div", { style: {
200
+ backgroundColor: 'white',
201
+ padding: '2px 6px',
202
+ borderRadius: '3px',
203
+ fontSize: '11px',
204
+ border: `1px solid ${edgeStyle.stroke || '#666'}`,
205
+ }, children: label })), !label && isTooltipVisible && (_jsx("div", { style: {
206
+ width: '12px',
207
+ height: '12px',
208
+ backgroundColor: status === 'incompatible' ? '#ef4444' : '#f59e0b',
209
+ borderRadius: '50%',
210
+ border: '2px solid white',
211
+ boxShadow: '0 1px 3px rgba(0,0,0,0.2)',
212
+ } }))] }) }) })), selected && waypoints && waypoints.length > 0 && (_jsx(EdgeLabelRenderer, { children: waypoints.map((wp) => (_jsx("div", { "data-waypoint-id": wp.id, className: "nodrag nopan", style: {
213
+ position: 'absolute',
214
+ transform: `translate(-50%, -50%) translate(${wp.x}px,${wp.y}px)`,
215
+ width: '8px',
216
+ height: '8px',
217
+ backgroundColor: '#3b82f6',
218
+ borderRadius: '50%',
219
+ border: '1.5px solid white',
220
+ boxShadow: '0 1px 3px rgba(0,0,0,0.3)',
221
+ cursor: 'grab',
222
+ pointerEvents: 'all',
223
+ }, onContextMenu: (e) => {
224
+ e.preventDefault();
225
+ onWaypointRemove?.(id, wp.id);
226
+ }, onMouseDown: (e) => {
227
+ if (e.button === 0 && onWaypointDrag) {
228
+ onWaypointDrag(id, wp.id, { x: wp.x, y: wp.y });
229
+ }
230
+ } }, wp.id))) }))] }));
231
+ });
232
+ export default CompatibilityEdge;
233
+ //# sourceMappingURL=CompatibilityEdge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CompatibilityEdge.js","sourceRoot":"","sources":["../../src/compatibility/CompatibilityEdge.tsx"],"names":[],"mappings":";AAAA;;;;;GAKG;AAEH,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAsB,MAAM,OAAO,CAAC;AACxE,OAAO,EACL,QAAQ,EACR,iBAAiB,EACjB,aAAa,EACb,iBAAiB,GAGlB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAGrE;;;GAGG;AACH,MAAM,UAAU,eAAe,CAC7B,UAAoB,EACpB,QAAkB,EAClB,UAAsB;IAEtB,MAAM,SAAS,GAAG,CAAC,UAAU,EAAE,GAAG,UAAU,EAAE,QAAQ,CAAC,CAAC;IACxD,MAAM,KAAK,GAAG,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACxD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC1C,KAAK,CAAC,IAAI,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACtD,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC;AAED;;GAEG;AACH,SAAS,kBAAkB,CACzB,UAAoB,EACpB,QAAkB,EAClB,UAAsB;IAEtB,MAAM,SAAS,GAAG,CAAC,UAAU,EAAE,GAAG,UAAU,EAAE,QAAQ,CAAC,CAAC;IACxD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAChD,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;QAC/B,4DAA4D;QAC5D,MAAM,CAAC,GAAG,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAChC,MAAM,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;QAC5B,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;IACpD,CAAC;IACD,OAAO,SAAS,CAAC,MAAM,CAAC,CAAC;AAC3B,CAAC;AAYD;;GAEG;AACH,MAAM,UAAU,qBAAqB,CACnC,MAA2C,EAC3C,SAAyB;IAEzB,MAAM,UAAU,GAAI,SAAS,EAAE,MAAiB,IAAI,SAAS,CAAC;IAC9D,MAAM,SAAS,GAAI,SAAS,EAAE,WAAsB,IAAI,GAAG,CAAC;IAE5D,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,cAAc;YACjB,OAAO;gBACL,GAAG,SAAS;gBACZ,MAAM,EAAE,SAAS,EAAE,UAAU;gBAC7B,WAAW,EAAE,SAAS,GAAG,GAAG;aAC7B,CAAC;QACJ,KAAK,SAAS;YACZ,OAAO;gBACL,GAAG,SAAS;gBACZ,MAAM,EAAE,SAAS,EAAE,YAAY;gBAC/B,WAAW,EAAE,SAAS,GAAG,GAAG;gBAC5B,eAAe,EAAE,KAAK;aACvB,CAAC;QACJ,KAAK,YAAY,CAAC;QAClB;YACE,OAAO;gBACL,GAAG,SAAS;gBACZ,MAAM,EAAE,UAAU;gBAClB,WAAW,EAAE,SAAS;aACvB,CAAC;IACN,CAAC;AACH,CAAC;AA+CD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,CAAC,SAAS,iBAAiB,CAAC,EAC/D,EAAE,EACF,OAAO,EACP,OAAO,EACP,OAAO,EACP,OAAO,EACP,cAAc,EACd,cAAc,EACd,IAAI,EACJ,SAAS,EACT,KAAK,EACL,QAAQ,EACR,QAAQ,GAAG,YAAY,GACA;IACvB,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAEtD,MAAM,MAAM,GAAG,IAAI,EAAE,mBAAmB,CAAC;IACzC,MAAM,UAAU,GAAG,IAAI,EAAE,UAAU,CAAC;IACpC,MAAM,KAAK,GAAG,IAAI,EAAE,KAAK,CAAC;IAC1B,MAAM,gBAAgB,GAAG,WAAW,IAAI,CAAC,IAAI,EAAE,gBAAgB,IAAI,KAAK,CAAC,CAAC;IAE1E,gCAAgC;IAChC,MAAM,SAAS,GAAG,IAAI,EAAE,SAAS,CAAC;IAClC,MAAM,aAAa,GAAG,IAAI,EAAE,aAAsE,CAAC;IACnG,MAAM,gBAAgB,GAAG,IAAI,EAAE,gBAAwE,CAAC;IACxG,MAAM,cAAc,GAAG,IAAI,EAAE,cAAqF,CAAC;IAEnH,gEAAgE;IAChE,MAAM,UAAU,GAAG,IAAI,EAAE,UAEZ,CAAC;IAEd,oFAAoF;IACpF,IAAI,QAAgB,CAAC;IACrB,IAAI,MAAc,CAAC;IACnB,IAAI,MAAc,CAAC;IAEnB,iFAAiF;IACjF,wFAAwF;IACxF,MAAM,eAAe,GAAG,CAAC,CAAC;IAC1B,MAAM,iBAAiB,GACrB,UAAU;QACV,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,GAAG,OAAO,CAAC,GAAG,eAAe;QAC7D,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,GAAG,OAAO,CAAC,GAAG,eAAe;QAC7D,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,GAAG,OAAO,CAAC,GAAG,eAAe;QAC3D,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,GAAG,OAAO,CAAC,GAAG,eAAe,CAAC;IAE9D,IAAI,iBAAiB,EAAE,CAAC;QACtB,mEAAmE;QACnE,2EAA2E;QAC3E,sBAAsB;QACtB,QAAQ,GAAG,eAAe,CAAC,UAAW,CAAC,UAAU,EAAE,UAAW,CAAC,QAAQ,EAAE,UAAW,CAAC,UAAU,CAAC,CAAC;QACjG,MAAM,GAAG,GAAG,kBAAkB,CAAC,UAAW,CAAC,UAAU,EAAE,UAAW,CAAC,QAAQ,EAAE,UAAW,CAAC,UAAU,CAAC,CAAC;QACrG,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC;QACf,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC;IACjB,CAAC;SAAM,CAAC;QACN,MAAM,CAAC,YAAY,EAAE,EAAE,EAAE,EAAE,CAAC,GAC1B,QAAQ,KAAK,YAAY;YACvB,CAAC,CAAC,iBAAiB,CAAC;gBAChB,OAAO;gBACP,OAAO;gBACP,cAAc;gBACd,OAAO;gBACP,OAAO;gBACP,cAAc;aACf,CAAC;YACJ,CAAC,CAAC,aAAa,CAAC;gBACZ,OAAO;gBACP,OAAO;gBACP,cAAc;gBACd,OAAO;gBACP,OAAO;gBACP,cAAc;aACf,CAAC,CAAC;QACT,QAAQ,GAAG,YAAY,CAAC;QACxB,MAAM,GAAG,EAAE,CAAC;QACZ,MAAM,GAAG,EAAE,CAAC;IACd,CAAC;IAED,8BAA8B;IAC9B,MAAM,SAAS,GAAG,qBAAqB,CAAC,MAAM,EAAE,KAAsB,CAAC,CAAC;IAExE,uDAAuD;IACvD,MAAM,gBAAgB,GAAG,WAAW,CAAC,GAAG,EAAE;QACxC,IAAI,MAAM,KAAK,cAAc,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACtD,cAAc,CAAC,IAAI,CAAC,CAAC;QACvB,CAAC;IACH,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IAEb,MAAM,gBAAgB,GAAG,WAAW,CAAC,GAAG,EAAE;QACxC,cAAc,CAAC,KAAK,CAAC,CAAC;IACxB,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,uDAAuD;IACvD,MAAM,iBAAiB,GAAG,WAAW,CACnC,CAAC,CAAmB,EAAE,EAAE;QACtB,IAAI,CAAC,aAAa;YAAE,OAAO;QAC3B,wCAAwC;QACxC,MAAM,GAAG,GAAI,CAAC,CAAC,MAAqB,CAAC,OAAO,EAAE,CAAC,KAAK,CAAyB,CAAC;QAC9E,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,CAAC,cAAc,KAAK,UAAU,EAAE,CAAC;YACrD,aAAa,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;YAClD,OAAO;QACT,CAAC;QACD,MAAM,EAAE,GAAG,GAAG,CAAC,cAAc,EAAE,CAAC;QAChC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC;QACjB,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC;QACjB,MAAM,GAAG,GAAG,GAAG,CAAC,YAAY,EAAE,CAAC;QAC/B,IAAI,GAAG,EAAE,CAAC;YACR,MAAM,KAAK,GAAG,EAAE,CAAC,eAAe,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;YAChD,aAAa,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;QAChD,CAAC;aAAM,CAAC;YACN,aAAa,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;QACpD,CAAC;IACH,CAAC,EACD,CAAC,EAAE,EAAE,aAAa,CAAC,CACpB,CAAC;IAEF,OAAO,CACL,8BAEE,eACE,CAAC,EAAE,QAAQ,EACX,IAAI,EAAC,MAAM,EACX,WAAW,EAAE,EAAE,EACf,MAAM,EAAC,aAAa,EACpB,KAAK,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,EAC5B,YAAY,EAAE,gBAAgB,EAC9B,YAAY,EAAE,gBAAgB,EAC9B,aAAa,EAAE,iBAAiB,GAChC,EAIF,KAAC,QAAQ,IACP,EAAE,EAAE,EAAE,EACN,IAAI,EAAE,QAAQ,EACd,SAAS,EAAE,SAAS,EACpB,KAAK,EAAE,SAAS,EAChB,gBAAgB,EAAE,CAAC,gBAEjB,mBAAmB,IAAI,EAAE,WAAW,IAAI,QAAQ,OAAO,IAAI,EAAE,WAAW,IAAI,QAAQ,EAAE;oBACtF,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBAC3B,CAAC,MAAM,KAAK,cAAc;wBACxB,CAAC,CAAC,gCAAgC;wBAClC,CAAC,CAAC,MAAM,KAAK,SAAS;4BACpB,CAAC,CAAC,iBAAiB;4BACnB,CAAC,CAAC,EAAE,CAAC,GAEX,EAGD,CAAC,KAAK,IAAI,gBAAgB,CAAC,IAAI,CAC9B,KAAC,iBAAiB,cAChB,cACE,KAAK,EAAE;wBACL,QAAQ,EAAE,UAAU;wBACpB,SAAS,EAAE,mCAAmC,MAAM,MAAM,MAAM,KAAK;wBACrE,aAAa,EAAE,KAAK;qBACrB,EACD,SAAS,EAAC,cAAc,EACxB,YAAY,EAAE,gBAAgB,EAC9B,YAAY,EAAE,gBAAgB,YAE9B,MAAC,sBAAsB,IACrB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,UAAU,EACtB,IAAI,EAAE,gBAAgB,EACtB,QAAQ,EAAC,KAAK,aAEb,KAAK,IAAI,CACR,cACE,KAAK,EAAE;oCACL,eAAe,EAAE,OAAO;oCACxB,OAAO,EAAE,SAAS;oCAClB,YAAY,EAAE,KAAK;oCACnB,QAAQ,EAAE,MAAM;oCAChB,MAAM,EAAE,aAAa,SAAS,CAAC,MAAM,IAAI,MAAM,EAAE;iCAClD,YAEA,KAAK,GACF,CACP,EACA,CAAC,KAAK,IAAI,gBAAgB,IAAI,CAC7B,cACE,KAAK,EAAE;oCACL,KAAK,EAAE,MAAM;oCACb,MAAM,EAAE,MAAM;oCACd,eAAe,EACb,MAAM,KAAK,cAAc,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;oCACnD,YAAY,EAAE,KAAK;oCACnB,MAAM,EAAE,iBAAiB;oCACzB,SAAS,EAAE,2BAA2B;iCACvC,GACD,CACH,IACsB,GACrB,GACY,CACrB,EAGA,QAAQ,IAAI,SAAS,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,IAAI,CAChD,KAAC,iBAAiB,cACf,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CACrB,kCAEoB,EAAE,CAAC,EAAE,EACvB,SAAS,EAAC,cAAc,EACxB,KAAK,EAAE;wBACL,QAAQ,EAAE,UAAU;wBACpB,SAAS,EAAE,mCAAmC,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,KAAK;wBACjE,KAAK,EAAE,KAAK;wBACZ,MAAM,EAAE,KAAK;wBACb,eAAe,EAAE,SAAS;wBAC1B,YAAY,EAAE,KAAK;wBACnB,MAAM,EAAE,mBAAmB;wBAC3B,SAAS,EAAE,2BAA2B;wBACtC,MAAM,EAAE,MAAM;wBACd,aAAa,EAAE,KAAK;qBACrB,EACD,aAAa,EAAE,CAAC,CAAC,EAAE,EAAE;wBACnB,CAAC,CAAC,cAAc,EAAE,CAAC;wBACnB,gBAAgB,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC;oBAChC,CAAC,EACD,WAAW,EAAE,CAAC,CAAC,EAAE,EAAE;wBACjB,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,IAAI,cAAc,EAAE,CAAC;4BACrC,cAAc,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;wBAClD,CAAC;oBACH,CAAC,IAvBI,EAAE,CAAC,EAAE,CAwBV,CACH,CAAC,GACgB,CACrB,IACA,CACJ,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,eAAe,iBAAiB,CAAC"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * IncompatibilityTooltip Component (CORAL-REQ-010)
3
+ *
4
+ * Displays a tooltip explaining why an edge connection is incompatible
5
+ * or has a warning based on notation rules.
6
+ */
7
+ import { type CSSProperties, type ReactNode } from 'react';
8
+ import type { ConnectionValidation, EdgeCompatibilityStatus } from '../types.js';
9
+ /**
10
+ * Props for the IncompatibilityTooltip component
11
+ */
12
+ export interface IncompatibilityTooltipProps {
13
+ /** Validation result from edge compatibility check */
14
+ validation?: ConnectionValidation;
15
+ /** Compatibility status */
16
+ status?: EdgeCompatibilityStatus;
17
+ /** Child element that triggers the tooltip on hover */
18
+ children: ReactNode;
19
+ /** Position of tooltip relative to trigger */
20
+ position?: 'top' | 'bottom' | 'left' | 'right';
21
+ /** Custom styles for the tooltip */
22
+ style?: CSSProperties;
23
+ /** Whether to show the tooltip (controlled mode) */
24
+ show?: boolean;
25
+ /** Callback when tooltip visibility changes */
26
+ onVisibilityChange?: (visible: boolean) => void;
27
+ }
28
+ /**
29
+ * IncompatibilityTooltip - Shows a tooltip explaining edge compatibility issues
30
+ *
31
+ * @example
32
+ * ```tsx
33
+ * <IncompatibilityTooltip
34
+ * validation={edgeValidation}
35
+ * status="incompatible"
36
+ * position="top"
37
+ * >
38
+ * <div className="edge-label">My Edge</div>
39
+ * </IncompatibilityTooltip>
40
+ * ```
41
+ */
42
+ export declare function IncompatibilityTooltip({ validation, status, children, position, style, show: controlledShow, onVisibilityChange, }: IncompatibilityTooltipProps): React.JSX.Element;
43
+ export default IncompatibilityTooltip;
44
+ //# sourceMappingURL=IncompatibilityTooltip.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IncompatibilityTooltip.d.ts","sourceRoot":"","sources":["../../src/compatibility/IncompatibilityTooltip.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAyB,KAAK,aAAa,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAClF,OAAO,KAAK,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAEjF;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC1C,sDAAsD;IACtD,UAAU,CAAC,EAAE,oBAAoB,CAAC;IAClC,2BAA2B;IAC3B,MAAM,CAAC,EAAE,uBAAuB,CAAC;IACjC,uDAAuD;IACvD,QAAQ,EAAE,SAAS,CAAC;IACpB,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;IAC/C,oCAAoC;IACpC,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,oDAAoD;IACpD,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,+CAA+C;IAC/C,kBAAkB,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;CACjD;AAkGD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,sBAAsB,CAAC,EACrC,UAAU,EACV,MAAM,EACN,QAAQ,EACR,QAAgB,EAChB,KAAK,EACL,IAAI,EAAE,cAAc,EACpB,kBAAkB,GACnB,EAAE,2BAA2B,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAmDjD;AAED,eAAe,sBAAsB,CAAC"}
@@ -0,0 +1,145 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * IncompatibilityTooltip Component (CORAL-REQ-010)
4
+ *
5
+ * Displays a tooltip explaining why an edge connection is incompatible
6
+ * or has a warning based on notation rules.
7
+ */
8
+ import { useState, useCallback } from 'react';
9
+ /**
10
+ * Default styles for the tooltip container
11
+ */
12
+ const defaultTooltipStyle = {
13
+ position: 'absolute',
14
+ padding: '8px 12px',
15
+ borderRadius: '4px',
16
+ fontSize: '12px',
17
+ fontWeight: 500,
18
+ maxWidth: '250px',
19
+ zIndex: 1000,
20
+ boxShadow: '0 2px 8px rgba(0,0,0,0.15)',
21
+ whiteSpace: 'normal',
22
+ lineHeight: 1.4,
23
+ };
24
+ /**
25
+ * Get position styles based on position prop
26
+ */
27
+ function getPositionStyles(position) {
28
+ switch (position) {
29
+ case 'top':
30
+ return { bottom: '100%', left: '50%', transform: 'translateX(-50%)', marginBottom: '8px' };
31
+ case 'bottom':
32
+ return { top: '100%', left: '50%', transform: 'translateX(-50%)', marginTop: '8px' };
33
+ case 'left':
34
+ return { right: '100%', top: '50%', transform: 'translateY(-50%)', marginRight: '8px' };
35
+ case 'right':
36
+ return { left: '100%', top: '50%', transform: 'translateY(-50%)', marginLeft: '8px' };
37
+ }
38
+ }
39
+ /**
40
+ * Get background color based on status
41
+ */
42
+ function getBackgroundColor(status) {
43
+ switch (status) {
44
+ case 'incompatible':
45
+ return '#fee2e2'; // red-100
46
+ case 'warning':
47
+ return '#fef3c7'; // amber-100
48
+ case 'compatible':
49
+ return '#d1fae5'; // green-100
50
+ default:
51
+ return '#f3f4f6'; // gray-100
52
+ }
53
+ }
54
+ /**
55
+ * Get border color based on status
56
+ */
57
+ function getBorderColor(status) {
58
+ switch (status) {
59
+ case 'incompatible':
60
+ return '#ef4444'; // red-500
61
+ case 'warning':
62
+ return '#f59e0b'; // amber-500
63
+ case 'compatible':
64
+ return '#10b981'; // green-500
65
+ default:
66
+ return '#9ca3af'; // gray-400
67
+ }
68
+ }
69
+ /**
70
+ * Get text color based on status
71
+ */
72
+ function getTextColor(status) {
73
+ switch (status) {
74
+ case 'incompatible':
75
+ return '#991b1b'; // red-800
76
+ case 'warning':
77
+ return '#92400e'; // amber-800
78
+ case 'compatible':
79
+ return '#065f46'; // green-800
80
+ default:
81
+ return '#374151'; // gray-700
82
+ }
83
+ }
84
+ /**
85
+ * Get status label
86
+ */
87
+ function getStatusLabel(status) {
88
+ switch (status) {
89
+ case 'incompatible':
90
+ return 'Incompatible Connection';
91
+ case 'warning':
92
+ return 'Warning';
93
+ case 'compatible':
94
+ return 'Compatible';
95
+ default:
96
+ return 'Unknown Status';
97
+ }
98
+ }
99
+ /**
100
+ * IncompatibilityTooltip - Shows a tooltip explaining edge compatibility issues
101
+ *
102
+ * @example
103
+ * ```tsx
104
+ * <IncompatibilityTooltip
105
+ * validation={edgeValidation}
106
+ * status="incompatible"
107
+ * position="top"
108
+ * >
109
+ * <div className="edge-label">My Edge</div>
110
+ * </IncompatibilityTooltip>
111
+ * ```
112
+ */
113
+ export function IncompatibilityTooltip({ validation, status, children, position = 'top', style, show: controlledShow, onVisibilityChange, }) {
114
+ const [internalShow, setInternalShow] = useState(false);
115
+ const isControlled = controlledShow !== undefined;
116
+ const isVisible = isControlled ? controlledShow : internalShow;
117
+ const handleMouseEnter = useCallback(() => {
118
+ if (!isControlled) {
119
+ setInternalShow(true);
120
+ }
121
+ onVisibilityChange?.(true);
122
+ }, [isControlled, onVisibilityChange]);
123
+ const handleMouseLeave = useCallback(() => {
124
+ if (!isControlled) {
125
+ setInternalShow(false);
126
+ }
127
+ onVisibilityChange?.(false);
128
+ }, [isControlled, onVisibilityChange]);
129
+ // Don't show tooltip for compatible edges unless explicitly requested
130
+ const shouldShow = isVisible && (status !== 'compatible' || validation?.hasWarning);
131
+ // Get the message to display
132
+ const message = validation?.message || 'Unknown issue with this connection';
133
+ const statusLabel = getStatusLabel(status);
134
+ const tooltipStyle = {
135
+ ...defaultTooltipStyle,
136
+ ...getPositionStyles(position),
137
+ backgroundColor: getBackgroundColor(status),
138
+ border: `1px solid ${getBorderColor(status)}`,
139
+ color: getTextColor(status),
140
+ ...style,
141
+ };
142
+ return (_jsxs("div", { style: { position: 'relative', display: 'inline-block' }, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, children: [children, shouldShow && (_jsxs("div", { style: tooltipStyle, role: "tooltip", children: [_jsx("div", { style: { fontWeight: 600, marginBottom: '4px' }, children: statusLabel }), _jsx("div", { children: message })] }))] }));
143
+ }
144
+ export default IncompatibilityTooltip;
145
+ //# sourceMappingURL=IncompatibilityTooltip.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IncompatibilityTooltip.js","sourceRoot":"","sources":["../../src/compatibility/IncompatibilityTooltip.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Compatibility Module (CORAL-REQ-010)
3
+ *
4
+ * Provides connection validation and port compatibility checking.
5
+ */
6
+ export { validateConnection, checkPortDirection, checkMaxConnections, getEdgeCompatibility, } from './validateConnection.js';
7
+ export { useEdgeCompatibility, type UseEdgeCompatibilityOptions, type UseEdgeCompatibilityOptionsNodes, type UseEdgeCompatibilityOptionsContext, type UseEdgeCompatibilityResult, } from './useEdgeCompatibility.js';
8
+ export { IncompatibilityTooltip, type IncompatibilityTooltipProps, } from './IncompatibilityTooltip.js';
9
+ export { CompatibilityEdge, getEdgeStyleForStatus, buildRoutedPath, type CompatibilityEdgeProps, type CompatibilityEdgeData, type WaypointHandleData, } from './CompatibilityEdge.js';
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/compatibility/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACL,oBAAoB,EACpB,KAAK,2BAA2B,EAChC,KAAK,gCAAgC,EACrC,KAAK,kCAAkC,EACvC,KAAK,0BAA0B,GAChC,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EACL,sBAAsB,EACtB,KAAK,2BAA2B,GACjC,MAAM,6BAA6B,CAAC;AAErC,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,eAAe,EACf,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,EAC1B,KAAK,kBAAkB,GACxB,MAAM,wBAAwB,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Compatibility Module (CORAL-REQ-010)
3
+ *
4
+ * Provides connection validation and port compatibility checking.
5
+ */
6
+ export { validateConnection, checkPortDirection, checkMaxConnections, getEdgeCompatibility, } from './validateConnection.js';
7
+ export { useEdgeCompatibility, } from './useEdgeCompatibility.js';
8
+ export { IncompatibilityTooltip, } from './IncompatibilityTooltip.js';
9
+ export { CompatibilityEdge, getEdgeStyleForStatus, buildRoutedPath, } from './CompatibilityEdge.js';
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/compatibility/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACL,oBAAoB,GAKrB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EACL,sBAAsB,GAEvB,MAAM,6BAA6B,CAAC;AAErC,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,eAAe,GAIhB,MAAM,wBAAwB,CAAC"}