@work-graph/cli 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -0
- package/bin/work-graph.mjs +238 -0
- package/package.json +38 -0
- package/vendor/packages/design-tokens/generated/gripe-dark-default.css +67 -0
- package/vendor/packages/design-tokens/generated/marketplace-default.css +67 -0
- package/vendor/packages/design-tokens/generated/workgraph-dark.css +67 -0
- package/vendor/packages/workgraph-mcp/README.md +28 -0
- package/vendor/packages/workgraph-mcp/bin/workgraph-mcp.mjs +21 -0
- package/vendor/packages/workgraph-mcp/package.json +37 -0
- package/vendor/packages/workgraph-mcp/src/handlers.mjs +761 -0
- package/vendor/packages/workgraph-mcp/src/index.mjs +638 -0
- package/vendor/packages/workgraph-mcp/src/prompts.mjs +162 -0
- package/vendor/public/assets/workgraph-logo.svg +11 -0
- package/vendor/public/fonts/GraphikLCG/GraphikLCG-Medium.woff2 +0 -0
- package/vendor/public/fonts/GraphikLCG/GraphikLCG-Regular.woff2 +0 -0
- package/vendor/public/fonts/GraphikLCG/GraphikLCG-Semibold.woff2 +0 -0
- package/vendor/public/fonts/GraphikLCG/stylesheet.css +25 -0
- package/vendor/public/graph-canvas-lit-flow.css +154 -0
- package/vendor/public/graph-canvas-lit-flow.css.map +7 -0
- package/vendor/public/graph-canvas-lit-flow.js +8530 -0
- package/vendor/public/graph-canvas-lit-flow.js.map +7 -0
- package/vendor/src/agentBehaviorRulesAudit.mjs +168 -0
- package/vendor/src/agentBehaviorRulesBundle.mjs +144 -0
- package/vendor/src/agentRunApi.mjs +136 -0
- package/vendor/src/agentToolLoopGuard.mjs +88 -0
- package/vendor/src/agentWorkerClaudeProvider.mjs +288 -0
- package/vendor/src/agentWorkerCursorSdkProvider.mjs +156 -0
- package/vendor/src/agentWorkerLiveLoop.mjs +455 -0
- package/vendor/src/agentWorkerLocalCliProvider.mjs +217 -0
- package/vendor/src/agentWorkerLocalRunner.mjs +246 -0
- package/vendor/src/agentWorkerOpenAiProvider.mjs +459 -0
- package/vendor/src/analyticsPanelProjection.mjs +212 -0
- package/vendor/src/analyticsRecordStore.mjs +165 -0
- package/vendor/src/analyticsRecordWorkItems.mjs +104 -0
- package/vendor/src/architectureL1Canon.mjs +419 -0
- package/vendor/src/architectureLayout.mjs +229 -0
- package/vendor/src/architectureSnapshot.mjs +490 -0
- package/vendor/src/architectureViewsProjection.mjs +116 -0
- package/vendor/src/atomInspector.mjs +253 -0
- package/vendor/src/atomInspectorApi.mjs +130 -0
- package/vendor/src/auditGapMatrixRefresh.mjs +121 -0
- package/vendor/src/backlogSchemaLint.mjs +176 -0
- package/vendor/src/blockedOnebaseGoPreflightEval.mjs +100 -0
- package/vendor/src/bracketIrTraceSignal.mjs +93 -0
- package/vendor/src/bvcAtomParser.mjs +210 -0
- package/vendor/src/bvcDialectRegistry.mjs +86 -0
- package/vendor/src/bvcFileFormat.mjs +218 -0
- package/vendor/src/bvcFormatCli.mjs +55 -0
- package/vendor/src/bvcLintCli.mjs +48 -0
- package/vendor/src/bvcNewWritePolicy.mjs +70 -0
- package/vendor/src/charterPreflightPromoteGate.mjs +194 -0
- package/vendor/src/claimNoEligibleEval.mjs +205 -0
- package/vendor/src/closingAnalysisSuggest.mjs +59 -0
- package/vendor/src/codeGapAnalyzer.mjs +308 -0
- package/vendor/src/codeGapBacklogFeeder.mjs +82 -0
- package/vendor/src/codeGapDraftIntakeApi.mjs +307 -0
- package/vendor/src/codeGapOperatorProjection.mjs +60 -0
- package/vendor/src/codeSyntaxHighlight.mjs +123 -0
- package/vendor/src/codegenEvidence.mjs +187 -0
- package/vendor/src/compilerRoundTripCli.mjs +164 -0
- package/vendor/src/dagreGraphLayout.mjs +78 -0
- package/vendor/src/draftIntakePromotionRules.mjs +205 -0
- package/vendor/src/epicWorkScope.mjs +85 -0
- package/vendor/src/evalLiveLlmEnv.mjs +63 -0
- package/vendor/src/evidenceReadModel.mjs +167 -0
- package/vendor/src/gfsOverlayProjectPassport.mjs +235 -0
- package/vendor/src/globalStepPathToBvcReferences.mjs +196 -0
- package/vendor/src/goldenPath.mjs +69 -0
- package/vendor/src/graphCanvasLayout.mjs +464 -0
- package/vendor/src/graphCanvasLitFlow/client/graphCanvasMinimap.ts +261 -0
- package/vendor/src/graphCanvasLitFlow/client/graphCanvasSvgEdges.ts +259 -0
- package/vendor/src/graphCanvasLitFlow/client/graphCanvasTheme.css +152 -0
- package/vendor/src/graphCanvasLitFlow/client/graphCardNode.ts +328 -0
- package/vendor/src/graphCanvasLitFlow/client/mountGraphCanvasLitFlow.ts +322 -0
- package/vendor/src/graphCanvasLitFlow/graphCanvasEdgeLabels.mjs +58 -0
- package/vendor/src/graphCanvasLitFlow/graphCanvasEdgeRouter.mjs +142 -0
- package/vendor/src/graphCanvasLitFlow/graphCanvasLayoutProfile.mjs +32 -0
- package/vendor/src/graphCanvasLitFlow/graphCanvasNodeMetrics.mjs +45 -0
- package/vendor/src/graphCanvasLitFlow/graphCanvasProjection.mjs +115 -0
- package/vendor/src/graphCanvasLitFlow/graphCanvasProjectionToFlow.mjs +133 -0
- package/vendor/src/graphCanvasLitFlow/graphCanvasTraversal.mjs +77 -0
- package/vendor/src/graphCanvasLitFlow/layoutIntentRoadmapWorkStack.mjs +73 -0
- package/vendor/src/graphCanvasLitFlow/resolveGraphCanvasOverlaps.mjs +77 -0
- package/vendor/src/graphRagContextSlice.mjs +461 -0
- package/vendor/src/gvmVerifyWorkerGate.mjs +95 -0
- package/vendor/src/homeSnapshotApi.mjs +131 -0
- package/vendor/src/homeSnapshotProjection.mjs +275 -0
- package/vendor/src/inboxEventStream.mjs +140 -0
- package/vendor/src/intentComposerApi.mjs +245 -0
- package/vendor/src/intentGraphGbcSliceBoundary.mjs +258 -0
- package/vendor/src/intentGraphProjection.mjs +208 -0
- package/vendor/src/intentHierarchy.mjs +241 -0
- package/vendor/src/intentNodeLint.mjs +107 -0
- package/vendor/src/intentNodeRuntime.mjs +185 -0
- package/vendor/src/intentRoadmapCanvas.mjs +393 -0
- package/vendor/src/intentRoadmapEpicProjection.mjs +122 -0
- package/vendor/src/intentRoadmapMermaid.mjs +165 -0
- package/vendor/src/intentRoadmapProjection.mjs +85 -0
- package/vendor/src/intentTreeLint.mjs +114 -0
- package/vendor/src/intentTreeMigration.mjs +150 -0
- package/vendor/src/intentTreeWorkItems.mjs +227 -0
- package/vendor/src/kanbanBoardProjection.mjs +58 -0
- package/vendor/src/languageAdapterRegistry.mjs +180 -0
- package/vendor/src/languageAdapters/goAdapter.mjs +62 -0
- package/vendor/src/languageAdapters/jsTsAdapter.mjs +60 -0
- package/vendor/src/languageAdapters/jsonYamlAdapter.mjs +103 -0
- package/vendor/src/languageAdapters/onebaseOsAdapter.mjs +55 -0
- package/vendor/src/languageAdapters/plaintextAdapter.mjs +36 -0
- package/vendor/src/languageAdapters/shared.mjs +68 -0
- package/vendor/src/languageAdapters/stepAdapter.mjs +81 -0
- package/vendor/src/lintPlanWorkAlignment.mjs +136 -0
- package/vendor/src/loopHintRepeatToolEval.mjs +153 -0
- package/vendor/src/lowcodeScaffoldCli.mjs +386 -0
- package/vendor/src/markdownDocumentRender.mjs +208 -0
- package/vendor/src/memoryPanelProjection.mjs +116 -0
- package/vendor/src/memoryRecordWriter.mjs +243 -0
- package/vendor/src/memoryWorkerSlice.mjs +238 -0
- package/vendor/src/migrateStepToBvc.mjs +133 -0
- package/vendor/src/missionControlServerHandlers.mjs +195 -0
- package/vendor/src/missionControlUiClient.mjs +278 -0
- package/vendor/src/onebaseCliCapabilityProbe.mjs +107 -0
- package/vendor/src/onebaseCliRunner.mjs +145 -0
- package/vendor/src/onebaseGrossProfitStaticVerify.mjs +98 -0
- package/vendor/src/onebaseParityEvidenceSync.mjs +88 -0
- package/vendor/src/onebasePvrgGraphNodes.mjs +257 -0
- package/vendor/src/onebaseRestEvidenceAdapter.mjs +216 -0
- package/vendor/src/onebaseVectorDslCodegenReadiness.mjs +137 -0
- package/vendor/src/onebaseWorkItemTemplate.mjs +154 -0
- package/vendor/src/onebaseWorkerTools.mjs +586 -0
- package/vendor/src/operatorShellProjection.mjs +102 -0
- package/vendor/src/pipelineProseRender.mjs +180 -0
- package/vendor/src/pipelineStageLint.mjs +118 -0
- package/vendor/src/promptRulesEditorApi.mjs +174 -0
- package/vendor/src/promptRulesProjection.mjs +134 -0
- package/vendor/src/pvrg/bladeAdapter.mjs +40 -0
- package/vendor/src/pvrgTaskScope.mjs +152 -0
- package/vendor/src/releaseGateMatrix.mjs +188 -0
- package/vendor/src/schematicView.mjs +305 -0
- package/vendor/src/seedAnalyticsRecord.mjs +217 -0
- package/vendor/src/semanticSearchBm25.mjs +103 -0
- package/vendor/src/semanticSearchExcerpts.mjs +68 -0
- package/vendor/src/semanticSearchTfidfVector.mjs +86 -0
- package/vendor/src/semanticSearchWorkflow.mjs +366 -0
- package/vendor/src/stepAtomFormatter.mjs +413 -0
- package/vendor/src/stepGraphSlice.mjs +318 -0
- package/vendor/src/ui/atoms/badge.mjs +40 -0
- package/vendor/src/ui/atoms/badgeClient.mjs +32 -0
- package/vendor/src/ui/atoms/button.mjs +114 -0
- package/vendor/src/ui/atoms/buttonClient.mjs +49 -0
- package/vendor/src/ui/atoms/icon.mjs +23 -0
- package/vendor/src/ui/atoms/input.mjs +38 -0
- package/vendor/src/ui/atoms/modal.mjs +44 -0
- package/vendor/src/ui/atoms/select.mjs +98 -0
- package/vendor/src/ui/backlogShellButtons.mjs +238 -0
- package/vendor/src/ui/htmlEscape.mjs +11 -0
- package/vendor/src/ui/molecules/rating.mjs +48 -0
- package/vendor/src/ui/molecules/tabs.mjs +70 -0
- package/vendor/src/ui/organisms/modal.mjs +1 -0
- package/vendor/src/ui/pages/uiKitPage.mjs +147 -0
- package/vendor/src/ui/workItemStatusTone.mjs +36 -0
- package/vendor/src/unifiedLinkageProjection.mjs +264 -0
- package/vendor/src/verificationLoop.mjs +206 -0
- package/vendor/src/workGraphBacklogPersist.mjs +234 -0
- package/vendor/src/workGraphBacklogUiServer.mjs +9192 -0
- package/vendor/src/workGraphBoundedTargetFileRead.mjs +178 -0
- package/vendor/src/workGraphCycleSlice.mjs +184 -0
- package/vendor/src/workGraphDaemonTick.mjs +307 -0
- package/vendor/src/workGraphDaemonWatch.mjs +157 -0
- package/vendor/src/workGraphEngineRoot.mjs +136 -0
- package/vendor/src/workGraphInstallLayout.mjs +65 -0
- package/vendor/src/workGraphLlmUsefulnessEval.mjs +611 -0
- package/vendor/src/workGraphPhasePromoteReadyQueue.mjs +159 -0
- package/vendor/src/workGraphProjectHost.mjs +149 -0
- package/vendor/src/workGraphProjectInit.mjs +392 -0
- package/vendor/src/workGraphPromoteReadyApi.mjs +115 -0
- package/vendor/src/workGraphRecoveryPolicy.mjs +124 -0
- package/vendor/src/workGraphRunnerQueueProjection.mjs +187 -0
- package/vendor/src/workGraphRuntime.mjs +1008 -0
- package/vendor/src/workGraphToolSurfaceAudit.mjs +372 -0
- package/vendor/src/workGraphToolTransportRuntime.mjs +195 -0
- package/vendor/src/workGraphWorkerProvider.mjs +600 -0
- package/vendor/src/workItemBvcQuality.mjs +262 -0
- package/vendor/src/workItemCreateAnalysis.mjs +157 -0
- package/vendor/src/workItemDecisionPipeline.mjs +278 -0
- package/vendor/src/workItemEpicCascade.mjs +176 -0
- package/vendor/src/workItemExecutionGate.mjs +78 -0
- package/vendor/src/workItemHierarchy.mjs +226 -0
- package/vendor/src/workItemProseLint.mjs +133 -0
- package/vendor/src/workItemTextRusify.mjs +794 -0
- package/vendor/src/workItemTraceEnvelope.mjs +158 -0
- package/vendor/src/workItemUiReferences.mjs +272 -0
- package/vendor/src/workflowEpicGrouping.mjs +67 -0
- package/vendor/src/workflowTreeProjection.mjs +53 -0
- package/vendor/src/workspaceRegistry.mjs +150 -0
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
import type { FlowCanvas } from 'lit-flow';
|
|
2
|
+
|
|
3
|
+
type FlowNodeState = {
|
|
4
|
+
id: string;
|
|
5
|
+
position: { x: number; y: number };
|
|
6
|
+
width?: number;
|
|
7
|
+
height?: number;
|
|
8
|
+
measured?: { width?: number; height?: number };
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
type FlowInstanceLike = {
|
|
12
|
+
container: HTMLElement | null;
|
|
13
|
+
getState: () => { nodes: FlowNodeState[]; viewport: { x: number; y: number; zoom: number } };
|
|
14
|
+
getViewport: () => { x: number; y: number; zoom: number };
|
|
15
|
+
setViewport: (viewport: { x: number; y: number; zoom: number }) => void;
|
|
16
|
+
subscribe: (callback: () => void) => () => void;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
type GraphBounds = {
|
|
20
|
+
minX: number;
|
|
21
|
+
minY: number;
|
|
22
|
+
width: number;
|
|
23
|
+
height: number;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
type MinimapTransform = {
|
|
27
|
+
bounds: GraphBounds;
|
|
28
|
+
scale: number;
|
|
29
|
+
offsetX: number;
|
|
30
|
+
offsetY: number;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export type GraphCanvasMinimapOptions = {
|
|
34
|
+
width?: number;
|
|
35
|
+
height?: number;
|
|
36
|
+
theme?: 'dark' | 'light';
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const minimapCleanups = new WeakMap<HTMLElement, () => void>();
|
|
40
|
+
|
|
41
|
+
function nodeSize(node: FlowNodeState) {
|
|
42
|
+
return {
|
|
43
|
+
width: node.measured?.width ?? node.width ?? 240,
|
|
44
|
+
height: node.measured?.height ?? node.height ?? 96,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function computeGraphBounds(nodes: FlowNodeState[]): GraphBounds | null {
|
|
49
|
+
if (nodes.length === 0) {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
let minX = Infinity;
|
|
54
|
+
let minY = Infinity;
|
|
55
|
+
let maxX = -Infinity;
|
|
56
|
+
let maxY = -Infinity;
|
|
57
|
+
|
|
58
|
+
for (const node of nodes) {
|
|
59
|
+
const { width, height } = nodeSize(node);
|
|
60
|
+
minX = Math.min(minX, node.position.x);
|
|
61
|
+
minY = Math.min(minY, node.position.y);
|
|
62
|
+
maxX = Math.max(maxX, node.position.x + width);
|
|
63
|
+
maxY = Math.max(maxY, node.position.y + height);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const pad = 28;
|
|
67
|
+
return {
|
|
68
|
+
minX: minX - pad,
|
|
69
|
+
minY: minY - pad,
|
|
70
|
+
width: Math.max(1, maxX - minX + pad * 2),
|
|
71
|
+
height: Math.max(1, maxY - minY + pad * 2),
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function buildMinimapTransform(bounds: GraphBounds, width: number, height: number): MinimapTransform {
|
|
76
|
+
const scale = Math.min(width / bounds.width, height / bounds.height);
|
|
77
|
+
const offsetX = (width - bounds.width * scale) / 2;
|
|
78
|
+
const offsetY = (height - bounds.height * scale) / 2;
|
|
79
|
+
return { bounds, scale, offsetX, offsetY };
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function graphToMinimap(transform: MinimapTransform, x: number, y: number) {
|
|
83
|
+
return {
|
|
84
|
+
x: transform.offsetX + (x - transform.bounds.minX) * transform.scale,
|
|
85
|
+
y: transform.offsetY + (y - transform.bounds.minY) * transform.scale,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function minimapToGraph(transform: MinimapTransform, x: number, y: number) {
|
|
90
|
+
return {
|
|
91
|
+
x: transform.bounds.minX + (x - transform.offsetX) / transform.scale,
|
|
92
|
+
y: transform.bounds.minY + (y - transform.offsetY) / transform.scale,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function createSvgElement<K extends keyof SVGElementTagNameMap>(
|
|
97
|
+
tag: K,
|
|
98
|
+
attrs: Record<string, string> = {},
|
|
99
|
+
) {
|
|
100
|
+
const element = document.createElementNS('http://www.w3.org/2000/svg', tag);
|
|
101
|
+
for (const [key, value] of Object.entries(attrs)) {
|
|
102
|
+
element.setAttribute(key, value);
|
|
103
|
+
}
|
|
104
|
+
return element;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export function mountGraphCanvasMinimap(
|
|
108
|
+
host: HTMLElement,
|
|
109
|
+
getCanvas: () => FlowCanvas | null,
|
|
110
|
+
options: GraphCanvasMinimapOptions = {},
|
|
111
|
+
): () => void {
|
|
112
|
+
minimapCleanups.get(host)?.();
|
|
113
|
+
|
|
114
|
+
const width = options.width ?? 168;
|
|
115
|
+
const height = options.height ?? 108;
|
|
116
|
+
host.replaceChildren();
|
|
117
|
+
host.classList.add('graph-canvas-minimap');
|
|
118
|
+
host.dataset.theme = options.theme ?? 'light';
|
|
119
|
+
host.setAttribute('role', 'img');
|
|
120
|
+
host.setAttribute('aria-label', 'Graph overview');
|
|
121
|
+
|
|
122
|
+
const svg = createSvgElement('svg', {
|
|
123
|
+
width: String(width),
|
|
124
|
+
height: String(height),
|
|
125
|
+
viewBox: `0 0 ${width} ${height}`,
|
|
126
|
+
});
|
|
127
|
+
const nodesLayer = createSvgElement('g', { class: 'graph-canvas-minimap-nodes' });
|
|
128
|
+
const viewportLayer = createSvgElement('rect', {
|
|
129
|
+
class: 'graph-canvas-minimap-viewport',
|
|
130
|
+
'pointer-events': 'none',
|
|
131
|
+
});
|
|
132
|
+
svg.appendChild(nodesLayer);
|
|
133
|
+
svg.appendChild(viewportLayer);
|
|
134
|
+
host.appendChild(svg);
|
|
135
|
+
|
|
136
|
+
let unsubscribe: (() => void) | null = null;
|
|
137
|
+
let rafId = 0;
|
|
138
|
+
let latestTransform: MinimapTransform | null = null;
|
|
139
|
+
|
|
140
|
+
const schedulePaint = () => {
|
|
141
|
+
window.cancelAnimationFrame(rafId);
|
|
142
|
+
rafId = window.requestAnimationFrame(paint);
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
const paint = () => {
|
|
146
|
+
const canvas = getCanvas();
|
|
147
|
+
const instance = canvas?.instance as FlowInstanceLike | undefined;
|
|
148
|
+
if (!instance) {
|
|
149
|
+
nodesLayer.replaceChildren();
|
|
150
|
+
viewportLayer.setAttribute('width', '0');
|
|
151
|
+
viewportLayer.setAttribute('height', '0');
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const { nodes } = instance.getState();
|
|
156
|
+
const bounds = computeGraphBounds(nodes);
|
|
157
|
+
if (!bounds) {
|
|
158
|
+
nodesLayer.replaceChildren();
|
|
159
|
+
viewportLayer.setAttribute('width', '0');
|
|
160
|
+
viewportLayer.setAttribute('height', '0');
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
latestTransform = buildMinimapTransform(bounds, width, height);
|
|
165
|
+
nodesLayer.replaceChildren();
|
|
166
|
+
|
|
167
|
+
for (const node of nodes) {
|
|
168
|
+
const size = nodeSize(node);
|
|
169
|
+
const topLeft = graphToMinimap(latestTransform, node.position.x, node.position.y);
|
|
170
|
+
const rect = createSvgElement('rect', {
|
|
171
|
+
class: 'graph-canvas-minimap-node',
|
|
172
|
+
x: String(topLeft.x),
|
|
173
|
+
y: String(topLeft.y),
|
|
174
|
+
width: String(Math.max(2, size.width * latestTransform.scale)),
|
|
175
|
+
height: String(Math.max(2, size.height * latestTransform.scale)),
|
|
176
|
+
rx: '2',
|
|
177
|
+
});
|
|
178
|
+
nodesLayer.appendChild(rect);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const container = instance.container ?? canvas;
|
|
182
|
+
const viewport = instance.getViewport();
|
|
183
|
+
const zoom = viewport.zoom || 1;
|
|
184
|
+
const visibleX = -viewport.x / zoom;
|
|
185
|
+
const visibleY = -viewport.y / zoom;
|
|
186
|
+
const visibleWidth = container.clientWidth / zoom;
|
|
187
|
+
const visibleHeight = container.clientHeight / zoom;
|
|
188
|
+
const viewportTopLeft = graphToMinimap(latestTransform, visibleX, visibleY);
|
|
189
|
+
const viewportBottomRight = graphToMinimap(
|
|
190
|
+
latestTransform,
|
|
191
|
+
visibleX + visibleWidth,
|
|
192
|
+
visibleY + visibleHeight,
|
|
193
|
+
);
|
|
194
|
+
|
|
195
|
+
viewportLayer.setAttribute('x', String(viewportTopLeft.x));
|
|
196
|
+
viewportLayer.setAttribute('y', String(viewportTopLeft.y));
|
|
197
|
+
viewportLayer.setAttribute('width', String(Math.max(2, viewportBottomRight.x - viewportTopLeft.x)));
|
|
198
|
+
viewportLayer.setAttribute('height', String(Math.max(2, viewportBottomRight.y - viewportTopLeft.y)));
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
const bindInstance = () => {
|
|
202
|
+
unsubscribe?.();
|
|
203
|
+
unsubscribe = null;
|
|
204
|
+
|
|
205
|
+
const canvas = getCanvas();
|
|
206
|
+
const instance = canvas?.instance as FlowInstanceLike | undefined;
|
|
207
|
+
if (!instance?.subscribe) {
|
|
208
|
+
window.requestAnimationFrame(bindInstance);
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
unsubscribe = instance.subscribe(schedulePaint);
|
|
213
|
+
schedulePaint();
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
const onPointerDown = (event: PointerEvent) => {
|
|
217
|
+
if (!latestTransform) {
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
const canvas = getCanvas();
|
|
221
|
+
const instance = canvas?.instance as FlowInstanceLike | undefined;
|
|
222
|
+
if (!instance) {
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
const rect = svg.getBoundingClientRect();
|
|
227
|
+
const localX = event.clientX - rect.left;
|
|
228
|
+
const localY = event.clientY - rect.top;
|
|
229
|
+
const graphPoint = minimapToGraph(latestTransform, localX, localY);
|
|
230
|
+
const container = instance.container ?? canvas;
|
|
231
|
+
const viewport = instance.getViewport();
|
|
232
|
+
const zoom = viewport.zoom || 1;
|
|
233
|
+
|
|
234
|
+
instance.setViewport({
|
|
235
|
+
x: container.clientWidth / 2 - graphPoint.x * zoom,
|
|
236
|
+
y: container.clientHeight / 2 - graphPoint.y * zoom,
|
|
237
|
+
zoom,
|
|
238
|
+
});
|
|
239
|
+
event.preventDefault();
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
svg.addEventListener('pointerdown', onPointerDown);
|
|
243
|
+
|
|
244
|
+
const cleanup = () => {
|
|
245
|
+
window.cancelAnimationFrame(rafId);
|
|
246
|
+
unsubscribe?.();
|
|
247
|
+
unsubscribe = null;
|
|
248
|
+
svg.removeEventListener('pointerdown', onPointerDown);
|
|
249
|
+
host.replaceChildren();
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
minimapCleanups.set(host, cleanup);
|
|
253
|
+
bindInstance();
|
|
254
|
+
|
|
255
|
+
return cleanup;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
export function unmountGraphCanvasMinimap(host: HTMLElement) {
|
|
259
|
+
minimapCleanups.get(host)?.();
|
|
260
|
+
minimapCleanups.delete(host);
|
|
261
|
+
}
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
import {
|
|
2
|
+
buildGraphCanvasEdgeLabelHtml,
|
|
3
|
+
buildGraphCanvasEdgeStrokeStyle,
|
|
4
|
+
} from '../graphCanvasEdgeLabels.mjs';
|
|
5
|
+
import { buildGraphCanvasEdgeRoutes } from '../graphCanvasEdgeRouter.mjs';
|
|
6
|
+
import type { FlowCanvas } from 'lit-flow';
|
|
7
|
+
|
|
8
|
+
type GraphCanvasProjection = {
|
|
9
|
+
layoutDirection?: string;
|
|
10
|
+
nodes: Array<{ id: string; x?: number; y?: number; width?: number; height?: number }>;
|
|
11
|
+
edges: Array<{ id?: string; from: string; to: string; label?: string; rejected?: boolean; upstream?: boolean }>;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
type SvgEdgeLayer = {
|
|
15
|
+
host: HTMLElement;
|
|
16
|
+
svg: SVGSVGElement;
|
|
17
|
+
labelsLayer: HTMLElement;
|
|
18
|
+
observer: MutationObserver | null;
|
|
19
|
+
paintKey: string;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const svgEdgeLayers = new WeakMap<FlowCanvas, SvgEdgeLayer>();
|
|
23
|
+
|
|
24
|
+
function resolveGraphCanvasTheme(): 'dark' | 'light' {
|
|
25
|
+
return document.body?.dataset?.theme === 'dark' ? 'dark' : 'light';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function buildPaintKey(projection: GraphCanvasProjection, theme: 'dark' | 'light') {
|
|
29
|
+
return `${theme}:${projection.layoutDirection ?? 'LR'}:${projection.edges.length}:${projection.nodes.length}`;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function buildMarkerDefs(theme: 'dark' | 'light') {
|
|
33
|
+
const color = theme === 'dark' ? '#858585' : '#8b8b95';
|
|
34
|
+
return `
|
|
35
|
+
<defs>
|
|
36
|
+
<marker id="wg-edge-arrow" markerWidth="12" markerHeight="12" refX="10" refY="6" orient="auto" markerUnits="userSpaceOnUse">
|
|
37
|
+
<path d="M0,0 L12,6 L0,12 Z" fill="${color}" />
|
|
38
|
+
</marker>
|
|
39
|
+
<marker id="wg-edge-arrow-upstream" markerWidth="12" markerHeight="12" refX="10" refY="6" orient="auto" markerUnits="userSpaceOnUse">
|
|
40
|
+
<path d="M0,0 L12,6 L0,12 Z" fill="${color}" opacity="0.72" />
|
|
41
|
+
</marker>
|
|
42
|
+
<marker id="wg-edge-arrow-rejected" markerWidth="12" markerHeight="12" refX="10" refY="6" orient="auto" markerUnits="userSpaceOnUse">
|
|
43
|
+
<path d="M0,0 L12,6 L0,12 Z" fill="${color}" opacity="0.42" />
|
|
44
|
+
</marker>
|
|
45
|
+
</defs>
|
|
46
|
+
`;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function paintSvgEdges(
|
|
50
|
+
layer: SvgEdgeLayer,
|
|
51
|
+
projection: GraphCanvasProjection,
|
|
52
|
+
theme: 'dark' | 'light',
|
|
53
|
+
force = false,
|
|
54
|
+
) {
|
|
55
|
+
const paintKey = buildPaintKey(projection, theme);
|
|
56
|
+
if (!force && layer.paintKey === paintKey) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const routes = buildGraphCanvasEdgeRoutes(projection);
|
|
61
|
+
const paths = routes.map((route) => {
|
|
62
|
+
const stroke = buildGraphCanvasEdgeStrokeStyle(
|
|
63
|
+
{ rejected: route.rejected, upstream: route.upstream },
|
|
64
|
+
theme,
|
|
65
|
+
);
|
|
66
|
+
const marker = route.rejected
|
|
67
|
+
? 'url(#wg-edge-arrow-rejected)'
|
|
68
|
+
: route.upstream
|
|
69
|
+
? 'url(#wg-edge-arrow-upstream)'
|
|
70
|
+
: 'url(#wg-edge-arrow)';
|
|
71
|
+
const dash = route.rejected
|
|
72
|
+
? 'stroke-dasharray="6 4" opacity="0.42"'
|
|
73
|
+
: route.upstream
|
|
74
|
+
? 'stroke-dasharray="5 4" opacity="0.72"'
|
|
75
|
+
: '';
|
|
76
|
+
return `<path class="graph-canvas-edge-path" data-edge-id="${route.id}" d="${route.d}" fill="none" stroke="${stroke.stroke}" stroke-width="${route.rejected ? 1.75 : 2.25}" marker-end="${marker}" ${dash} />`;
|
|
77
|
+
}).join('');
|
|
78
|
+
|
|
79
|
+
layer.svg.innerHTML = `${buildMarkerDefs(theme)}<g class="graph-canvas-edge-paths">${paths}</g>`;
|
|
80
|
+
|
|
81
|
+
layer.labelsLayer.replaceChildren();
|
|
82
|
+
for (const route of routes) {
|
|
83
|
+
if (!route.label) {
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
const labelHtml = buildGraphCanvasEdgeLabelHtml(route.label, theme, { rejected: route.rejected });
|
|
87
|
+
if (!labelHtml) {
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
const label = document.createElement('div');
|
|
91
|
+
label.className = 'graph-canvas-edge-label';
|
|
92
|
+
label.style.left = `${route.labelX}px`;
|
|
93
|
+
label.style.top = `${route.labelY}px`;
|
|
94
|
+
if (route.labelPlacement === 'start') {
|
|
95
|
+
label.style.transform = 'translate(8px, -50%)';
|
|
96
|
+
} else {
|
|
97
|
+
label.style.transform = 'translate(-50%, -50%)';
|
|
98
|
+
}
|
|
99
|
+
label.innerHTML = labelHtml;
|
|
100
|
+
layer.labelsLayer.appendChild(label);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
layer.paintKey = paintKey;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function createSvgEdgeHost(): HTMLElement {
|
|
107
|
+
const host = document.createElement('div');
|
|
108
|
+
host.className = 'graph-canvas-wg-edges-layer';
|
|
109
|
+
host.dataset.testid = 'graph-canvas-svg-edges';
|
|
110
|
+
host.style.cssText = 'position:absolute;inset:0;pointer-events:none;z-index:0;overflow:visible;';
|
|
111
|
+
return host;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function createSvgEdgeLayer(host: HTMLElement): SvgEdgeLayer {
|
|
115
|
+
host.replaceChildren();
|
|
116
|
+
|
|
117
|
+
const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
|
118
|
+
svg.setAttribute('class', 'graph-canvas-svg-edges-svg');
|
|
119
|
+
svg.setAttribute('aria-hidden', 'true');
|
|
120
|
+
svg.style.cssText = 'position:absolute;inset:0;overflow:visible;display:block;';
|
|
121
|
+
|
|
122
|
+
const labelsLayer = document.createElement('div');
|
|
123
|
+
labelsLayer.className = 'graph-canvas-svg-edge-labels';
|
|
124
|
+
labelsLayer.style.cssText = 'position:absolute;inset:0;pointer-events:none;';
|
|
125
|
+
|
|
126
|
+
host.appendChild(svg);
|
|
127
|
+
host.appendChild(labelsLayer);
|
|
128
|
+
|
|
129
|
+
return {
|
|
130
|
+
host,
|
|
131
|
+
svg,
|
|
132
|
+
labelsLayer,
|
|
133
|
+
observer: null,
|
|
134
|
+
paintKey: '',
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function getFlowViewport(canvas: FlowCanvas) {
|
|
139
|
+
return canvas.shadowRoot?.querySelector('.flow-viewport') ?? null;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function restoreSvgEdgeLayerIfMissing(canvas: FlowCanvas, projection: GraphCanvasProjection) {
|
|
143
|
+
const viewport = getFlowViewport(canvas);
|
|
144
|
+
const nodesLayer = viewport?.querySelector('.flow-nodes-layer');
|
|
145
|
+
if (!viewport || !nodesLayer) {
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
let layer = svgEdgeLayers.get(canvas);
|
|
150
|
+
if (layer?.host.isConnected && viewport.contains(layer.host)) {
|
|
151
|
+
return layer;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const host = createSvgEdgeHost();
|
|
155
|
+
viewport.insertBefore(host, nodesLayer);
|
|
156
|
+
layer = createSvgEdgeLayer(host);
|
|
157
|
+
svgEdgeLayers.set(canvas, layer);
|
|
158
|
+
paintSvgEdges(layer, projection, resolveGraphCanvasTheme(), true);
|
|
159
|
+
return layer;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function watchForSvgEdgeHostRemoval(canvas: FlowCanvas, projection: GraphCanvasProjection) {
|
|
163
|
+
const root = canvas.shadowRoot;
|
|
164
|
+
if (!root) {
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const existing = svgEdgeLayers.get(canvas);
|
|
169
|
+
existing?.observer?.disconnect();
|
|
170
|
+
|
|
171
|
+
let restoring = false;
|
|
172
|
+
const observer = new MutationObserver(() => {
|
|
173
|
+
if (restoring) {
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
const viewport = getFlowViewport(canvas);
|
|
177
|
+
if (!viewport?.querySelector('.flow-nodes-layer')) {
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
if (viewport.querySelector('.graph-canvas-wg-edges-layer')) {
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
restoring = true;
|
|
185
|
+
try {
|
|
186
|
+
restoreSvgEdgeLayerIfMissing(canvas, projection);
|
|
187
|
+
} finally {
|
|
188
|
+
restoring = false;
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
observer.observe(root, { childList: true, subtree: true });
|
|
193
|
+
|
|
194
|
+
const layer = svgEdgeLayers.get(canvas);
|
|
195
|
+
if (layer) {
|
|
196
|
+
layer.observer = observer;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
export function injectFlowCanvasNativeEdgeHide(canvas: FlowCanvas) {
|
|
201
|
+
const root = canvas.shadowRoot;
|
|
202
|
+
if (!root || root.querySelector('[data-wg-hide-native-edges]')) {
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
const style = document.createElement('style');
|
|
206
|
+
style.setAttribute('data-wg-hide-native-edges', 'true');
|
|
207
|
+
style.textContent = `
|
|
208
|
+
.flow-edges-layer,
|
|
209
|
+
.flow-labels-overlay {
|
|
210
|
+
display: none !important;
|
|
211
|
+
}
|
|
212
|
+
`;
|
|
213
|
+
root.appendChild(style);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
export function mountGraphCanvasSvgEdges(
|
|
217
|
+
canvas: FlowCanvas,
|
|
218
|
+
projection: GraphCanvasProjection,
|
|
219
|
+
): () => void {
|
|
220
|
+
unmountGraphCanvasSvgEdges(canvas);
|
|
221
|
+
|
|
222
|
+
let attempts = 0;
|
|
223
|
+
const tryMount = () => {
|
|
224
|
+
const layer = restoreSvgEdgeLayerIfMissing(canvas, projection);
|
|
225
|
+
if (!layer) {
|
|
226
|
+
attempts += 1;
|
|
227
|
+
if (attempts < 120) {
|
|
228
|
+
window.requestAnimationFrame(tryMount);
|
|
229
|
+
}
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
watchForSvgEdgeHostRemoval(canvas, projection);
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
tryMount();
|
|
236
|
+
|
|
237
|
+
return () => unmountGraphCanvasSvgEdges(canvas);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
export function unmountGraphCanvasSvgEdges(canvas: FlowCanvas) {
|
|
241
|
+
const layer = svgEdgeLayers.get(canvas);
|
|
242
|
+
if (!layer) {
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
layer.observer?.disconnect();
|
|
246
|
+
layer.host.remove();
|
|
247
|
+
svgEdgeLayers.delete(canvas);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
export function repaintGraphCanvasSvgEdges(
|
|
251
|
+
canvas: FlowCanvas,
|
|
252
|
+
projection: GraphCanvasProjection,
|
|
253
|
+
) {
|
|
254
|
+
const layer = restoreSvgEdgeLayerIfMissing(canvas, projection);
|
|
255
|
+
if (!layer) {
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
paintSvgEdges(layer, projection, resolveGraphCanvasTheme(), true);
|
|
259
|
+
}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/* Work Graph overrides for lit-flow chrome inside backlog UI */
|
|
2
|
+
|
|
3
|
+
.graph-canvas-lit-flow-host {
|
|
4
|
+
--wg-graph-node-bg: #ffffff;
|
|
5
|
+
--wg-graph-node-border: #dfe1e6;
|
|
6
|
+
--wg-graph-node-text: #172b4d;
|
|
7
|
+
--wg-graph-node-subtext: #5e6c84;
|
|
8
|
+
--wg-graph-node-hover-border: #c1c7d0;
|
|
9
|
+
--wg-graph-node-selected-border: #0052cc;
|
|
10
|
+
--wg-graph-node-rejected-bg: #f4f5f7;
|
|
11
|
+
--wg-graph-node-selected-bg: linear-gradient(180deg, #deebff 0%, #ffffff 72%);
|
|
12
|
+
--wg-graph-layer-bg: rgba(9, 30, 66, 0.05);
|
|
13
|
+
--wg-graph-layer-border: rgba(9, 30, 66, 0.1);
|
|
14
|
+
--wg-graph-badge-bg: #f4f5f7;
|
|
15
|
+
--wg-graph-badge-border: #dfe1e6;
|
|
16
|
+
--wg-graph-badge-done-bg: #e3fcef;
|
|
17
|
+
--wg-graph-badge-done-border: #abf5d1;
|
|
18
|
+
--wg-graph-badge-done-text: #006644;
|
|
19
|
+
--wg-graph-badge-doing-bg: #fff7d6;
|
|
20
|
+
--wg-graph-badge-doing-border: #f0c36d;
|
|
21
|
+
--wg-graph-badge-doing-text: #7a4f01;
|
|
22
|
+
--wg-graph-badge-ready-bg: #deebff;
|
|
23
|
+
--wg-graph-badge-ready-border: #85b8ff;
|
|
24
|
+
--wg-graph-badge-ready-text: #0052cc;
|
|
25
|
+
--wg-graph-badge-blocked-bg: #ffebe6;
|
|
26
|
+
--wg-graph-badge-blocked-border: #ffbdad;
|
|
27
|
+
--wg-graph-badge-blocked-text: #bf2600;
|
|
28
|
+
--wg-graph-tone-question: #0052cc;
|
|
29
|
+
--wg-graph-tone-analysis: #5b21b6;
|
|
30
|
+
--wg-graph-tone-decision: #9a6700;
|
|
31
|
+
--wg-graph-tone-work: #1a7f37;
|
|
32
|
+
--wg-graph-tone-architecture: #0052cc;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.graph-canvas-lit-flow-host[data-graph-theme='dark'],
|
|
36
|
+
body[data-theme='dark'] .graph-canvas-lit-flow-host {
|
|
37
|
+
--wg-graph-node-bg: #252526;
|
|
38
|
+
--wg-graph-node-border: #3c3c3c;
|
|
39
|
+
--wg-graph-node-text: #e0e0e0;
|
|
40
|
+
--wg-graph-node-subtext: #9d9d9d;
|
|
41
|
+
--wg-graph-node-hover-border: #4a4a4a;
|
|
42
|
+
--wg-graph-node-selected-border: #0066ff;
|
|
43
|
+
--wg-graph-node-rejected-bg: #1f1f1f;
|
|
44
|
+
--wg-graph-node-selected-bg: linear-gradient(180deg, #1a2940 0%, #252526 72%);
|
|
45
|
+
--wg-graph-layer-bg: rgba(255, 255, 255, 0.05);
|
|
46
|
+
--wg-graph-layer-border: rgba(255, 255, 255, 0.08);
|
|
47
|
+
--wg-graph-badge-bg: #2d2d30;
|
|
48
|
+
--wg-graph-badge-border: #3c3c3c;
|
|
49
|
+
--wg-graph-badge-done-bg: #173b2b;
|
|
50
|
+
--wg-graph-badge-done-border: #2f6f4f;
|
|
51
|
+
--wg-graph-badge-done-text: #b5f2cf;
|
|
52
|
+
--wg-graph-badge-doing-bg: #3d2e12;
|
|
53
|
+
--wg-graph-badge-doing-border: #7a5a16;
|
|
54
|
+
--wg-graph-badge-doing-text: #ffd599;
|
|
55
|
+
--wg-graph-badge-ready-bg: #17324d;
|
|
56
|
+
--wg-graph-badge-ready-border: #24517a;
|
|
57
|
+
--wg-graph-badge-ready-text: #cce0ff;
|
|
58
|
+
--wg-graph-badge-blocked-bg: #4a1f1a;
|
|
59
|
+
--wg-graph-badge-blocked-border: #8f3328;
|
|
60
|
+
--wg-graph-badge-blocked-text: #ffb3b3;
|
|
61
|
+
--wg-graph-tone-question: #4d9fff;
|
|
62
|
+
--wg-graph-tone-analysis: #a371f7;
|
|
63
|
+
--wg-graph-tone-decision: #f0ad4e;
|
|
64
|
+
--wg-graph-tone-work: #2ea043;
|
|
65
|
+
--wg-graph-tone-architecture: #569cd6;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.graph-canvas-lit-flow-shell flow-canvas[theme='dark'] {
|
|
69
|
+
--flow-background-color: #1e1e1e;
|
|
70
|
+
--flow-grid-color: #3c3c3c;
|
|
71
|
+
--flow-edge-color: #858585;
|
|
72
|
+
--flow-edge-selected-color: #0066ff;
|
|
73
|
+
--flow-node-selected-border: #0066ff;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.graph-canvas-lit-flow-shell flow-canvas[theme='light'] {
|
|
77
|
+
--flow-background-color: #f4f5f7;
|
|
78
|
+
--flow-grid-color: #dfe1e6;
|
|
79
|
+
--flow-edge-color: #97a0af;
|
|
80
|
+
--flow-edge-selected-color: #0052cc;
|
|
81
|
+
--flow-node-selected-border: #0052cc;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.graph-canvas-lit-flow-host:focus-visible {
|
|
85
|
+
outline: 2px solid var(--accent, #0066ff);
|
|
86
|
+
outline-offset: 2px;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.graph-canvas-lit-flow-host .empty {
|
|
90
|
+
display: flex;
|
|
91
|
+
align-items: center;
|
|
92
|
+
justify-content: center;
|
|
93
|
+
height: 100%;
|
|
94
|
+
color: var(--muted, #9d9d9d);
|
|
95
|
+
font-size: 13px;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.graph-canvas-minimap-host {
|
|
99
|
+
bottom: 12px;
|
|
100
|
+
pointer-events: auto;
|
|
101
|
+
position: absolute;
|
|
102
|
+
right: 12px;
|
|
103
|
+
z-index: 4;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.graph-canvas-minimap {
|
|
107
|
+
background: var(--wg-graph-minimap-bg, #ffffff);
|
|
108
|
+
border: 1px solid var(--wg-graph-minimap-border, #dfe1e6);
|
|
109
|
+
border-radius: 8px;
|
|
110
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);
|
|
111
|
+
cursor: pointer;
|
|
112
|
+
height: 108px;
|
|
113
|
+
opacity: 0.94;
|
|
114
|
+
overflow: hidden;
|
|
115
|
+
width: 168px;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.graph-canvas-minimap[data-theme='dark'] {
|
|
119
|
+
--wg-graph-minimap-bg: #252526;
|
|
120
|
+
--wg-graph-minimap-border: #3c3c3c;
|
|
121
|
+
--wg-graph-minimap-node-fill: #3c3c3c;
|
|
122
|
+
--wg-graph-minimap-node-stroke: #569cd6;
|
|
123
|
+
--wg-graph-minimap-viewport-stroke: #0066ff;
|
|
124
|
+
--wg-graph-minimap-viewport-fill: rgba(0, 102, 255, 0.14);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.graph-canvas-minimap[data-theme='light'] {
|
|
128
|
+
--wg-graph-minimap-bg: #ffffff;
|
|
129
|
+
--wg-graph-minimap-border: #dfe1e6;
|
|
130
|
+
--wg-graph-minimap-node-fill: #ebecf0;
|
|
131
|
+
--wg-graph-minimap-node-stroke: #97a0af;
|
|
132
|
+
--wg-graph-minimap-viewport-stroke: #0052cc;
|
|
133
|
+
--wg-graph-minimap-viewport-fill: rgba(0, 82, 204, 0.12);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.graph-canvas-minimap-node {
|
|
137
|
+
fill: var(--wg-graph-minimap-node-fill, #ebecf0);
|
|
138
|
+
stroke: var(--wg-graph-minimap-node-stroke, #97a0af);
|
|
139
|
+
stroke-width: 1;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.graph-canvas-minimap-viewport {
|
|
143
|
+
fill: var(--wg-graph-minimap-viewport-fill, rgba(0, 82, 204, 0.12));
|
|
144
|
+
stroke: var(--wg-graph-minimap-viewport-stroke, #0052cc);
|
|
145
|
+
stroke-width: 1.5;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
.graph-canvas-svg-edge-labels .graph-canvas-edge-label {
|
|
149
|
+
pointer-events: none;
|
|
150
|
+
position: absolute;
|
|
151
|
+
white-space: nowrap;
|
|
152
|
+
}
|