feat(network): add align/distribute/group sections to context menu
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,10 @@
|
||||
import { useEffect, useRef } from 'react'
|
||||
import { Copy, CopyPlus, Trash2, ClipboardPaste, BoxSelect, Maximize2, BringToFront, SendToBack } from 'lucide-react'
|
||||
import {
|
||||
Copy, CopyPlus, Trash2, ClipboardPaste, BoxSelect, Maximize2, BringToFront, SendToBack,
|
||||
AlignStartVertical, AlignCenterHorizontal, AlignEndVertical,
|
||||
AlignStartHorizontal, AlignCenterVertical, AlignEndHorizontal,
|
||||
AlignHorizontalSpaceAround, AlignVerticalSpaceAround,
|
||||
} from 'lucide-react'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
interface MenuAction {
|
||||
@@ -15,9 +20,41 @@ interface ContextMenuProps {
|
||||
position: { x: number; y: number }
|
||||
actions: MenuAction[]
|
||||
onClose: () => void
|
||||
onAlignLeft?: () => void
|
||||
onAlignRight?: () => void
|
||||
onAlignCenterH?: () => void
|
||||
onAlignTop?: () => void
|
||||
onAlignBottom?: () => void
|
||||
onAlignCenterV?: () => void
|
||||
onDistributeH?: () => void
|
||||
onDistributeV?: () => void
|
||||
canAlign?: boolean
|
||||
canDistribute?: boolean
|
||||
onGroupSelection?: () => void
|
||||
onUngroupSelection?: () => void
|
||||
canGroup?: boolean
|
||||
canUngroup?: boolean
|
||||
}
|
||||
|
||||
export function ContextMenu({ position, actions, onClose }: ContextMenuProps) {
|
||||
export function ContextMenu({
|
||||
position,
|
||||
actions,
|
||||
onClose,
|
||||
onAlignLeft,
|
||||
onAlignRight,
|
||||
onAlignCenterH,
|
||||
onAlignTop,
|
||||
onAlignBottom,
|
||||
onAlignCenterV,
|
||||
onDistributeH,
|
||||
onDistributeV,
|
||||
canAlign,
|
||||
canDistribute,
|
||||
onGroupSelection,
|
||||
onUngroupSelection,
|
||||
canGroup,
|
||||
canUngroup,
|
||||
}: ContextMenuProps) {
|
||||
const menuRef = useRef<HTMLDivElement>(null)
|
||||
|
||||
const clampedPosition = { ...position }
|
||||
@@ -83,6 +120,59 @@ export function ContextMenu({ position, actions, onClose }: ContextMenuProps) {
|
||||
</button>
|
||||
</div>
|
||||
))}
|
||||
|
||||
{canAlign && (
|
||||
<>
|
||||
<div className="border-t border-default my-1" />
|
||||
<div className="px-3 py-0.5 text-[10px] font-medium text-muted uppercase tracking-wider">Align</div>
|
||||
<button onClick={() => { onAlignLeft?.(); onClose() }} className="flex w-full items-center gap-2 px-3 py-2 text-xs text-primary hover:bg-elevated">
|
||||
<AlignStartVertical size={13} /> <span>Align Left</span>
|
||||
</button>
|
||||
<button onClick={() => { onAlignCenterH?.(); onClose() }} className="flex w-full items-center gap-2 px-3 py-2 text-xs text-primary hover:bg-elevated">
|
||||
<AlignCenterHorizontal size={13} /> <span>Align Center</span>
|
||||
</button>
|
||||
<button onClick={() => { onAlignRight?.(); onClose() }} className="flex w-full items-center gap-2 px-3 py-2 text-xs text-primary hover:bg-elevated">
|
||||
<AlignEndVertical size={13} /> <span>Align Right</span>
|
||||
</button>
|
||||
<button onClick={() => { onAlignTop?.(); onClose() }} className="flex w-full items-center gap-2 px-3 py-2 text-xs text-primary hover:bg-elevated">
|
||||
<AlignStartHorizontal size={13} /> <span>Align Top</span>
|
||||
</button>
|
||||
<button onClick={() => { onAlignCenterV?.(); onClose() }} className="flex w-full items-center gap-2 px-3 py-2 text-xs text-primary hover:bg-elevated">
|
||||
<AlignCenterVertical size={13} /> <span>Align Middle</span>
|
||||
</button>
|
||||
<button onClick={() => { onAlignBottom?.(); onClose() }} className="flex w-full items-center gap-2 px-3 py-2 text-xs text-primary hover:bg-elevated">
|
||||
<AlignEndHorizontal size={13} /> <span>Align Bottom</span>
|
||||
</button>
|
||||
{canDistribute && (
|
||||
<>
|
||||
<div className="border-t border-default my-1" />
|
||||
<div className="px-3 py-0.5 text-[10px] font-medium text-muted uppercase tracking-wider">Distribute</div>
|
||||
<button onClick={() => { onDistributeH?.(); onClose() }} className="flex w-full items-center gap-2 px-3 py-2 text-xs text-primary hover:bg-elevated">
|
||||
<AlignHorizontalSpaceAround size={13} /> <span>Space Horizontally</span>
|
||||
</button>
|
||||
<button onClick={() => { onDistributeV?.(); onClose() }} className="flex w-full items-center gap-2 px-3 py-2 text-xs text-primary hover:bg-elevated">
|
||||
<AlignVerticalSpaceAround size={13} /> <span>Space Vertically</span>
|
||||
</button>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
|
||||
{(canGroup || canUngroup) && (
|
||||
<>
|
||||
<div className="border-t border-default my-1" />
|
||||
{canGroup && (
|
||||
<button onClick={() => { onGroupSelection?.(); onClose() }} className="flex w-full items-center gap-2 px-3 py-2 text-xs text-primary hover:bg-elevated">
|
||||
<BoxSelect size={13} /> <span>Group Selection</span>
|
||||
</button>
|
||||
)}
|
||||
{canUngroup && (
|
||||
<button onClick={() => { onUngroupSelection?.(); onClose() }} className="flex w-full items-center gap-2 px-3 py-2 text-xs text-primary hover:bg-elevated">
|
||||
<BoxSelect size={13} /> <span>Ungroup</span>
|
||||
</button>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -736,6 +736,20 @@ function DiagramEditorInner() {
|
||||
})
|
||||
}
|
||||
onClose={closeContextMenu}
|
||||
onAlignLeft={diagramCommands.alignLeft}
|
||||
onAlignRight={diagramCommands.alignRight}
|
||||
onAlignCenterH={diagramCommands.alignCenterH}
|
||||
onAlignTop={diagramCommands.alignTop}
|
||||
onAlignBottom={diagramCommands.alignBottom}
|
||||
onAlignCenterV={diagramCommands.alignCenterV}
|
||||
onDistributeH={diagramCommands.distributeHorizontally}
|
||||
onDistributeV={diagramCommands.distributeVertically}
|
||||
canAlign={contextMenu.type === 'node' ? diagramCommands.canAlign : false}
|
||||
canDistribute={contextMenu.type === 'node' ? diagramCommands.canDistribute : false}
|
||||
onGroupSelection={() => {}}
|
||||
onUngroupSelection={() => {}}
|
||||
canGroup={false}
|
||||
canUngroup={false}
|
||||
/>
|
||||
)}
|
||||
{pendingDeleteNodeId && (
|
||||
|
||||
Reference in New Issue
Block a user