chore: commit workspace updates
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import React, { useCallback, useEffect, useRef, useState } from "react";
|
||||
import type { ReactNode } from "react";
|
||||
import { AlertCircle, BookOpenCheck, CheckCircle2, ChevronRight, Clapperboard, Copy, Download, Image as ImageIcon, Lock, Maximize2, Music2, Pencil, RefreshCw, ScanSearch, Settings2, Star, Trash2, Type, Video, WandSparkles } from "lucide-react";
|
||||
import { AlertCircle, BookOpenCheck, CheckCircle2, ChevronRight, Clapperboard, Copy, Download, GripVertical, Image as ImageIcon, Lock, Maximize2, Music2, Pencil, RefreshCw, ScanSearch, Settings2, Star, Trash2, Type, Video, WandSparkles } from "lucide-react";
|
||||
|
||||
import { useCanvasNodeActions } from "./canvas-node-action-context";
|
||||
|
||||
@@ -11,8 +11,6 @@ import { resourceStorageLabel, resourceStorageLocation, resourceStorageTitle } f
|
||||
import { useThemeStore } from "@/stores/use-theme-store";
|
||||
import { CanvasNodeType, type CanvasNodeData, type CanvasNodeTypeId, type Position } from "@/types/canvas";
|
||||
import type { CanvasResourceReference } from "@/lib/canvas/canvas-resource-references";
|
||||
import { PortraitClearanceIcon } from "@/components/canvas/portrait-clearance/portrait-clearance-icon";
|
||||
import { PORTRAIT_CLEARANCE_NODE_TYPE } from "@/lib/portrait-clearance/contracts";
|
||||
import { ART_CRITIQUE_NODE_TYPE } from "@/lib/art-critique/contracts";
|
||||
import { getNodeDefinition, getNodeMinSize, shouldKeepAspectRatio } from "@/lib/canvas/node-registry";
|
||||
import { CanvasNodeContent, CanvasNodeImageInfo } from "./canvas-node-content";
|
||||
@@ -131,7 +129,7 @@ export const CanvasNode = React.memo(function CanvasNode({
|
||||
const showStatusTrack = Boolean(resourceLabel || data.metadata?.locked || isBatchRoot || (isBatchChild && !readOnly) || (hasMediaContent && !readOnly));
|
||||
const isActive = isConnectionTarget || isSelected || isFocusRelated;
|
||||
const nodeState = isFocusRelated ? "focus" : isConnectionTarget ? "target" : isSelected ? "selected" : isRelated && !isBatchChild ? "related" : "idle";
|
||||
const showOutputConnection = data.type !== PORTRAIT_CLEARANCE_NODE_TYPE && getNodeDefinition(data.type)?.showOutputConnection !== false;
|
||||
const showOutputConnection = getNodeDefinition(data.type)?.showOutputConnection !== false;
|
||||
const assetTags = data.metadata?.assetTags?.filter((tag) => tag.trim()) || [];
|
||||
const scriptMinHeight = data.type === CanvasNodeType.Script ? storyboardMinNodeHeight(data.metadata?.storyboardComposerHeight) : null;
|
||||
const textareaRef = useRef<HTMLTextAreaElement>(null);
|
||||
@@ -301,6 +299,7 @@ export const CanvasNode = React.memo(function CanvasNode({
|
||||
draft={titleDraft}
|
||||
theme={theme}
|
||||
onDraftChange={setTitleDraft}
|
||||
onDragStart={readOnly ? undefined : (event) => onMouseDown(event, data.id)}
|
||||
onEdit={() => setIsEditingTitle(true)}
|
||||
onCommit={commitTitle}
|
||||
onCancel={() => { setTitleDraft(data.title); setIsEditingTitle(false); }}
|
||||
@@ -634,7 +633,7 @@ function formatMediaDimensionLabel(node: CanvasNodeData, hasVisualMediaContent:
|
||||
return `${Math.round(width)}*${Math.round(height)}`;
|
||||
}
|
||||
|
||||
function NodeExternalHeader({ node, scale, dimensionLabel, active, editable, editing, draft, theme, onDraftChange, onEdit, onCommit, onCancel }: {
|
||||
function NodeExternalHeader({ node, scale, dimensionLabel, active, editable, editing, draft, theme, onDragStart, onDraftChange, onEdit, onCommit, onCancel }: {
|
||||
node: CanvasNodeData;
|
||||
scale: number;
|
||||
dimensionLabel: string | null;
|
||||
@@ -644,6 +643,7 @@ function NodeExternalHeader({ node, scale, dimensionLabel, active, editable, edi
|
||||
draft: string;
|
||||
theme: CanvasTheme;
|
||||
onDraftChange: (value: string) => void;
|
||||
onDragStart?: (event: React.MouseEvent) => void;
|
||||
onEdit: () => void;
|
||||
onCommit: () => void;
|
||||
onCancel: () => void;
|
||||
@@ -672,6 +672,23 @@ function NodeExternalHeader({ node, scale, dimensionLabel, active, editable, edi
|
||||
onPointerDown={(event) => event.stopPropagation()}
|
||||
>
|
||||
<div className="flex min-w-0 items-center gap-1" style={{ maxWidth: maxHeaderWidth }}>
|
||||
<button
|
||||
type="button"
|
||||
className="flex size-6 shrink-0 touch-none items-center justify-center rounded cursor-grab active:cursor-grabbing disabled:cursor-not-allowed focus-visible:outline focus-visible:outline-1"
|
||||
aria-label={node.metadata?.locked ? "节点已锁定" : `拖动节点:${node.title}`}
|
||||
title={node.metadata?.locked ? "节点已锁定,请先解锁" : "拖动此处移动节点;点击名称可重命名"}
|
||||
disabled={!onDragStart || Boolean(node.metadata?.locked)}
|
||||
onPointerDown={(event) => {
|
||||
if (event.button !== 0) return;
|
||||
// HTML / SVG 正文在跨源沙箱中;捕获指针,避免经过 iframe 后丢失 move / up。
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
event.currentTarget.setPointerCapture(event.pointerId);
|
||||
onDragStart?.(event);
|
||||
}}
|
||||
>
|
||||
{node.metadata?.locked ? <Lock className="size-3" /> : <GripVertical className="size-3" strokeWidth={1.8} />}
|
||||
</button>
|
||||
<Icon className="size-3 shrink-0" strokeWidth={1.8} />
|
||||
{editing ? (
|
||||
<input
|
||||
@@ -709,9 +726,7 @@ function nodeTypeIcon(type: CanvasNodeTypeId) {
|
||||
if (type === CanvasNodeType.Drawing) return Pencil;
|
||||
if (type === CanvasNodeType.Script) return Clapperboard;
|
||||
if (type === CanvasNodeType.Config) return Settings2;
|
||||
if (type === CanvasNodeType.MediaConversion) return WandSparkles;
|
||||
if (type === CanvasNodeType.Skill) return BookOpenCheck;
|
||||
if (type === PORTRAIT_CLEARANCE_NODE_TYPE) return PortraitClearanceIcon;
|
||||
if (type === ART_CRITIQUE_NODE_TYPE) return ScanSearch;
|
||||
return Type;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user