78 lines
3.8 KiB
TypeScript
78 lines
3.8 KiB
TypeScript
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 },
|
||
};
|
||
}
|