52 lines
1.4 KiB
TypeScript
52 lines
1.4 KiB
TypeScript
import { useCallback } from 'react';
|
||
import { getNodesBounds, useReactFlow, useStore } from '@xyflow/react';
|
||
import { START_NODE_ID } from '../../utils/strategyFlowLayout';
|
||
|
||
type Props = {
|
||
onDelete: () => void;
|
||
};
|
||
|
||
export function MultiSelectionDeleteButton({ onDelete }: Props) {
|
||
const { getNodes, flowToScreenPosition } = useReactFlow();
|
||
|
||
const selectionKey = useStore(useCallback((state) => {
|
||
const selected = state.nodes.filter(n => n.selected && n.id !== START_NODE_ID);
|
||
if (selected.length < 2) return null;
|
||
return selected
|
||
.map(n => `${n.id}:${Math.round(n.position.x)}:${Math.round(n.position.y)}`)
|
||
.join('|');
|
||
}, []));
|
||
|
||
if (!selectionKey) return null;
|
||
|
||
const selectedNodes = getNodes().filter(n => n.selected && n.id !== START_NODE_ID);
|
||
if (selectedNodes.length < 2) return null;
|
||
|
||
const bounds = getNodesBounds(selectedNodes);
|
||
const anchor = flowToScreenPosition({
|
||
x: bounds.x + bounds.width,
|
||
y: bounds.y,
|
||
});
|
||
|
||
return (
|
||
<button
|
||
type="button"
|
||
className="se-selection-delete"
|
||
title="선택 항목 모두 삭제 (Logic Expression에서 제외)"
|
||
style={{
|
||
position: 'absolute',
|
||
left: anchor.x + 6,
|
||
top: anchor.y - 6,
|
||
transform: 'translate(0, -100%)',
|
||
}}
|
||
onMouseDown={(e) => e.stopPropagation()}
|
||
onClick={(e) => {
|
||
e.stopPropagation();
|
||
onDelete();
|
||
}}
|
||
>
|
||
×
|
||
</button>
|
||
);
|
||
}
|