feat: add node help system and registry for extensible node types

- Implemented a help system for different node types (config, render, variable, function) with detailed usage instructions.
- Created a node registry to manage node types, including registration, retrieval, and validation of connections between nodes.
- Defined central node and edge types for the application to streamline state management.
- Added Nunjucks autocomplete functionality to enhance user experience in template editing.
- Developed a syntax highlighting parser for PlantUML and Nunjucks within the CodeMirror editor.
- Registered built-in node types at application startup, including their default configurations and help entries.
- Introduced a theme context provider to manage light/dark mode preferences across the application.
- Created utility functions for class name management using clsx and tailwind-merge.
- Set up Tailwind CSS for styling with custom themes and responsive design.
- Configured Vite for development with proxy settings for backend API calls and Kroki diagram service.
This commit is contained in:
2026-03-09 20:04:31 +01:00
parent 11fd9cd54d
commit b3c2c6711f
67 changed files with 1286 additions and 2124 deletions

View File

@@ -0,0 +1,93 @@
/**
* Registers built-in node types (config, render, variable, function).
* Import this once at app startup (e.g. in main.tsx) so the registry is populated.
*/
import React from 'react'
import { ScrollText, Sparkles, Variable, Code2 } from 'lucide-react'
import { registerNodeType } from './nodeRegistry'
import { NODE_HELP } from './nodeHelp'
import ConfigNode from '../components/nodes/ConfigNode'
import RenderingNode from '../components/nodes/RenderingNode'
import VariableNode from '../components/nodes/VariableNode'
import FunctionNode from '../components/nodes/FunctionNode'
const ICON_CLASS = 'mr-2 h-4 w-4'
export function registerBuiltinNodes(): void {
registerNodeType({
id: 'config',
component: ConfigNode,
defaultStyle: { width: 320, height: 320 },
defaultData: { configType: 'plantuml', content: '@startuml\n\n@enduml\n', title: '' },
idPrefix: 'cfg_',
hasInput: true,
hasOutput: true,
allowedSourceTypes: ['config', 'variable', 'function'],
allowedTargetTypes: ['config', 'render'],
help: NODE_HELP.config,
menuLabel: 'Config',
menuIcon: <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',
})
registerNodeType({
id: 'render',
component: RenderingNode,
defaultStyle: { width: 384, height: 320 },
defaultData: { viewportWidth: 1200, viewportHeight: 800 },
idPrefix: 'rnd_',
hasInput: true,
hasOutput: false,
allowedSourceTypes: ['config'],
help: NODE_HELP.render,
menuLabel: 'Renderer',
menuIcon: <Sparkles className={ICON_CLASS} />,
connectionLabel: 'rendering',
})
registerNodeType({
id: 'variable',
component: VariableNode,
defaultStyle: { width: 224, height: 180 },
defaultData: { value: '', valueType: 'string' },
idPrefix: 'var_',
hasInput: false,
hasOutput: true,
allowedTargetTypes: ['config', 'function'],
help: NODE_HELP.variable,
menuLabel: 'Variable',
menuIcon: <Variable className={ICON_CLASS} />,
})
registerNodeType({
id: 'function',
component: FunctionNode,
defaultStyle: { width: 288, height: 260 },
defaultData: {
body: `function(num, kwargs) {
return num + (kwargs.bar || 0);
}`,
},
idPrefix: 'fn_',
hasInput: true,
hasOutput: true,
allowedSourceTypes: ['config', 'variable', 'function'],
allowedTargetTypes: ['config', 'function'],
help: NODE_HELP.function,
menuLabel: 'Function',
menuIcon: <Code2 className={ICON_CLASS} />,
getResetData: () => ({ body: '' }),
connectionLabel: 'adding input',
})
}