Files
ttstd-infinite-canvas/web/src/lib/canvas/node-registry/node-definition.ts

78 lines
3.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import type { ReactNode } from "react";
import type { CanvasResourceKind } from "@/lib/canvas/canvas-resource-references";
import type { CanvasGenerationMode, CanvasNodeData, CanvasNodeMetadata, CanvasNodeTypeId } from "@/types/canvas";
import type { PluginCanvasNodeContribution } from "@/lib/plugins/plugin-types";
/** 作为上游输入被容量校验计数时归入的类别 */
export type CanvasNodeInputKind = "image" | "video" | "audio" | "text" | "table_data";
/**
* 节点定义——注册表的基本单元。
*
* 一种画布节点类型的静态知识(叫什么、长什么样、能拉多小、是否锁比例)集中在这里,
* 避免同一份知识散落到创建菜单、搜索弹窗、拉伸逻辑等多处后各自漂移。
*/
export type CanvasNodeDefinition = {
type: CanvasNodeTypeId;
/** UI 短标签——创建菜单等处显示,如「文本」 */
label: string;
/** 列表/搜索标签,缺省派生为 `${label}节点` */
listLabel?: string;
/** 不带 className——由渲染处用 [&_svg]:size-* 统一控制尺寸 */
icon: ReactNode;
/** 新建节点的默认标题(与 label 分开:菜单叫「文本」,新建出来的节点名是「Note」) */
defaultTitle: string;
defaultSize: { width: number; height: number };
defaultMetadata?: CanvasNodeMetadata;
/** 手动拉伸的最小尺寸 */
minSize: { width: number; height: number };
/** 拉伸时是否锁定宽高比,缺省不锁 */
keepAspectRatio?: (node: CanvasNodeData) => boolean;
/** 是否出现在添加节点菜单(技能、生成配置由其他入口创建) */
showInCreateMenu: boolean;
/**
* 作为 @ 引用素材时归入的类型;不设或返回 null 表示该节点不是可引用素材。
* 判定依赖内容——空节点不构成素材。
*
* 注意:角色卡(workflowKind === "character")是**跨类型覆盖**,不在这里表达,
* 由 canvas-resource-references 在查注册表之前先行判定。
*/
resourceKind?: (node: CanvasNodeData) => CanvasResourceKind | null;
/** 作为生成节点时的生成模式;不设表示该类型不产生生成行为 */
generationMode?: (node: CanvasNodeData) => CanvasGenerationMode | null;
/** 是否显示右侧输出连接点;缺省为 true,消费型终点节点可关闭。 */
showOutputConnection?: boolean;
/** 若设置,作为目标时只接受这些上游节点类型。 */
acceptsInputKind?: CanvasNodeInputKind | CanvasNodeInputKind[];
/** 限制直接输入数量;转换节点等一进一出节点通常为 1。 */
maxInputCount?: number;
/**
* 作为上游输入被参考素材容量校验计数时的类别;
* 不设表示不参与计数(生成配置、背板)。与 resourceKind 不同,计数不看内容。
*/
inputKind?: CanvasNodeInputKind;
plugin?: {
pluginId: string;
renderer: PluginCanvasNodeContribution["renderer"];
schema: Record<string, unknown>;
};
};
export function canvasNodeDefinitionFromPlugin(pluginId: string, contribution: PluginCanvasNodeContribution): CanvasNodeDefinition {
return {
type: contribution.id,
label: contribution.label,
icon: null,
defaultTitle: contribution.defaultTitle,
defaultSize: contribution.defaultSize,
defaultMetadata: { pluginId, pluginNodeId: contribution.id, pluginData: {}, content: "" },
minSize: { width: Math.min(contribution.defaultSize.width, 220), height: Math.min(contribution.defaultSize.height, 160) },
showInCreateMenu: true,
showOutputConnection: contribution.showOutputConnection,
acceptsInputKind: contribution.acceptsInputKind,
maxInputCount: contribution.maxInputCount,
plugin: { pluginId, renderer: contribution.renderer, schema: contribution.schema },
};
}