feat: enhance connection validation and node creation logic, improve type handling in various components
This commit is contained in:
@@ -217,9 +217,12 @@ export function CanvasPage({ projectId: _projectId }: CanvasPageProps) {
|
||||
)
|
||||
|
||||
const isValidConnection = useCallback(
|
||||
(connection: Connection) => {
|
||||
const sourceNode = nodes.find((n) => n.id === connection.source)
|
||||
const targetNode = nodes.find((n) => n.id === connection.target)
|
||||
(connection: Connection | AppEdge) => {
|
||||
const src = 'source' in connection ? connection.source : undefined
|
||||
const tgt = 'target' in connection ? connection.target : undefined
|
||||
if (typeof src !== 'string' || typeof tgt !== 'string') return false
|
||||
const sourceNode = nodes.find((n) => n.id === src)
|
||||
const targetNode = nodes.find((n) => n.id === tgt)
|
||||
const sourceType = sourceNode?.type
|
||||
const targetType = targetNode?.type
|
||||
if (!sourceType || !targetType) return false
|
||||
@@ -227,13 +230,16 @@ export function CanvasPage({ projectId: _projectId }: CanvasPageProps) {
|
||||
const targetData = targetNode?.data as { configType?: string } | undefined
|
||||
if (targetData?.configType !== 'markdown') return false
|
||||
}
|
||||
return isConnectionAllowed(sourceType, targetType, connection.source, connection.target)
|
||||
return isConnectionAllowed(sourceType, targetType, src, tgt)
|
||||
},
|
||||
[nodes]
|
||||
)
|
||||
|
||||
const onConnectStart = useCallback(
|
||||
(_: React.MouseEvent | React.TouchEvent, params: { nodeId?: string | null; handleId?: string | null; handleType?: string | null }) => {
|
||||
(
|
||||
_: React.MouseEvent<Element> | React.TouchEvent<Element> | MouseEvent | TouchEvent,
|
||||
params: { nodeId?: string | null; handleId?: string | null; handleType?: string | null }
|
||||
) => {
|
||||
if (params.handleType !== 'source' || !params.nodeId) {
|
||||
setConnectionFrom(null)
|
||||
return
|
||||
@@ -371,14 +377,14 @@ export function CanvasPage({ projectId: _projectId }: CanvasPageProps) {
|
||||
const createNode = useCallback(
|
||||
(type: string) => {
|
||||
const position = getMenuPosition()
|
||||
if (position == null) return
|
||||
const nodeType = type as Node['type']
|
||||
const newId = getNextNodeId(nodeType, nodesRef.current.map((n) => n.id))
|
||||
const dataMap = getDefaultDataForType(nodeType, newId)
|
||||
const style = getDefaultStyle(nodeType)
|
||||
if (position == null || typeof type !== 'string') return
|
||||
const existingIds = nodesRef.current.map((n) => n.id).filter((id): id is string => id != null)
|
||||
const newId = getNextNodeId(type, existingIds)
|
||||
const dataMap = getDefaultDataForType(type, newId)
|
||||
const style = getDefaultStyle(type)
|
||||
const newNode: Node = {
|
||||
id: newId,
|
||||
type: nodeType,
|
||||
type: type as Node['type'],
|
||||
position: { x: position.x, y: position.y },
|
||||
data: dataMap,
|
||||
style,
|
||||
@@ -416,14 +422,16 @@ export function CanvasPage({ projectId: _projectId }: CanvasPageProps) {
|
||||
const raw = JSON.parse(text) as { id?: string; type?: string; data?: Record<string, unknown>; position?: { x: number; y: number }; style?: unknown }
|
||||
const validIds = getRegisteredNodeTypeIds()
|
||||
if (!raw || typeof raw.type !== 'string' || !validIds.includes(raw.type)) return
|
||||
const nodeType = raw.type
|
||||
setNodes((nds) => {
|
||||
const newId = getNextNodeId(raw.type as Node['type'], nds.map((n) => n.id))
|
||||
const existingIds = nds.map((n) => n.id).filter((id): id is string => id != null)
|
||||
const newId = getNextNodeId(nodeType, existingIds)
|
||||
const data = raw.data != null && typeof raw.data === 'object' ? { ...raw.data } : {}
|
||||
if (raw.type === 'config' && data && 'title' in data) data.title = `config-${newId}`
|
||||
const style = getDefaultStyle(raw.type)
|
||||
if (nodeType === 'config' && data && 'title' in data) data.title = `config-${newId}`
|
||||
const style = getDefaultStyle(nodeType)
|
||||
const newNode: Node = {
|
||||
id: newId,
|
||||
type: raw.type as Node['type'],
|
||||
type: nodeType as Node['type'],
|
||||
position: { x: position.x, y: position.y },
|
||||
data,
|
||||
style,
|
||||
@@ -560,7 +568,8 @@ export function CanvasPage({ projectId: _projectId }: CanvasPageProps) {
|
||||
nodesConnectable
|
||||
elementsSelectable
|
||||
>
|
||||
<Background variant="dots" gap={20} />
|
||||
{/* BackgroundVariant from @xyflow/system expects enum; 'dots' is valid at runtime */}
|
||||
<Background variant={'dots' as React.ComponentProps<typeof Background>['variant']} gap={20} />
|
||||
<div role="group" aria-label="Canvas controls: zoom and fit view">
|
||||
<Controls />
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user