feat: add zoom controls and reset functionality to workflow editor toolbar
This commit is contained in:
@@ -3,6 +3,9 @@
|
|||||||
import type { ReactNode } from "react"
|
import type { ReactNode } from "react"
|
||||||
import {
|
import {
|
||||||
CheckCircle2Icon,
|
CheckCircle2Icon,
|
||||||
|
Maximize2Icon,
|
||||||
|
MinusIcon,
|
||||||
|
PlusIcon,
|
||||||
RotateCcwIcon,
|
RotateCcwIcon,
|
||||||
SaveIcon,
|
SaveIcon,
|
||||||
SendIcon,
|
SendIcon,
|
||||||
@@ -11,6 +14,7 @@ import {
|
|||||||
} from "lucide-react"
|
} from "lucide-react"
|
||||||
|
|
||||||
import { Button } from "@/components/ui/button"
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
import type { WorkflowDraftValidation } from "./workflow-utils"
|
import type { WorkflowDraftValidation } from "./workflow-utils"
|
||||||
@@ -26,6 +30,11 @@ export function WorkflowEditorToolbar({
|
|||||||
redoDisabled = false,
|
redoDisabled = false,
|
||||||
onAutoLayout,
|
onAutoLayout,
|
||||||
autoLayoutDisabled = false,
|
autoLayoutDisabled = false,
|
||||||
|
zoomPercent,
|
||||||
|
onZoomIn,
|
||||||
|
onZoomOut,
|
||||||
|
onResetZoom,
|
||||||
|
onFitView,
|
||||||
onRestoreDefault,
|
onRestoreDefault,
|
||||||
restoreDefaultDisabled = false,
|
restoreDefaultDisabled = false,
|
||||||
onValidate,
|
onValidate,
|
||||||
@@ -45,6 +54,11 @@ export function WorkflowEditorToolbar({
|
|||||||
redoDisabled?: boolean
|
redoDisabled?: boolean
|
||||||
onAutoLayout?: () => void
|
onAutoLayout?: () => void
|
||||||
autoLayoutDisabled?: boolean
|
autoLayoutDisabled?: boolean
|
||||||
|
zoomPercent?: string
|
||||||
|
onZoomIn?: () => void
|
||||||
|
onZoomOut?: () => void
|
||||||
|
onResetZoom?: () => void
|
||||||
|
onFitView?: () => void
|
||||||
onRestoreDefault?: () => void
|
onRestoreDefault?: () => void
|
||||||
restoreDefaultDisabled?: boolean
|
restoreDefaultDisabled?: boolean
|
||||||
onValidate?: () => void
|
onValidate?: () => void
|
||||||
@@ -72,6 +86,35 @@ export function WorkflowEditorToolbar({
|
|||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-1">
|
<div className="flex items-center gap-1">
|
||||||
{toolbarExtra}
|
{toolbarExtra}
|
||||||
|
<div className="flex h-7 items-center rounded-lg border bg-muted/30 p-0.5">
|
||||||
|
<WorkflowToolbarIconButton label="缩小" onClick={onZoomOut}>
|
||||||
|
<MinusIcon className="size-3.5" />
|
||||||
|
</WorkflowToolbarIconButton>
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger
|
||||||
|
render={
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
className="h-6 w-12 px-1 text-xs tabular-nums"
|
||||||
|
aria-label="重置为 100%"
|
||||||
|
disabled={!onResetZoom}
|
||||||
|
onClick={onResetZoom}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{zoomPercent ?? "100%"}
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent>重置为 100%</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
<WorkflowToolbarIconButton label="放大" onClick={onZoomIn}>
|
||||||
|
<PlusIcon className="size-3.5" />
|
||||||
|
</WorkflowToolbarIconButton>
|
||||||
|
<WorkflowToolbarIconButton label="适配画布" onClick={onFitView}>
|
||||||
|
<Maximize2Icon className="size-3.5" />
|
||||||
|
</WorkflowToolbarIconButton>
|
||||||
|
</div>
|
||||||
<Button type="button" variant="ghost" size="sm" className="h-7 px-2 text-xs" disabled={undoDisabled} onClick={onUndo}>
|
<Button type="button" variant="ghost" size="sm" className="h-7 px-2 text-xs" disabled={undoDisabled} onClick={onUndo}>
|
||||||
<Undo2Icon className="size-3.5" />
|
<Undo2Icon className="size-3.5" />
|
||||||
撤销
|
撤销
|
||||||
@@ -102,3 +145,34 @@ export function WorkflowEditorToolbar({
|
|||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function WorkflowToolbarIconButton({
|
||||||
|
label,
|
||||||
|
onClick,
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
label: string
|
||||||
|
onClick?: () => void
|
||||||
|
children: ReactNode
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger
|
||||||
|
render={
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
variant="ghost"
|
||||||
|
size="icon-xs"
|
||||||
|
className="size-6"
|
||||||
|
aria-label={label}
|
||||||
|
disabled={!onClick}
|
||||||
|
onClick={onClick}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent>{label}</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|||||||
@@ -191,6 +191,7 @@ function WorkflowEditorInner({
|
|||||||
const workflowDocument = useService(WorkflowDocument)
|
const workflowDocument = useService(WorkflowDocument)
|
||||||
const selectService = useService(WorkflowSelectService)
|
const selectService = useService(WorkflowSelectService)
|
||||||
const [autoLayouting, setAutoLayouting] = useState(false)
|
const [autoLayouting, setAutoLayouting] = useState(false)
|
||||||
|
const zoomPercent = `${Math.round(playgroundTools.zoom * 100)}%`
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const disposable = selectService.onSelectionChanged(() => {
|
const disposable = selectService.onSelectionChanged(() => {
|
||||||
@@ -248,6 +249,12 @@ function WorkflowEditorInner({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const resetZoom = () => {
|
||||||
|
context.playground.config.updateConfig({
|
||||||
|
zoom: 1,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const closeConfigPanel = () => {
|
const closeConfigPanel = () => {
|
||||||
selectService.clear()
|
selectService.clear()
|
||||||
onSelectNode("")
|
onSelectNode("")
|
||||||
@@ -273,6 +280,11 @@ function WorkflowEditorInner({
|
|||||||
redoDisabled={redoDisabled}
|
redoDisabled={redoDisabled}
|
||||||
onAutoLayout={() => void autoLayout()}
|
onAutoLayout={() => void autoLayout()}
|
||||||
autoLayoutDisabled={autoLayouting || definition.nodes.length < 2}
|
autoLayoutDisabled={autoLayouting || definition.nodes.length < 2}
|
||||||
|
zoomPercent={zoomPercent}
|
||||||
|
onZoomIn={() => playgroundTools.zoomin(true)}
|
||||||
|
onZoomOut={() => playgroundTools.zoomout(true)}
|
||||||
|
onResetZoom={resetZoom}
|
||||||
|
onFitView={() => playgroundTools.fitView(true)}
|
||||||
onRestoreDefault={onRestoreDefault}
|
onRestoreDefault={onRestoreDefault}
|
||||||
restoreDefaultDisabled={restoreDefaultDisabled}
|
restoreDefaultDisabled={restoreDefaultDisabled}
|
||||||
onValidate={onValidate}
|
onValidate={onValidate}
|
||||||
|
|||||||
Reference in New Issue
Block a user