feat: add auto layout functionality to workflow editor and toolbar

This commit is contained in:
mlogclub
2026-06-28 09:37:34 +08:00
parent 6a402cff78
commit a185a0a352
2 changed files with 32 additions and 0 deletions
@@ -6,6 +6,7 @@ import {
RotateCcwIcon, RotateCcwIcon,
SaveIcon, SaveIcon,
SendIcon, SendIcon,
SparklesIcon,
Undo2Icon, Undo2Icon,
} from "lucide-react" } from "lucide-react"
@@ -23,6 +24,8 @@ export function WorkflowEditorToolbar({
undoDisabled = false, undoDisabled = false,
onRedo, onRedo,
redoDisabled = false, redoDisabled = false,
onAutoLayout,
autoLayoutDisabled = false,
onRestoreDefault, onRestoreDefault,
restoreDefaultDisabled = false, restoreDefaultDisabled = false,
onValidate, onValidate,
@@ -40,6 +43,8 @@ export function WorkflowEditorToolbar({
undoDisabled?: boolean undoDisabled?: boolean
onRedo?: () => void onRedo?: () => void
redoDisabled?: boolean redoDisabled?: boolean
onAutoLayout?: () => void
autoLayoutDisabled?: boolean
onRestoreDefault?: () => void onRestoreDefault?: () => void
restoreDefaultDisabled?: boolean restoreDefaultDisabled?: boolean
onValidate?: () => void onValidate?: () => void
@@ -74,6 +79,10 @@ export function WorkflowEditorToolbar({
<Button type="button" variant="ghost" size="sm" className="h-7 px-2 text-xs" disabled={redoDisabled} onClick={onRedo}> <Button type="button" variant="ghost" size="sm" className="h-7 px-2 text-xs" disabled={redoDisabled} onClick={onRedo}>
</Button> </Button>
<Button type="button" variant="ghost" size="sm" className="h-7 px-2 text-xs" disabled={autoLayoutDisabled} onClick={onAutoLayout}>
<SparklesIcon className="size-3.5" />
</Button>
<Button type="button" variant="ghost" size="sm" className="h-7 px-2 text-xs" disabled={restoreDefaultDisabled} onClick={onRestoreDefault}> <Button type="button" variant="ghost" size="sm" className="h-7 px-2 text-xs" disabled={restoreDefaultDisabled} onClick={onRestoreDefault}>
<RotateCcwIcon className="size-3.5" /> <RotateCcwIcon className="size-3.5" />
@@ -10,6 +10,7 @@ import {
type WorkflowJSON, type WorkflowJSON,
type WorkflowNodeJSON, type WorkflowNodeJSON,
useClientContext, useClientContext,
usePlaygroundTools,
useService, useService,
} from "@flowgram.ai/free-layout-editor" } from "@flowgram.ai/free-layout-editor"
@@ -151,8 +152,10 @@ function WorkflowEditorInner({
publishDisabled?: boolean publishDisabled?: boolean
}) { }) {
const context = useClientContext() const context = useClientContext()
const playgroundTools = usePlaygroundTools()
const workflowDocument = useService(WorkflowDocument) const workflowDocument = useService(WorkflowDocument)
const selectService = useService(WorkflowSelectService) const selectService = useService(WorkflowSelectService)
const [autoLayouting, setAutoLayouting] = useState(false)
useEffect(() => { useEffect(() => {
const disposable = selectService.onSelectionChanged(() => { const disposable = selectService.onSelectionChanged(() => {
@@ -192,6 +195,24 @@ function WorkflowEditorInner({
onDefinitionChange(context.document.toJSON() as AIWorkflowDefinition) onDefinitionChange(context.document.toJSON() as AIWorkflowDefinition)
} }
const autoLayout = async () => {
if (autoLayouting || definition.nodes.length < 2) {
return
}
setAutoLayouting(true)
try {
await playgroundTools.autoLayout({
enableAnimation: true,
animationDuration: 240,
disableFitView: true,
})
playgroundTools.fitView(true)
emitCurrentDefinition()
} finally {
setAutoLayouting(false)
}
}
const closeConfigPanel = () => { const closeConfigPanel = () => {
selectService.clear() selectService.clear()
onSelectNode("") onSelectNode("")
@@ -214,6 +235,8 @@ function WorkflowEditorInner({
undoDisabled={undoDisabled} undoDisabled={undoDisabled}
onRedo={onRedo} onRedo={onRedo}
redoDisabled={redoDisabled} redoDisabled={redoDisabled}
onAutoLayout={() => void autoLayout()}
autoLayoutDisabled={autoLayouting || definition.nodes.length < 2}
onRestoreDefault={onRestoreDefault} onRestoreDefault={onRestoreDefault}
restoreDefaultDisabled={restoreDefaultDisabled} restoreDefaultDisabled={restoreDefaultDisabled}
onValidate={onValidate} onValidate={onValidate}