94 lines
3.2 KiB
TypeScript
94 lines
3.2 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', 'render'])
|
|
.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 ?? '',
|
|
}))
|
|
.connectionLabelByStatus({ default: 'adding input', updating: 'pushing new form', paused: 'pending', error: 'corrupted' })
|
|
.withFullscreen()
|
|
.sourceRenderingLogic({
|
|
defaultUpdateMode: 'auto',
|
|
getResolvedContent: getResolvedContentForConfig,
|
|
})
|
|
.outputMenuContent(configOutputMenuContent)
|
|
.build()
|
|
}
|