@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.
- package/LICENSE +4 -0
- package/README.md +11 -0
- package/dist/compatibility/CompatibilityEdge.d.ts +106 -0
- package/dist/compatibility/CompatibilityEdge.d.ts.map +1 -0
- package/dist/compatibility/CompatibilityEdge.js +233 -0
- package/dist/compatibility/CompatibilityEdge.js.map +1 -0
- package/dist/compatibility/IncompatibilityTooltip.d.ts +44 -0
- package/dist/compatibility/IncompatibilityTooltip.d.ts.map +1 -0
- package/dist/compatibility/IncompatibilityTooltip.js +145 -0
- package/dist/compatibility/IncompatibilityTooltip.js.map +1 -0
- package/dist/compatibility/index.d.ts +10 -0
- package/dist/compatibility/index.d.ts.map +1 -0
- package/dist/compatibility/index.js +10 -0
- package/dist/compatibility/index.js.map +1 -0
- package/dist/compatibility/useEdgeCompatibility.d.ts +82 -0
- package/dist/compatibility/useEdgeCompatibility.d.ts.map +1 -0
- package/dist/compatibility/useEdgeCompatibility.js +170 -0
- package/dist/compatibility/useEdgeCompatibility.js.map +1 -0
- package/dist/compatibility/validateConnection.d.ts +56 -0
- package/dist/compatibility/validateConnection.d.ts.map +1 -0
- package/dist/compatibility/validateConnection.js +382 -0
- package/dist/compatibility/validateConnection.js.map +1 -0
- package/dist/components/EditContext.d.ts +45 -0
- package/dist/components/EditContext.d.ts.map +1 -0
- package/dist/components/EditContext.js +41 -0
- package/dist/components/EditContext.js.map +1 -0
- package/dist/components/ShapeRenderer.d.ts +35 -0
- package/dist/components/ShapeRenderer.d.ts.map +1 -0
- package/dist/components/ShapeRenderer.js +77 -0
- package/dist/components/ShapeRenderer.js.map +1 -0
- package/dist/components/SymbolNode.d.ts +53 -0
- package/dist/components/SymbolNode.d.ts.map +1 -0
- package/dist/components/SymbolNode.js +333 -0
- package/dist/components/SymbolNode.js.map +1 -0
- package/dist/components/index.d.ts +8 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/index.js +10 -0
- package/dist/components/index.js.map +1 -0
- package/dist/components/nodes.d.ts +43 -0
- package/dist/components/nodes.d.ts.map +1 -0
- package/dist/components/nodes.js +111 -0
- package/dist/components/nodes.js.map +1 -0
- package/dist/editor/CoralEditor.d.ts +29 -0
- package/dist/editor/CoralEditor.d.ts.map +1 -0
- package/dist/editor/CoralEditor.js +112 -0
- package/dist/editor/CoralEditor.js.map +1 -0
- package/dist/editor/FileControls.d.ts +34 -0
- package/dist/editor/FileControls.d.ts.map +1 -0
- package/dist/editor/FileControls.js +139 -0
- package/dist/editor/FileControls.js.map +1 -0
- package/dist/editor/LayoutControls.d.ts +41 -0
- package/dist/editor/LayoutControls.d.ts.map +1 -0
- package/dist/editor/LayoutControls.js +124 -0
- package/dist/editor/LayoutControls.js.map +1 -0
- package/dist/editor/converter.d.ts +37 -0
- package/dist/editor/converter.d.ts.map +1 -0
- package/dist/editor/converter.js +256 -0
- package/dist/editor/converter.js.map +1 -0
- package/dist/editor/index.d.ts +8 -0
- package/dist/editor/index.d.ts.map +1 -0
- package/dist/editor/index.js +8 -0
- package/dist/editor/index.js.map +1 -0
- package/dist/file/deserialize.d.ts +15 -0
- package/dist/file/deserialize.d.ts.map +1 -0
- package/dist/file/deserialize.js +145 -0
- package/dist/file/deserialize.js.map +1 -0
- package/dist/file/index.d.ts +15 -0
- package/dist/file/index.d.ts.map +1 -0
- package/dist/file/index.js +20 -0
- package/dist/file/index.js.map +1 -0
- package/dist/file/migrate.d.ts +29 -0
- package/dist/file/migrate.d.ts.map +1 -0
- package/dist/file/migrate.js +103 -0
- package/dist/file/migrate.js.map +1 -0
- package/dist/file/schema.d.ts +385 -0
- package/dist/file/schema.d.ts.map +1 -0
- package/dist/file/schema.js +180 -0
- package/dist/file/schema.js.map +1 -0
- package/dist/file/serialize.d.ts +30 -0
- package/dist/file/serialize.d.ts.map +1 -0
- package/dist/file/serialize.js +218 -0
- package/dist/file/serialize.js.map +1 -0
- package/dist/file/validate.d.ts +21 -0
- package/dist/file/validate.d.ts.map +1 -0
- package/dist/file/validate.js +165 -0
- package/dist/file/validate.js.map +1 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +42 -0
- package/dist/index.js.map +1 -0
- package/dist/layout/elk.d.ts +77 -0
- package/dist/layout/elk.d.ts.map +1 -0
- package/dist/layout/elk.js +379 -0
- package/dist/layout/elk.js.map +1 -0
- package/dist/layout/index.d.ts +12 -0
- package/dist/layout/index.d.ts.map +1 -0
- package/dist/layout/index.js +12 -0
- package/dist/layout/index.js.map +1 -0
- package/dist/layout/nodeSizing.d.ts +65 -0
- package/dist/layout/nodeSizing.d.ts.map +1 -0
- package/dist/layout/nodeSizing.js +319 -0
- package/dist/layout/nodeSizing.js.map +1 -0
- package/dist/layout/positionStability.d.ts +73 -0
- package/dist/layout/positionStability.d.ts.map +1 -0
- package/dist/layout/positionStability.js +199 -0
- package/dist/layout/positionStability.js.map +1 -0
- package/dist/layout/useAxisConstrain.d.ts +20 -0
- package/dist/layout/useAxisConstrain.d.ts.map +1 -0
- package/dist/layout/useAxisConstrain.js +106 -0
- package/dist/layout/useAxisConstrain.js.map +1 -0
- package/dist/layout/useDiagramState.d.ts +92 -0
- package/dist/layout/useDiagramState.d.ts.map +1 -0
- package/dist/layout/useDiagramState.js +256 -0
- package/dist/layout/useDiagramState.js.map +1 -0
- package/dist/layout/useLayoutHistory.d.ts +53 -0
- package/dist/layout/useLayoutHistory.d.ts.map +1 -0
- package/dist/layout/useLayoutHistory.js +124 -0
- package/dist/layout/useLayoutHistory.js.map +1 -0
- package/dist/properties/NodePropertiesPanel.d.ts +47 -0
- package/dist/properties/NodePropertiesPanel.d.ts.map +1 -0
- package/dist/properties/NodePropertiesPanel.js +199 -0
- package/dist/properties/NodePropertiesPanel.js.map +1 -0
- package/dist/properties/index.d.ts +10 -0
- package/dist/properties/index.d.ts.map +1 -0
- package/dist/properties/index.js +10 -0
- package/dist/properties/index.js.map +1 -0
- package/dist/properties/propertyUtils.d.ts +60 -0
- package/dist/properties/propertyUtils.d.ts.map +1 -0
- package/dist/properties/propertyUtils.js +89 -0
- package/dist/properties/propertyUtils.js.map +1 -0
- package/dist/settings/FontSettingsForm.d.ts +28 -0
- package/dist/settings/FontSettingsForm.d.ts.map +1 -0
- package/dist/settings/FontSettingsForm.js +129 -0
- package/dist/settings/FontSettingsForm.js.map +1 -0
- package/dist/settings/LayoutSettingsForm.d.ts +37 -0
- package/dist/settings/LayoutSettingsForm.d.ts.map +1 -0
- package/dist/settings/LayoutSettingsForm.js +165 -0
- package/dist/settings/LayoutSettingsForm.js.map +1 -0
- package/dist/settings/SettingsPanel.d.ts +55 -0
- package/dist/settings/SettingsPanel.d.ts.map +1 -0
- package/dist/settings/SettingsPanel.js +84 -0
- package/dist/settings/SettingsPanel.js.map +1 -0
- package/dist/settings/index.d.ts +13 -0
- package/dist/settings/index.d.ts.map +1 -0
- package/dist/settings/index.js +13 -0
- package/dist/settings/index.js.map +1 -0
- package/dist/settings/useSettings.d.ts +51 -0
- package/dist/settings/useSettings.d.ts.map +1 -0
- package/dist/settings/useSettings.js +154 -0
- package/dist/settings/useSettings.js.map +1 -0
- package/dist/text-editor/SplitEditor.d.ts +72 -0
- package/dist/text-editor/SplitEditor.d.ts.map +1 -0
- package/dist/text-editor/SplitEditor.js +172 -0
- package/dist/text-editor/SplitEditor.js.map +1 -0
- package/dist/text-editor/TextEditor.d.ts +53 -0
- package/dist/text-editor/TextEditor.d.ts.map +1 -0
- package/dist/text-editor/TextEditor.js +181 -0
- package/dist/text-editor/TextEditor.js.map +1 -0
- package/dist/text-editor/hooks/useBidirectionalSync.d.ts +106 -0
- package/dist/text-editor/hooks/useBidirectionalSync.d.ts.map +1 -0
- package/dist/text-editor/hooks/useBidirectionalSync.js +151 -0
- package/dist/text-editor/hooks/useBidirectionalSync.js.map +1 -0
- package/dist/text-editor/index.d.ts +9 -0
- package/dist/text-editor/index.d.ts.map +1 -0
- package/dist/text-editor/index.js +11 -0
- package/dist/text-editor/index.js.map +1 -0
- package/dist/types.d.ts +242 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/dist/waypoints/index.d.ts +8 -0
- package/dist/waypoints/index.d.ts.map +1 -0
- package/dist/waypoints/index.js +7 -0
- package/dist/waypoints/index.js.map +1 -0
- package/dist/waypoints/operations.d.ts +29 -0
- package/dist/waypoints/operations.d.ts.map +1 -0
- package/dist/waypoints/operations.js +85 -0
- package/dist/waypoints/operations.js.map +1 -0
- package/dist/waypoints/router.d.ts +23 -0
- package/dist/waypoints/router.d.ts.map +1 -0
- package/dist/waypoints/router.js +109 -0
- package/dist/waypoints/router.js.map +1 -0
- package/dist/waypoints/types.d.ts +15 -0
- package/dist/waypoints/types.d.ts.map +1 -0
- package/dist/waypoints/types.js +5 -0
- package/dist/waypoints/types.js.map +1 -0
- package/dist/waypoints/useWaypointManager.d.ts +38 -0
- package/dist/waypoints/useWaypointManager.d.ts.map +1 -0
- package/dist/waypoints/useWaypointManager.js +106 -0
- package/dist/waypoints/useWaypointManager.js.map +1 -0
- package/package.json +76 -0
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* CoralEditor - Main visual editor component
|
|
4
|
+
*
|
|
5
|
+
* Renders Graph-IR as an interactive diagram using React Flow.
|
|
6
|
+
*/
|
|
7
|
+
import { useCallback, useMemo, useState } from 'react';
|
|
8
|
+
import { ReactFlow, Background, Controls, MiniMap, useNodesState, useEdgesState, BackgroundVariant, } from '@xyflow/react';
|
|
9
|
+
import { nodeTypes } from '../components/nodes.js';
|
|
10
|
+
import { convertGraphToFlow, convertFlowToGraphNodes, convertFlowToGraphEdges } from './converter.js';
|
|
11
|
+
const defaultConfig = {
|
|
12
|
+
draggable: true,
|
|
13
|
+
connectable: false,
|
|
14
|
+
selectable: true,
|
|
15
|
+
zoomable: true,
|
|
16
|
+
pannable: true,
|
|
17
|
+
showMinimap: true,
|
|
18
|
+
showControls: true,
|
|
19
|
+
fitViewOnLoad: true,
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Main Coral Editor component
|
|
23
|
+
*/
|
|
24
|
+
export const CoralEditor = ({ graph, config: userConfig, callbacks, className, style, }) => {
|
|
25
|
+
const config = useMemo(() => ({ ...defaultConfig, ...userConfig }), [userConfig]);
|
|
26
|
+
// Convert Graph-IR to React Flow format
|
|
27
|
+
const initialData = useMemo(() => convertGraphToFlow(graph), [graph]);
|
|
28
|
+
// React Flow state
|
|
29
|
+
const [nodes, setNodes, onNodesChange] = useNodesState(initialData.nodes);
|
|
30
|
+
const [edges, setEdges, onEdgesChange] = useEdgesState(initialData.edges);
|
|
31
|
+
const [selectedNodes, setSelectedNodes] = useState([]);
|
|
32
|
+
const [selectedEdges, setSelectedEdges] = useState([]);
|
|
33
|
+
// Handle node changes and notify parent
|
|
34
|
+
const handleNodesChange = useCallback((changes) => {
|
|
35
|
+
onNodesChange(changes);
|
|
36
|
+
// Notify parent of changes
|
|
37
|
+
if (callbacks?.onNodesChange) {
|
|
38
|
+
// Get updated nodes after change
|
|
39
|
+
setNodes((currentNodes) => {
|
|
40
|
+
callbacks.onNodesChange?.(currentNodes);
|
|
41
|
+
return currentNodes;
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
}, [onNodesChange, callbacks, setNodes]);
|
|
45
|
+
// Handle edge changes and notify parent
|
|
46
|
+
const handleEdgesChange = useCallback((changes) => {
|
|
47
|
+
onEdgesChange(changes);
|
|
48
|
+
if (callbacks?.onEdgesChange) {
|
|
49
|
+
setEdges((currentEdges) => {
|
|
50
|
+
callbacks.onEdgesChange?.(currentEdges);
|
|
51
|
+
return currentEdges;
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}, [onEdgesChange, callbacks, setEdges]);
|
|
55
|
+
// Handle selection changes
|
|
56
|
+
const handleSelectionChange = useCallback(({ nodes: selectedNodeList, edges: selectedEdgeList }) => {
|
|
57
|
+
const nodeIds = selectedNodeList.map((n) => n.id);
|
|
58
|
+
const edgeIds = selectedEdgeList.map((e) => e.id);
|
|
59
|
+
setSelectedNodes(nodeIds);
|
|
60
|
+
setSelectedEdges(edgeIds);
|
|
61
|
+
callbacks?.onNodeSelect?.(nodeIds);
|
|
62
|
+
callbacks?.onEdgeSelect?.(edgeIds);
|
|
63
|
+
}, [callbacks]);
|
|
64
|
+
// Handle node double click
|
|
65
|
+
const handleNodeDoubleClick = useCallback((_event, node) => {
|
|
66
|
+
callbacks?.onNodeDoubleClick?.(node.id);
|
|
67
|
+
}, [callbacks]);
|
|
68
|
+
// Minimap node color based on type
|
|
69
|
+
const getMinimapNodeColor = useCallback((node) => {
|
|
70
|
+
switch (node.data.nodeType) {
|
|
71
|
+
case 'service':
|
|
72
|
+
return '#90caf9';
|
|
73
|
+
case 'database':
|
|
74
|
+
return '#ffb74d';
|
|
75
|
+
case 'external_api':
|
|
76
|
+
return '#f48fb1';
|
|
77
|
+
case 'actor':
|
|
78
|
+
return '#81c784';
|
|
79
|
+
case 'module':
|
|
80
|
+
return '#ce93d8';
|
|
81
|
+
case 'group':
|
|
82
|
+
return '#bdbdbd';
|
|
83
|
+
default:
|
|
84
|
+
return '#90caf9';
|
|
85
|
+
}
|
|
86
|
+
}, []);
|
|
87
|
+
return (_jsx("div", { className: `coral-editor ${className || ''}`, style: {
|
|
88
|
+
width: '100%',
|
|
89
|
+
height: '100%',
|
|
90
|
+
minHeight: '400px',
|
|
91
|
+
...style,
|
|
92
|
+
}, children: _jsxs(ReactFlow, { nodes: nodes, edges: edges, onNodesChange: handleNodesChange, onEdgesChange: handleEdgesChange, onSelectionChange: handleSelectionChange, onNodeDoubleClick: handleNodeDoubleClick, nodeTypes: nodeTypes, nodesDraggable: config.draggable, nodesConnectable: config.connectable, elementsSelectable: config.selectable, zoomOnScroll: config.zoomable, panOnScroll: config.pannable, fitView: config.fitViewOnLoad, fitViewOptions: { padding: 0.2 }, defaultEdgeOptions: {
|
|
93
|
+
type: 'smoothstep',
|
|
94
|
+
animated: false,
|
|
95
|
+
}, children: [_jsx(Background, { variant: BackgroundVariant.Dots, gap: 20, size: 1 }), config.showControls && _jsx(Controls, {}), config.showMinimap && (_jsx(MiniMap, { nodeColor: getMinimapNodeColor, nodeStrokeWidth: 3, zoomable: true, pannable: true }))] }) }));
|
|
96
|
+
};
|
|
97
|
+
/**
|
|
98
|
+
* Hook to get Graph-IR from current editor state
|
|
99
|
+
*/
|
|
100
|
+
export function useGraphIR(nodes, edges, originalGraph) {
|
|
101
|
+
return useMemo(() => {
|
|
102
|
+
const graphNodes = convertFlowToGraphNodes(nodes, originalGraph.nodes);
|
|
103
|
+
const graphEdges = convertFlowToGraphEdges(edges);
|
|
104
|
+
return {
|
|
105
|
+
...originalGraph,
|
|
106
|
+
nodes: graphNodes,
|
|
107
|
+
edges: graphEdges,
|
|
108
|
+
};
|
|
109
|
+
}, [nodes, edges, originalGraph]);
|
|
110
|
+
}
|
|
111
|
+
export default CoralEditor;
|
|
112
|
+
//# sourceMappingURL=CoralEditor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CoralEditor.js","sourceRoot":"","sources":["../../src/editor/CoralEditor.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FileControls - UI component for file operations (CORAL-REQ-008)
|
|
3
|
+
*
|
|
4
|
+
* Provides buttons for:
|
|
5
|
+
* - Save: Download diagram as .coral.json file
|
|
6
|
+
* - Load: Open file picker to load .coral.json file
|
|
7
|
+
* - Export: Export Graph-IR as JSON
|
|
8
|
+
*/
|
|
9
|
+
import { type CSSProperties } from 'react';
|
|
10
|
+
import type { CoralDocument } from '../file/index.js';
|
|
11
|
+
/** Props for the FileControls component */
|
|
12
|
+
export interface FileControlsProps {
|
|
13
|
+
/** Current document to save */
|
|
14
|
+
document: CoralDocument | null;
|
|
15
|
+
/** Callback when a document is loaded */
|
|
16
|
+
onLoad: (document: CoralDocument) => void;
|
|
17
|
+
/** Callback to get current state as document (for saving) */
|
|
18
|
+
onGetDocument?: () => CoralDocument;
|
|
19
|
+
/** Custom styles for the container */
|
|
20
|
+
style?: CSSProperties;
|
|
21
|
+
/** Custom class name for the container */
|
|
22
|
+
className?: string;
|
|
23
|
+
/** Whether to show keyboard shortcut hints in tooltips */
|
|
24
|
+
showShortcutHints?: boolean;
|
|
25
|
+
/** Disable all controls */
|
|
26
|
+
disabled?: boolean;
|
|
27
|
+
/** Show export button */
|
|
28
|
+
showExport?: boolean;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* FileControls component
|
|
32
|
+
*/
|
|
33
|
+
export declare function FileControls({ document, onLoad, onGetDocument, style, className, showShortcutHints, disabled, showExport, }: FileControlsProps): import("react").JSX.Element;
|
|
34
|
+
//# sourceMappingURL=FileControls.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FileControls.d.ts","sourceRoot":"","sources":["../../src/editor/FileControls.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAuB,KAAK,aAAa,EAAoB,MAAM,OAAO,CAAC;AAClF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEtD,2CAA2C;AAC3C,MAAM,WAAW,iBAAiB;IAChC,+BAA+B;IAC/B,QAAQ,EAAE,aAAa,GAAG,IAAI,CAAC;IAC/B,yCAAyC;IACzC,MAAM,EAAE,CAAC,QAAQ,EAAE,aAAa,KAAK,IAAI,CAAC;IAC1C,6DAA6D;IAC7D,aAAa,CAAC,EAAE,MAAM,aAAa,CAAC;IACpC,sCAAsC;IACtC,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,0CAA0C;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0DAA0D;IAC1D,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,2BAA2B;IAC3B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,yBAAyB;IACzB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AA8DD;;GAEG;AACH,wBAAgB,YAAY,CAAC,EAC3B,QAAQ,EACR,MAAM,EACN,aAAa,EACb,KAAK,EACL,SAAS,EACT,iBAAwB,EACxB,QAAgB,EAChB,UAAiB,GAClB,EAAE,iBAAiB,+BAgJnB"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* FileControls - UI component for file operations (CORAL-REQ-008)
|
|
4
|
+
*
|
|
5
|
+
* Provides buttons for:
|
|
6
|
+
* - Save: Download diagram as .coral.json file
|
|
7
|
+
* - Load: Open file picker to load .coral.json file
|
|
8
|
+
* - Export: Export Graph-IR as JSON
|
|
9
|
+
*/
|
|
10
|
+
import { useRef, useCallback } from 'react';
|
|
11
|
+
/** Default button styles */
|
|
12
|
+
const buttonStyle = {
|
|
13
|
+
padding: '6px 12px',
|
|
14
|
+
fontSize: '13px',
|
|
15
|
+
fontWeight: 500,
|
|
16
|
+
borderRadius: '4px',
|
|
17
|
+
border: '1px solid #ccc',
|
|
18
|
+
background: '#fff',
|
|
19
|
+
cursor: 'pointer',
|
|
20
|
+
display: 'inline-flex',
|
|
21
|
+
alignItems: 'center',
|
|
22
|
+
gap: '4px',
|
|
23
|
+
transition: 'all 0.15s ease',
|
|
24
|
+
};
|
|
25
|
+
const buttonStyleDisabled = {
|
|
26
|
+
...buttonStyle,
|
|
27
|
+
opacity: 0.5,
|
|
28
|
+
cursor: 'not-allowed',
|
|
29
|
+
};
|
|
30
|
+
const buttonStylePrimary = {
|
|
31
|
+
...buttonStyle,
|
|
32
|
+
background: '#2e7d32',
|
|
33
|
+
borderColor: '#2e7d32',
|
|
34
|
+
color: '#fff',
|
|
35
|
+
};
|
|
36
|
+
const containerStyle = {
|
|
37
|
+
display: 'flex',
|
|
38
|
+
alignItems: 'center',
|
|
39
|
+
gap: '8px',
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Download a file with the given content
|
|
43
|
+
*/
|
|
44
|
+
function downloadFile(content, filename, mimeType) {
|
|
45
|
+
const blob = new Blob([content], { type: mimeType });
|
|
46
|
+
const url = URL.createObjectURL(blob);
|
|
47
|
+
const link = document.createElement('a');
|
|
48
|
+
link.href = url;
|
|
49
|
+
link.download = filename;
|
|
50
|
+
document.body.appendChild(link);
|
|
51
|
+
link.click();
|
|
52
|
+
document.body.removeChild(link);
|
|
53
|
+
URL.revokeObjectURL(url);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Generate filename from document name
|
|
57
|
+
*/
|
|
58
|
+
function generateFilename(name) {
|
|
59
|
+
const sanitized = name
|
|
60
|
+
.toLowerCase()
|
|
61
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
62
|
+
.replace(/^-+|-+$/g, '');
|
|
63
|
+
return `${sanitized || 'diagram'}.coral.json`;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* FileControls component
|
|
67
|
+
*/
|
|
68
|
+
export function FileControls({ document, onLoad, onGetDocument, style, className, showShortcutHints = true, disabled = false, showExport = true, }) {
|
|
69
|
+
const fileInputRef = useRef(null);
|
|
70
|
+
/**
|
|
71
|
+
* Handle save button click
|
|
72
|
+
*/
|
|
73
|
+
const handleSave = useCallback(() => {
|
|
74
|
+
const doc = onGetDocument ? onGetDocument() : document;
|
|
75
|
+
if (!doc)
|
|
76
|
+
return;
|
|
77
|
+
const json = JSON.stringify(doc, null, 2);
|
|
78
|
+
const filename = generateFilename(doc.metadata.name);
|
|
79
|
+
downloadFile(json, filename, 'application/json');
|
|
80
|
+
}, [document, onGetDocument]);
|
|
81
|
+
/**
|
|
82
|
+
* Handle load button click
|
|
83
|
+
*/
|
|
84
|
+
const handleLoadClick = useCallback(() => {
|
|
85
|
+
fileInputRef.current?.click();
|
|
86
|
+
}, []);
|
|
87
|
+
/**
|
|
88
|
+
* Handle file input change
|
|
89
|
+
*/
|
|
90
|
+
const handleFileChange = useCallback((event) => {
|
|
91
|
+
const file = event.target.files?.[0];
|
|
92
|
+
if (!file)
|
|
93
|
+
return;
|
|
94
|
+
const reader = new FileReader();
|
|
95
|
+
reader.onload = (e) => {
|
|
96
|
+
try {
|
|
97
|
+
const content = e.target?.result;
|
|
98
|
+
const doc = JSON.parse(content);
|
|
99
|
+
onLoad(doc);
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
console.error('Failed to parse file:', error);
|
|
103
|
+
alert(`Failed to load file: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
reader.readAsText(file);
|
|
107
|
+
// Reset input so same file can be loaded again
|
|
108
|
+
event.target.value = '';
|
|
109
|
+
}, [onLoad]);
|
|
110
|
+
/**
|
|
111
|
+
* Handle export Graph-IR button click
|
|
112
|
+
*/
|
|
113
|
+
const handleExport = useCallback(() => {
|
|
114
|
+
const doc = onGetDocument ? onGetDocument() : document;
|
|
115
|
+
if (!doc?.content.graphIR)
|
|
116
|
+
return;
|
|
117
|
+
const json = JSON.stringify(doc.content.graphIR, null, 2);
|
|
118
|
+
const filename = `${doc.metadata.name.toLowerCase().replace(/\s+/g, '-')}-graph-ir.json`;
|
|
119
|
+
downloadFile(json, filename, 'application/json');
|
|
120
|
+
}, [document, onGetDocument]);
|
|
121
|
+
const getSaveTitle = () => {
|
|
122
|
+
let title = 'Save diagram as .coral.json file';
|
|
123
|
+
if (showShortcutHints) {
|
|
124
|
+
title += ' (Ctrl+S)';
|
|
125
|
+
}
|
|
126
|
+
return title;
|
|
127
|
+
};
|
|
128
|
+
const getLoadTitle = () => {
|
|
129
|
+
let title = 'Load diagram from .coral.json file';
|
|
130
|
+
if (showShortcutHints) {
|
|
131
|
+
title += ' (Ctrl+O)';
|
|
132
|
+
}
|
|
133
|
+
return title;
|
|
134
|
+
};
|
|
135
|
+
const canSave = Boolean(document || onGetDocument);
|
|
136
|
+
const canExport = Boolean(document?.content.graphIR || onGetDocument);
|
|
137
|
+
return (_jsxs("div", { style: { ...containerStyle, ...style }, className: className, children: [_jsx("input", { ref: fileInputRef, type: "file", accept: ".coral.json,.json", style: { display: 'none' }, onChange: handleFileChange }), _jsxs("button", { onClick: handleSave, disabled: disabled || !canSave, title: getSaveTitle(), style: disabled || !canSave ? buttonStyleDisabled : buttonStylePrimary, children: [_jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [_jsx("path", { d: "M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z" }), _jsx("polyline", { points: "17 21 17 13 7 13 7 21" }), _jsx("polyline", { points: "7 3 7 8 15 8" })] }), "Save"] }), _jsxs("button", { onClick: handleLoadClick, disabled: disabled, title: getLoadTitle(), style: disabled ? buttonStyleDisabled : buttonStyle, children: [_jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [_jsx("path", { d: "M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z" }), _jsx("line", { x1: "12", y1: "11", x2: "12", y2: "17" }), _jsx("polyline", { points: "9 14 12 11 15 14" })] }), "Load"] }), showExport && (_jsxs(_Fragment, { children: [_jsx("div", { style: { width: '1px', height: '20px', background: '#ddd' } }), _jsxs("button", { onClick: handleExport, disabled: disabled || !canExport, title: "Export Graph-IR as JSON", style: disabled || !canExport ? buttonStyleDisabled : buttonStyle, children: [_jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [_jsx("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }), _jsx("polyline", { points: "7 10 12 15 17 10" }), _jsx("line", { x1: "12", y1: "15", x2: "12", y2: "3" })] }), "Export IR"] })] }))] }));
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=FileControls.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FileControls.js","sourceRoot":"","sources":["../../src/editor/FileControls.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LayoutControls - UI component for diagram reflow and undo/redo
|
|
3
|
+
*
|
|
4
|
+
* Provides buttons and keyboard shortcuts for:
|
|
5
|
+
* - Reflow: Re-run automatic layout (ELK)
|
|
6
|
+
* - Undo: Restore previous node positions
|
|
7
|
+
* - Redo: Re-apply undone changes
|
|
8
|
+
*/
|
|
9
|
+
import { type CSSProperties } from 'react';
|
|
10
|
+
/** Props for the LayoutControls component */
|
|
11
|
+
export interface LayoutControlsProps {
|
|
12
|
+
/** Callback to trigger reflow/re-layout */
|
|
13
|
+
onReflow: () => void;
|
|
14
|
+
/** Callback to undo last layout change */
|
|
15
|
+
onUndo: () => void;
|
|
16
|
+
/** Callback to redo undone change */
|
|
17
|
+
onRedo: () => void;
|
|
18
|
+
/** Whether undo is available */
|
|
19
|
+
canUndo: boolean;
|
|
20
|
+
/** Whether redo is available */
|
|
21
|
+
canRedo: boolean;
|
|
22
|
+
/** Number of undo steps available */
|
|
23
|
+
undoCount?: number;
|
|
24
|
+
/** Number of redo steps available */
|
|
25
|
+
redoCount?: number;
|
|
26
|
+
/** Whether a reflow is currently in progress */
|
|
27
|
+
isReflowing?: boolean;
|
|
28
|
+
/** Custom styles for the container */
|
|
29
|
+
style?: CSSProperties;
|
|
30
|
+
/** Custom class name for the container */
|
|
31
|
+
className?: string;
|
|
32
|
+
/** Whether to show keyboard shortcut hints in tooltips */
|
|
33
|
+
showShortcutHints?: boolean;
|
|
34
|
+
/** Disable all controls */
|
|
35
|
+
disabled?: boolean;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* LayoutControls component
|
|
39
|
+
*/
|
|
40
|
+
export declare function LayoutControls({ onReflow, onUndo, onRedo, canUndo, canRedo, undoCount, redoCount, isReflowing, style, className, showShortcutHints, disabled, }: LayoutControlsProps): import("react").JSX.Element;
|
|
41
|
+
//# sourceMappingURL=LayoutControls.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LayoutControls.d.ts","sourceRoot":"","sources":["../../src/editor/LayoutControls.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAA0B,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAEnE,6CAA6C;AAC7C,MAAM,WAAW,mBAAmB;IAClC,2CAA2C;IAC3C,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,0CAA0C;IAC1C,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,qCAAqC;IACrC,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,gCAAgC;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,gCAAgC;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,qCAAqC;IACrC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qCAAqC;IACrC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gDAAgD;IAChD,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,sCAAsC;IACtC,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,0CAA0C;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0DAA0D;IAC1D,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,2BAA2B;IAC3B,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAoCD;;GAEG;AACH,wBAAgB,cAAc,CAAC,EAC7B,QAAQ,EACR,MAAM,EACN,MAAM,EACN,OAAO,EACP,OAAO,EACP,SAAa,EACb,SAAa,EACb,WAAmB,EACnB,KAAK,EACL,SAAS,EACT,iBAAwB,EACxB,QAAgB,GACjB,EAAE,mBAAmB,+BAuJrB"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* LayoutControls - UI component for diagram reflow and undo/redo
|
|
4
|
+
*
|
|
5
|
+
* Provides buttons and keyboard shortcuts for:
|
|
6
|
+
* - Reflow: Re-run automatic layout (ELK)
|
|
7
|
+
* - Undo: Restore previous node positions
|
|
8
|
+
* - Redo: Re-apply undone changes
|
|
9
|
+
*/
|
|
10
|
+
import { useEffect, useCallback } from 'react';
|
|
11
|
+
/** Default button styles */
|
|
12
|
+
const buttonStyle = {
|
|
13
|
+
padding: '6px 12px',
|
|
14
|
+
fontSize: '13px',
|
|
15
|
+
fontWeight: 500,
|
|
16
|
+
borderRadius: '4px',
|
|
17
|
+
border: '1px solid #ccc',
|
|
18
|
+
background: '#fff',
|
|
19
|
+
cursor: 'pointer',
|
|
20
|
+
display: 'inline-flex',
|
|
21
|
+
alignItems: 'center',
|
|
22
|
+
gap: '4px',
|
|
23
|
+
transition: 'all 0.15s ease',
|
|
24
|
+
};
|
|
25
|
+
const buttonStyleDisabled = {
|
|
26
|
+
...buttonStyle,
|
|
27
|
+
opacity: 0.5,
|
|
28
|
+
cursor: 'not-allowed',
|
|
29
|
+
};
|
|
30
|
+
const buttonStylePrimary = {
|
|
31
|
+
...buttonStyle,
|
|
32
|
+
background: '#1976d2',
|
|
33
|
+
borderColor: '#1976d2',
|
|
34
|
+
color: '#fff',
|
|
35
|
+
};
|
|
36
|
+
const containerStyle = {
|
|
37
|
+
display: 'flex',
|
|
38
|
+
alignItems: 'center',
|
|
39
|
+
gap: '8px',
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* LayoutControls component
|
|
43
|
+
*/
|
|
44
|
+
export function LayoutControls({ onReflow, onUndo, onRedo, canUndo, canRedo, undoCount = 0, redoCount = 0, isReflowing = false, style, className, showShortcutHints = true, disabled = false, }) {
|
|
45
|
+
/**
|
|
46
|
+
* Handle keyboard shortcuts
|
|
47
|
+
*/
|
|
48
|
+
const handleKeyDown = useCallback((e) => {
|
|
49
|
+
if (disabled)
|
|
50
|
+
return;
|
|
51
|
+
// Ctrl+Shift+L or Cmd+Shift+L for reflow
|
|
52
|
+
if ((e.ctrlKey || e.metaKey) && e.shiftKey && e.key === 'L') {
|
|
53
|
+
e.preventDefault();
|
|
54
|
+
if (!isReflowing) {
|
|
55
|
+
onReflow();
|
|
56
|
+
}
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
// Ctrl+Z or Cmd+Z for undo (without shift)
|
|
60
|
+
if ((e.ctrlKey || e.metaKey) && !e.shiftKey && e.key === 'z') {
|
|
61
|
+
e.preventDefault();
|
|
62
|
+
if (canUndo) {
|
|
63
|
+
onUndo();
|
|
64
|
+
}
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
// Ctrl+Shift+Z or Cmd+Shift+Z for redo
|
|
68
|
+
if ((e.ctrlKey || e.metaKey) && e.shiftKey && (e.key === 'z' || e.key === 'Z')) {
|
|
69
|
+
e.preventDefault();
|
|
70
|
+
if (canRedo) {
|
|
71
|
+
onRedo();
|
|
72
|
+
}
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
// Ctrl+Y or Cmd+Y for redo (alternative)
|
|
76
|
+
if ((e.ctrlKey || e.metaKey) && e.key === 'y') {
|
|
77
|
+
e.preventDefault();
|
|
78
|
+
if (canRedo) {
|
|
79
|
+
onRedo();
|
|
80
|
+
}
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
}, [disabled, isReflowing, canUndo, canRedo, onReflow, onUndo, onRedo]);
|
|
84
|
+
// Attach keyboard listener
|
|
85
|
+
useEffect(() => {
|
|
86
|
+
window.addEventListener('keydown', handleKeyDown);
|
|
87
|
+
return () => window.removeEventListener('keydown', handleKeyDown);
|
|
88
|
+
}, [handleKeyDown]);
|
|
89
|
+
const getReflowTitle = () => {
|
|
90
|
+
let title = 'Re-apply automatic layout';
|
|
91
|
+
if (showShortcutHints) {
|
|
92
|
+
title += ' (Ctrl+Shift+L)';
|
|
93
|
+
}
|
|
94
|
+
return title;
|
|
95
|
+
};
|
|
96
|
+
const getUndoTitle = () => {
|
|
97
|
+
let title = `Undo${undoCount > 0 ? ` (${undoCount} step${undoCount > 1 ? 's' : ''} available)` : ''}`;
|
|
98
|
+
if (showShortcutHints) {
|
|
99
|
+
title += ' (Ctrl+Z)';
|
|
100
|
+
}
|
|
101
|
+
return title;
|
|
102
|
+
};
|
|
103
|
+
const getRedoTitle = () => {
|
|
104
|
+
let title = `Redo${redoCount > 0 ? ` (${redoCount} step${redoCount > 1 ? 's' : ''} available)` : ''}`;
|
|
105
|
+
if (showShortcutHints) {
|
|
106
|
+
title += ' (Ctrl+Shift+Z)';
|
|
107
|
+
}
|
|
108
|
+
return title;
|
|
109
|
+
};
|
|
110
|
+
return (_jsxs("div", { style: { ...containerStyle, ...style }, className: className, children: [_jsx("button", { onClick: onReflow, disabled: disabled || isReflowing, title: getReflowTitle(), style: disabled || isReflowing ? buttonStyleDisabled : buttonStylePrimary, children: isReflowing ? (_jsxs(_Fragment, { children: [_jsx("span", { style: {
|
|
111
|
+
display: 'inline-block',
|
|
112
|
+
width: '12px',
|
|
113
|
+
height: '12px',
|
|
114
|
+
border: '2px solid #fff',
|
|
115
|
+
borderTopColor: 'transparent',
|
|
116
|
+
borderRadius: '50%',
|
|
117
|
+
animation: 'spin 1s linear infinite',
|
|
118
|
+
} }), "Reflowing..."] })) : (_jsxs(_Fragment, { children: [_jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [_jsx("path", { d: "M23 4v6h-6M1 20v-6h6" }), _jsx("path", { d: "M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15" })] }), "Reflow"] })) }), _jsx("div", { style: { width: '1px', height: '20px', background: '#ddd' } }), _jsxs("button", { onClick: onUndo, disabled: disabled || !canUndo, title: getUndoTitle(), style: disabled || !canUndo ? buttonStyleDisabled : buttonStyle, children: [_jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [_jsx("path", { d: "M3 7v6h6" }), _jsx("path", { d: "M21 17a9 9 0 0 0-9-9 9 9 0 0 0-6 2.3L3 13" })] }), "Undo"] }), _jsxs("button", { onClick: onRedo, disabled: disabled || !canRedo, title: getRedoTitle(), style: disabled || !canRedo ? buttonStyleDisabled : buttonStyle, children: [_jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [_jsx("path", { d: "M21 7v6h-6" }), _jsx("path", { d: "M3 17a9 9 0 0 1 9-9 9 9 0 0 1 6 2.3L21 13" })] }), "Redo"] }), _jsx("style", { children: `
|
|
119
|
+
@keyframes spin {
|
|
120
|
+
to { transform: rotate(360deg); }
|
|
121
|
+
}
|
|
122
|
+
` })] }));
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=LayoutControls.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LayoutControls.js","sourceRoot":"","sources":["../../src/editor/LayoutControls.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Graph-IR to React Flow Converter
|
|
3
|
+
*
|
|
4
|
+
* Transforms Graph-IR nodes and edges to React Flow format.
|
|
5
|
+
*/
|
|
6
|
+
import type { GraphIR, GraphNode, GraphEdge, CoralNode, CoralEdge } from '../types.js';
|
|
7
|
+
/**
|
|
8
|
+
* Convert a Graph-IR node to React Flow node
|
|
9
|
+
*/
|
|
10
|
+
export declare function convertNode(node: GraphNode, index: number, parentId?: string): CoralNode;
|
|
11
|
+
/**
|
|
12
|
+
* Flatten nested nodes for React Flow
|
|
13
|
+
* React Flow doesn't support deeply nested nodes well, so we flatten
|
|
14
|
+
* and use parentId for grouping
|
|
15
|
+
*/
|
|
16
|
+
export declare function flattenNodes(nodes: GraphNode[]): CoralNode[];
|
|
17
|
+
/**
|
|
18
|
+
* Convert a Graph-IR edge to React Flow edge
|
|
19
|
+
*/
|
|
20
|
+
export declare function convertEdge(edge: GraphEdge): CoralEdge;
|
|
21
|
+
/**
|
|
22
|
+
* Convert entire Graph-IR to React Flow format
|
|
23
|
+
*/
|
|
24
|
+
export declare function convertGraphToFlow(graph: GraphIR): {
|
|
25
|
+
nodes: CoralNode[];
|
|
26
|
+
edges: CoralEdge[];
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Convert React Flow nodes back to Graph-IR nodes
|
|
30
|
+
* Used for bidirectional sync
|
|
31
|
+
*/
|
|
32
|
+
export declare function convertFlowToGraphNodes(flowNodes: CoralNode[], originalNodes: GraphNode[]): GraphNode[];
|
|
33
|
+
/**
|
|
34
|
+
* Convert React Flow edges back to Graph-IR edges
|
|
35
|
+
*/
|
|
36
|
+
export declare function convertFlowToGraphEdges(flowEdges: CoralEdge[]): GraphEdge[];
|
|
37
|
+
//# sourceMappingURL=converter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"converter.d.ts","sourceRoot":"","sources":["../../src/editor/converter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EACV,OAAO,EACP,SAAS,EACT,SAAS,EACT,SAAS,EACT,SAAS,EAGV,MAAM,aAAa,CAAC;AAoCrB;;GAEG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,SAAS,EACf,KAAK,EAAE,MAAM,EACb,QAAQ,CAAC,EAAE,MAAM,GAChB,SAAS,CAqDX;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,SAAS,EAAE,CAmB5D;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,SAAS,GAAG,SAAS,CA8CtD;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG;IAClD,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,KAAK,EAAE,SAAS,EAAE,CAAC;CACpB,CAKA;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,SAAS,EAAE,EACtB,aAAa,EAAE,SAAS,EAAE,GACzB,SAAS,EAAE,CA4Db;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,SAAS,EAAE,GAAG,SAAS,EAAE,CA+B3E"}
|