Files
Endoleap/src/components/canvas/unsupported-elements.tsx
T

35 lines
3.0 KiB
TypeScript

/**
* 兼容占位组件:显示可理解的公共几何与说明文字,不解析未知类型的业务payload。
* 原始数据由模型保留;这些组件只提供占位绘制,不执行数据迁移,也不自行决定外层是否允许移动或选择。
*/
"use client";
import { BaseEdge, Handle, Position, getBezierPath, type EdgeProps, type NodeProps } from "@xyflow/react";
import type {ReactFlowProjectionNode as ProjectionNode} from "@/lib/canvas-bindings/react-flow";
import type { CanvasEdgeModel } from "@/lib/canvas-v2";
import styles from "./canvas.module.css";
/** 将投影提供的四边方位转换成ReactFlow Handle要求的枚举。 */
const positions={top:Position.Top,right:Position.Right,bottom:Position.Bottom,left:Position.Left};
/** Render only the known envelope and derived endpoints, never interpret opaque payload fields. */
/** 使用投影已提供的标题、旋转和fallback元数据绘制占位节点,尺寸填满外层节点容器。
* renderer-unavailable明确表示当前缺少显示实现,其它情形提示原内容保留。
* 仍绘制已知连接点供现有连线定位,但禁止从这些Handle发起或接收新连接;不推断未知内容字段。 */
export function UnsupportedNode({data,selected}:NodeProps<ProjectionNode>){
// fallback来自bindings投影;缺失时仍显示通用提示,不尝试从data猜测组件结构。
// 只读取公共投影信封;此组件本身没有 TransformableNode,也不安装任何编辑动作处理器。
const fallback=data.__headlessFallback;
return <div className={`${styles.node} ${selected?styles.selectedNode:""}`} style={{width:"100%",height:"100%",padding:14,transform:`rotate(${data.rotation||0}deg)`}} role="note" aria-label="暂不支持编辑的元素">
<span>{data.title}</span><small style={{display:"block"}}>此元素需要兼容的组件版本才能编辑</small>
<small title={fallback?`${fallback.componentId} · v${fallback.dataVersion}`:undefined}>{fallback?.reason==='renderer-unavailable'?'当前视图暂无此类型的编辑器':'原始内容已保留'}</small>
{fallback?.handles.map(handle=><Handle key={handle.id} id={handle.id} type="source" position={positions[handle.side]} className={styles.centerHandle} isConnectable={false} isConnectableStart={false} isConnectableEnd={false} aria-hidden />)}
</div>;
}
/** 直接使用ReactFlow推导的端点生成贝塞尔路径,附可访问标题;不调用未知类型的编辑/样式逻辑。
* BaseEdge绘制统一颜色的可见线条,数据保留与版本兼容仍归模型层负责。 */
export function UnsupportedEdge(props:EdgeProps<CanvasEdgeModel>){
// 采用端点派生的通用曲线,不重放未知模型的自定义 path/marker;保留数据与视觉完全还原是两件事。
const [path]=getBezierPath(props);
return <g role="img" aria-label="暂不支持编辑的连线"><title>原始连线内容已保留</title><BaseEdge id={props.id} path={path} style={{stroke:'#aa968b',strokeWidth:1.5}} /></g>;
}