Files
zui/frontend/src/components/nodes/config/descriptor.tsx
2026-03-12 17:07:42 +01:00

94 lines
3.1 KiB
TypeScript

import React from 'react'
import { ScrollText } from 'lucide-react'
import { createNodeTypeBuilder } from '@/lib/graph/nodeTypeBuilder'
import { NODE_HELP } from '@/lib/graph/nodeHelp'
import { getConfigType } from '@/lib/graph/rendering'
import {
MenubarItem,
MenubarSeparator,
MenubarSub,
MenubarSubContent,
MenubarSubTrigger,
} from '@/components/ui/menubar'
import { getResolvedContentForConfig } from './renderingLogic'
import type { NodeTypeDescriptor } from '@/lib/graph/nodeRegistry'
import ConfigNode from './ConfigNode'
import { createImageExportHandlers, type OutputMenuContext } from '@/components/nodes/render/outputMenuHandlers'
const ICON_CLASS = 'mr-2 h-4 w-4'
function configOutputMenuContent(outputTypeId: string, ctx: unknown): React.ReactNode {
const c = ctx as OutputMenuContext
const configType = getConfigType(outputTypeId as 'plantuml' | 'markdown' | 'wireframe')
const descriptor = configType?.outputMenuDescriptor
if (!descriptor?.items?.length) return null
const disabled = !c.state.isSvgOutput
const handlers = createImageExportHandlers(c)
return (
<>
<MenubarSeparator />
<MenubarSub>
<MenubarSubTrigger className="text-xs" disabled={disabled}>
{descriptor.submenuLabel ?? 'Export'}
</MenubarSubTrigger>
<MenubarSubContent className="min-w-[10rem]" aria-label={descriptor.submenuLabel ?? 'Export'}>
{descriptor.items.map((item) => {
const handler =
item.action === 'downloadSvg'
? handlers.downloadSvg
: item.action === 'downloadPng'
? handlers.downloadPng
: item.action === 'copySvg'
? handlers.copySvg
: handlers.copyPng
return (
<MenubarItem
key={item.id}
className="text-xs"
onClick={handler}
disabled={disabled}
>
{item.label}
</MenubarItem>
)
})}
</MenubarSubContent>
</MenubarSub>
</>
)
}
export function getConfigNodeDescriptor(): NodeTypeDescriptor {
return createNodeTypeBuilder(
'config',
ConfigNode,
{ width: 320, height: 320 },
{ configType: 'plantuml', content: '@startuml\n\n@enduml\n', title: '' }
)
.idPrefix('cfg_')
.withInputOutput(true, true)
.classification('psyche')
.allowedSourceTypes(['config', 'variable', 'function', 'data'])
.allowedTargetTypes(['config', 'render', 'agent'])
.help(NODE_HELP.config)
.menu('Config', <ScrollText className={ICON_CLASS} />)
.getDefaultData((newId) => ({
configType: 'plantuml',
content: '@startuml\n\n@enduml\n',
title: newId ?? '',
}))
.getResetData((nodeId) => ({
configType: 'plantuml',
content: '@startuml\n\n@enduml\n',
title: nodeId ?? '',
}))
.connectionLabel('adding input')
.withFullscreen()
.sourceRenderingLogic({
defaultUpdateMode: 'auto',
getResolvedContent: getResolvedContentForConfig,
})
.outputMenuContent(configOutputMenuContent)
.build()
}