feat(svelte): make edges selectable
This commit is contained in:
@@ -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,6 +23,7 @@
|
|||||||
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;
|
||||||
@@ -32,7 +33,7 @@
|
|||||||
|
|
||||||
// @ 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,
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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',
|
||||||
|
|||||||
Reference in New Issue
Block a user