feat: add node calssification
This commit is contained in:
40
frontend/src/lib/iconMap.tsx
Normal file
40
frontend/src/lib/iconMap.tsx
Normal 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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user