menu for deps

This commit is contained in:
2026-03-06 21:11:56 +01:00
parent 9cbd709b69
commit bec33211c7
8 changed files with 631 additions and 28 deletions

View File

@@ -1,4 +1,4 @@
import React, { memo, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react'
import React, { memo, useCallback, useContext, useEffect, useRef, useState } from 'react'
import { Handle, Position } from 'reactflow'
import Editor, { loader } from '@monaco-editor/react'
import FlowContext from '../../lib/flowContext'
@@ -9,7 +9,19 @@ import {
BaseNodeHeader,
BaseNodeHeaderTitle,
} from './BaseNode'
import { Pencil } from 'lucide-react'
import { GitBranch, Pencil } from 'lucide-react'
import {
Menubar,
MenubarContent,
MenubarItem,
MenubarLabel,
MenubarMenu,
MenubarSeparator,
MenubarSub,
MenubarSubContent,
MenubarSubTrigger,
MenubarTrigger,
} from '../ui/menubar'
// Ensure Monaco can load its web workers under Vite by pointing to a CDN
loader.config({ paths: { vs: 'https://unpkg.com/monaco-editor@latest/min/vs' } })
@@ -59,7 +71,7 @@ export const ConfigNode = memo(function ConfigNode({ id, data }: Props) {
}, [])
const insertIncludeFromNode = useCallback(
(sourceNode: any) => {
(sourceNode: any, mode: 'prepend' | 'append' | 'cursor') => {
const ref = `${sourceNode.id}.yaml`
const includeText = `!include ${ref}\n`
const editor = editorRef.current
@@ -67,22 +79,32 @@ export const ConfigNode = memo(function ConfigNode({ id, data }: Props) {
try {
if (editor && monaco) {
const model = editor.getModel()
const lineCount = model.getLineCount()
const selection = editor.getSelection()
let range
if (selection) {
if (mode === 'prepend') {
range = new monaco.Range(1, 1, 1, 1)
} else if (mode === 'append') {
range = new monaco.Range(lineCount + 1, 1, lineCount + 1, 1)
} else if (selection) {
range = new monaco.Range(selection.startLineNumber, selection.startColumn, selection.startLineNumber, selection.startColumn)
} else {
const model = editor.getModel()
const lineCount = model.getLineCount()
range = new monaco.Range(lineCount + 1, 1, lineCount + 1, 1)
}
editor.executeEdits('insert-include', [{ range, text: includeText, forceMoveMarkers: true }])
const newVal = editor.getModel().getValue()
onChange(newVal)
return
}
onChange(value + '\n' + includeText)
if (mode === 'prepend') {
onChange(includeText + value)
} else {
onChange(value + '\n' + includeText)
}
} catch (err) {
// eslint-disable-next-line no-console
console.error('Insert include failed', err)
@@ -100,23 +122,43 @@ export const ConfigNode = memo(function ConfigNode({ id, data }: Props) {
<BaseNodeContent>
{connectedConfigNodes.length > 0 && (
<div className="px-0 py-0 text-xs bg-gray-50 border-b border-gray-100 w-full">
<div className="text-xs font-medium text-gray-600 px-3 pt-3">Connected configs</div>
<div className="mt-1 space-y-1 px-3 pb-3">
{connectedConfigNodes.map((n: any) => (
<div key={n.id} className="flex items-center justify-between">
<div className="text-xs text-gray-700">{n.data?.title ?? n.id}</div>
<div>
<button
className="text-xs px-2 py-0.5 bg-white border rounded text-gray-600"
onClick={() => insertIncludeFromNode(n)}
>
Insert include
</button>
</div>
</div>
))}
</div>
<div className="w-full pb-1">
<Menubar className="h-7 bg-muted/60 px-1 py-0">
<MenubarMenu>
<MenubarTrigger className="px-1.5 py-0 text-xs">
<GitBranch className="size-3.5" />
</MenubarTrigger>
<MenubarContent className="min-w-[12rem]">
{connectedConfigNodes.map((n: any) => (
<MenubarSub key={n.id}>
<MenubarSubTrigger className="text-xs">
{n.data?.title ?? n.id}
</MenubarSubTrigger>
<MenubarSubContent>
<MenubarItem
className="text-xs"
onClick={() => insertIncludeFromNode(n, 'prepend')}
>
Prepend include
</MenubarItem>
<MenubarItem
className="text-xs"
onClick={() => insertIncludeFromNode(n, 'append')}
>
Append include
</MenubarItem>
<MenubarItem
className="text-xs"
onClick={() => insertIncludeFromNode(n, 'cursor')}
>
Insert at cursor
</MenubarItem>
</MenubarSubContent>
</MenubarSub>
))}
</MenubarContent>
</MenubarMenu>
</Menubar>
</div>
)}