feat: add node calssification

This commit is contained in:
2026-03-10 21:34:39 +01:00
parent eed880e7ef
commit 87c46c25c6
8 changed files with 79 additions and 19 deletions

View File

@@ -0,0 +1,40 @@
/**
* Map project icon ids to Lucide icons for the sidebar.
* Only Lucide "Animals" category icons are allowed for projects.
*/
import {
Bird,
Bug,
Cat,
Dog,
Egg,
Fish,
Rabbit,
Rat,
Shrimp,
Snail,
Squirrel,
Turtle,
type LucideIcon,
} from 'lucide-react'
import type { ProjectIconId } from '../app/platform/types'
export const PROJECT_ICON_MAP: Record<ProjectIconId, LucideIcon> = {
bird: Bird,
bug: Bug,
cat: Cat,
dog: Dog,
fish: Fish,
rat: Rat,
rabbit: Rabbit,
squirrel: Squirrel,
turtle: Turtle,
snail: Snail,
shrimp: Shrimp,
egg: Egg
}
export function getProjectIcon(iconId: string): LucideIcon {
return PROJECT_ICON_MAP[iconId as ProjectIconId] ?? Cat
}

View File

@@ -7,6 +7,15 @@
import type React from 'react'
import type { Node } from '@xyflow/react'
/** Node classification for UI: Psyche (Form/Config, Variable, Behavior/Function), Pneuma (Rendering), Physis (TBD). */
export type NodeClassification = 'psyche' | 'pneuma' | 'physis'
export const NODE_CLASSIFICATION_LABELS: Record<NodeClassification, string> = {
psyche: 'Psyche',
pneuma: 'Pneuma',
physis: 'Physis',
}
export type NodeHelpEntry = {
title: string
content: React.ReactNode
@@ -20,6 +29,8 @@ export type NodeTypeDescriptor = {
idPrefix: string
hasInput: boolean
hasOutput: boolean
/** Classification for creation menu and node footer: Psyche, Pneuma, Physis. */
classification?: NodeClassification
/** When this type is the connection target, which source types are allowed. Omit = all. */
allowedSourceTypes?: string[]
/** When this type is the connection source, which target types are allowed. Omit = all. */
@@ -48,10 +59,31 @@ export function getNodeType(id: string): NodeTypeDescriptor | undefined {
return registry.get(id)
}
const CLASSIFICATION_ORDER: NodeClassification[] = ['psyche', 'pneuma', 'physis']
export function getRegisteredNodeTypes(): NodeTypeDescriptor[] {
return Array.from(registry.values())
}
/** Node types grouped by classification for the Create Node menu. Order: Psyche, Pneuma, Physis. */
export function getRegisteredNodeTypesGroupedByClassification(): {
classification: NodeClassification
label: string
types: NodeTypeDescriptor[]
}[] {
const byClass = new Map<NodeClassification, NodeTypeDescriptor[]>()
for (const c of CLASSIFICATION_ORDER) byClass.set(c, [])
for (const desc of registry.values()) {
const c = desc.classification ?? 'physis'
byClass.get(c)!.push(desc)
}
return CLASSIFICATION_ORDER.map((classification) => ({
classification,
label: NODE_CLASSIFICATION_LABELS[classification],
types: byClass.get(classification)!,
}))
}
export function getRegisteredNodeTypeIds(): string[] {
return Array.from(registry.keys())
}
@@ -114,3 +146,10 @@ export function getNodeHelp(nodeType: string): NodeHelpEntry {
const desc = getNodeType(nodeType)
return desc?.help ?? { title: nodeType, content: null }
}
/** Classification label for a node type (e.g. "Psyche"). Shown in node footer before help button. */
export function getNodeClassificationLabel(nodeType: string): string | null {
const desc = getNodeType(nodeType)
const c = desc?.classification
return c ? NODE_CLASSIFICATION_LABELS[c] : null
}

View File

@@ -23,6 +23,7 @@ export function registerBuiltinNodes(): void {
idPrefix: 'cfg_',
hasInput: true,
hasOutput: true,
classification: 'psyche',
allowedSourceTypes: ['config', 'variable', 'function'],
allowedTargetTypes: ['config', 'render'],
help: NODE_HELP.config,
@@ -49,6 +50,7 @@ export function registerBuiltinNodes(): void {
idPrefix: 'rnd_',
hasInput: true,
hasOutput: false,
classification: 'pneuma',
allowedSourceTypes: ['config'],
help: NODE_HELP.render,
menuLabel: 'Renderer',
@@ -64,6 +66,7 @@ export function registerBuiltinNodes(): void {
idPrefix: 'var_',
hasInput: false,
hasOutput: true,
classification: 'psyche',
allowedTargetTypes: ['config', 'function'],
help: NODE_HELP.variable,
menuLabel: 'Variable',
@@ -82,6 +85,7 @@ export function registerBuiltinNodes(): void {
idPrefix: 'fn_',
hasInput: true,
hasOutput: true,
classification: 'psyche',
allowedSourceTypes: ['config', 'variable', 'function'],
allowedTargetTypes: ['config', 'function'],
help: NODE_HELP.function,