feat(svelte): make edges selectable

This commit is contained in:
moklick
2023-05-17 13:04:28 +02:00
parent bb847b7a77
commit dd8292ce57
10 changed files with 42 additions and 11 deletions
@@ -108,7 +108,7 @@ export function calcNextPosition(
] ]
: currentExtent; : currentExtent;
} else { } else {
devWarn('005', errorMessages['005']()); devWarn('005', errorMessages['error005']());
currentExtent = nodeExtent; currentExtent = nodeExtent;
} }
} else if (node.extent && node.parentNode) { } else if (node.extent && node.parentNode) {
@@ -14,7 +14,6 @@
export let markerEnd: $$Props['markerEnd'] = undefined; export let markerEnd: $$Props['markerEnd'] = undefined;
export let style: $$Props['style'] = undefined; export let style: $$Props['style'] = undefined;
export let interactionWidth: $$Props['interactionWidth'] = 20; export let interactionWidth: $$Props['interactionWidth'] = 20;
</script> </script>
<path <path
@@ -23,16 +23,17 @@
export let targetPosition: $$Props['targetPosition'] = Position.Top; export let targetPosition: $$Props['targetPosition'] = Position.Top;
export let animated: $$Props['animated'] = false; export let animated: $$Props['animated'] = false;
export let selected: $$Props['selected'] = false; export let selected: $$Props['selected'] = false;
export let selectable: $$Props['selectable'] = true;
export let label: $$Props['label'] = undefined; export let label: $$Props['label'] = undefined;
export let labelStyle: $$Props['labelStyle'] = undefined; export let labelStyle: $$Props['labelStyle'] = undefined;
export let markerStart: $$Props['markerStart'] = undefined; export let markerStart: $$Props['markerStart'] = undefined;
export let markerEnd: $$Props['markerEnd'] = undefined; export let markerEnd: $$Props['markerEnd'] = undefined;
export let sourceHandleId: $$Props['sourceHandleId'] = undefined; export let sourceHandleId: $$Props['sourceHandleId'] = undefined;
export let targetHandleId: $$Props['targetHandleId'] = undefined; export let targetHandleId: $$Props['targetHandleId'] = undefined;
// @ todo: support edge updates // @ todo: support edge updates
const { edges, edgeTypes, flowId } = useStore(); const { edges, edgeTypes, flowId, addSelectedEdges } = useStore();
const dispatch = createEventDispatcher(); const dispatch = createEventDispatcher();
const edgeComponent: typeof SvelteComponentTyped<EdgeProps> = $edgeTypes[type!] || BezierEdge; const edgeComponent: typeof SvelteComponentTyped<EdgeProps> = $edgeTypes[type!] || BezierEdge;
@@ -41,6 +42,10 @@
$: markerEndUrl = markerEnd ? `url(#${getMarkerId(markerEnd, $flowId)})` : undefined; $: markerEndUrl = markerEnd ? `url(#${getMarkerId(markerEnd, $flowId)})` : undefined;
function onClick() { function onClick() {
if (selectable) {
addSelectedEdges([id]);
}
const edge = $edges.find(e => e.id === id); const edge = $edges.find(e => e.id === id);
dispatch('edge:click', edge); dispatch('edge:click', edge);
} }
@@ -50,6 +55,7 @@
<g <g
class="svelte-flow__edge" class="svelte-flow__edge"
class:animated class:animated
class:selected
data-id={id} data-id={id}
on:click={onClick} on:click={onClick}
> >
@@ -83,13 +89,17 @@
cursor: pointer; cursor: pointer;
} }
.svelte-flow__edge :global(path) { .svelte-flow__edge :global(.svelte-flow__edge-path) {
stroke: #ccc; stroke: #ccc;
stroke-width: 1; stroke-width: 1;
fill: none; fill: none;
} }
.animated :global(path) { .selected :global(.svelte-flow__edge-path) {
stroke: #555;
}
.animated :global(.svelte-flow__edge-path) {
stroke-dasharray: 5; stroke-dasharray: 5;
animation: dashdraw 0.5s linear infinite; animation: dashdraw 0.5s linear infinite;
} }
@@ -15,6 +15,7 @@
export let data: NodeWrapperProps['data'] = {}; export let data: NodeWrapperProps['data'] = {};
export let selected: NodeWrapperProps['selected'] = false; export let selected: NodeWrapperProps['selected'] = false;
export let draggable: NodeWrapperProps['draggable'] = undefined; export let draggable: NodeWrapperProps['draggable'] = undefined;
export let selectable: NodeWrapperProps['selectable'] = undefined;
export let connectable: NodeWrapperProps['connectable'] = true; export let connectable: NodeWrapperProps['connectable'] = true;
export let dragging: boolean = false; export let dragging: boolean = false;
export let resizeObserver: NodeWrapperProps['resizeObserver'] = null; export let resizeObserver: NodeWrapperProps['resizeObserver'] = null;
@@ -36,13 +37,12 @@
const nodeTypeValid = !!$nodeTypes[type!]; const nodeTypeValid = !!$nodeTypes[type!];
if (!nodeTypeValid) { if (!nodeTypeValid) {
console.warn('003', errorMessages['003'](type!)); console.warn('003', errorMessages['error003'](type!));
type = 'default'; type = 'default';
} }
const nodeComponent: typeof SvelteComponentTyped<Partial<NodeProps>> = const nodeComponent: typeof SvelteComponentTyped<Partial<NodeProps>> =
$nodeTypes[type!] || DefaultNode; $nodeTypes[type!] || DefaultNode;
const isSelectable = true;
const selectNodesOnDrag = false; const selectNodesOnDrag = false;
const dispatch = createEventDispatcher(); const dispatch = createEventDispatcher();
@@ -63,7 +63,7 @@
} }
function onSelectNodeHandler(event: MouseEvent) { function onSelectNodeHandler(event: MouseEvent) {
if (isSelectable && (!selectNodesOnDrag || !draggable)) { if (selectable && (!selectNodesOnDrag || !draggable)) {
// this handler gets called within the drag start event when selectNodesOnDrag=true // this handler gets called within the drag start event when selectNodesOnDrag=true
addSelectedNodes([id]); addSelectedNodes([id]);
} }
@@ -11,6 +11,7 @@ export type NodeWrapperProps = Pick<
| 'dragging' | 'dragging'
| 'positionAbsolute' | 'positionAbsolute'
| 'selected' | 'selected'
| 'selectable'
| 'style' | 'style'
| 'type' | 'type'
| 'width' | 'width'
@@ -39,6 +39,7 @@
data={node.data} data={node.data}
selected={node.selected} selected={node.selected}
draggable={node.draggable || node.draggable === undefined} draggable={node.draggable || node.draggable === undefined}
selectable={node.selectable || node.selectable === undefined}
connectable={node.connectable || node.connectable === undefined} connectable={node.connectable || node.connectable === undefined}
positionAbsolute={node.positionAbsolute} positionAbsolute={node.positionAbsolute}
positionOrigin={posOrigin} positionOrigin={posOrigin}
@@ -45,6 +45,7 @@ export function getEdgesLayouted(store: SvelteFlowStoreState) {
res.push({ res.push({
...edge, ...edge,
selectable: edge.selectable || typeof edge.selectable === 'undefined',
type: edgeType, type: edgeType,
sourceX, sourceX,
sourceY, sourceY,
+16
View File
@@ -251,6 +251,21 @@ export function createStore(params: CreateStoreParams): SvelteFlowStore {
); );
} }
function addSelectedEdges(ids: string[]) {
if (get(store.multiselectionKeyPressed)) {
// @todo handle multiselection key
}
store.edges.update((edges) =>
edges.map((edge) => {
return {
...edge,
selected: ids.includes(edge.id)
};
})
);
}
function panBy(delta: XYPosition) { function panBy(delta: XYPosition) {
const { zoom: d3Zoom, selection: d3Selection } = get(store.d3); const { zoom: d3Zoom, selection: d3Selection } = get(store.d3);
const transform = get(store.transform); const transform = get(store.transform);
@@ -335,6 +350,7 @@ export function createStore(params: CreateStoreParams): SvelteFlowStore {
setMaxZoom, setMaxZoom,
resetSelectedElements, resetSelectedElements,
addSelectedNodes, addSelectedNodes,
addSelectedEdges,
panBy, panBy,
updateConnection, updateConnection,
cancelConnection, cancelConnection,
+1
View File
@@ -27,6 +27,7 @@ export type SvelteFlowStoreActions = {
updateNodeDimensions: (updates: NodeDimensionUpdate[]) => void; updateNodeDimensions: (updates: NodeDimensionUpdate[]) => void;
resetSelectedElements: () => void; resetSelectedElements: () => void;
addSelectedNodes: (ids: string[]) => void; addSelectedNodes: (ids: string[]) => void;
addSelectedEdges: (ids: string[]) => void;
panBy: (delta: XYPosition) => void; panBy: (delta: XYPosition) => void;
updateConnection: (connection: Partial<ConnectionData>) => void; updateConnection: (connection: Partial<ConnectionData>) => void;
cancelConnection: () => void; cancelConnection: () => void;
@@ -34,7 +34,8 @@
id: '2', id: '2',
type: 'default', type: 'default',
data: { label: 'Node' }, data: { label: 'Node' },
position: { x: 0, y: 150 } position: { x: 0, y: 150 },
selectable: false,
}, },
{ {
id: 'A', id: 'A',
@@ -83,7 +84,8 @@
id: '1-3', id: '1-3',
type: 'smoothstep', type: 'smoothstep',
source: '1', source: '1',
target: '3' target: '3',
selectable: false
}, },
{ {
id: '2-4', id: '2-4',