fix(svelte): repair selection, add multi selection closes #3557
This commit is contained in:
@@ -3,11 +3,12 @@
|
||||
<script lang="ts">
|
||||
import cc from 'classcat';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import { getMarkerId } from '@xyflow/system';
|
||||
import { errorMessages, getMarkerId } from '@xyflow/system';
|
||||
|
||||
import { useStore } from '$lib/store';
|
||||
import BezierEdge from '$lib/components/edges/BezierEdge.svelte';
|
||||
import type { EdgeLayouted, Edge } from '$lib/types';
|
||||
import { get } from 'svelte/store';
|
||||
|
||||
type $$Props = EdgeLayouted;
|
||||
|
||||
@@ -41,7 +42,16 @@
|
||||
let className: string = '';
|
||||
export { className as class };
|
||||
|
||||
const { edges, edgeTypes, flowId, addSelectedEdges } = useStore();
|
||||
const {
|
||||
edges,
|
||||
edgeTypes,
|
||||
flowId,
|
||||
selectionRect,
|
||||
selectionRectMode,
|
||||
multiselectionKeyPressed,
|
||||
addSelectedEdges,
|
||||
unselectNodesAndEdges
|
||||
} = useStore();
|
||||
const dispatch = createEventDispatcher<{
|
||||
edgeclick: { edge: Edge; event: MouseEvent | TouchEvent };
|
||||
edgecontextmenu: { edge: Edge; event: MouseEvent };
|
||||
@@ -52,15 +62,25 @@
|
||||
$: markerEndUrl = markerEnd ? `url(#${getMarkerId(markerEnd, $flowId)})` : undefined;
|
||||
|
||||
function onClick(event: MouseEvent | TouchEvent) {
|
||||
if (selectable) {
|
||||
addSelectedEdges([id]);
|
||||
}
|
||||
|
||||
const edge = $edges.find((e) => e.id === id);
|
||||
|
||||
if (edge) {
|
||||
dispatch('edgeclick', { event, edge });
|
||||
if (!edge) {
|
||||
console.warn('012', errorMessages['error012'](id));
|
||||
return;
|
||||
}
|
||||
|
||||
if (selectable) {
|
||||
selectionRect.set(null);
|
||||
selectionRectMode.set(null);
|
||||
|
||||
if (!edge.selected) {
|
||||
addSelectedEdges([id]);
|
||||
} else if (edge.selected && get(multiselectionKeyPressed)) {
|
||||
unselectNodesAndEdges({ nodes: [], edges: [edge] });
|
||||
}
|
||||
}
|
||||
|
||||
dispatch('edgeclick', { event, edge });
|
||||
}
|
||||
|
||||
function onContextMenu(event: MouseEvent) {
|
||||
|
||||
@@ -4,14 +4,21 @@
|
||||
import { useStore } from '$lib/store';
|
||||
import type { KeyHandlerProps } from './types';
|
||||
import type { KeyDefinition, KeyDefinitionObject } from '$lib/types';
|
||||
import { isMacOs } from '@xyflow/system';
|
||||
|
||||
type $$Props = KeyHandlerProps;
|
||||
|
||||
export let selectionKey: $$Props['selectionKey'] = 'Shift';
|
||||
export let multiSelectionKey: $$Props['multiSelectionKey'] = isMacOs() ? 'Meta' : 'Control';
|
||||
export let deleteKey: $$Props['deleteKey'] = 'Backspace';
|
||||
export let panActivationKey: $$Props['panActivationKey'] = ' ';
|
||||
|
||||
const { selectionKeyPressed, deleteKeyPressed, panActivationKeyPressed } = useStore();
|
||||
const {
|
||||
selectionKeyPressed,
|
||||
multiselectionKeyPressed,
|
||||
deleteKeyPressed,
|
||||
panActivationKeyPressed
|
||||
} = useStore();
|
||||
|
||||
function isKeyObject(key?: KeyDefinition): key is KeyDefinitionObject {
|
||||
return typeof key === 'object';
|
||||
@@ -20,6 +27,10 @@
|
||||
$: selectionKeyString = typeof selectionKey === 'string' ? selectionKey : selectionKey!.key;
|
||||
$: selectionKeyModifier = isKeyObject(selectionKey) ? selectionKey?.modifier : [];
|
||||
|
||||
$: multiSelectionKeyString =
|
||||
typeof multiSelectionKey === 'string' ? multiSelectionKey : multiSelectionKey!.key;
|
||||
$: multiSelectionKeyModifier = isKeyObject(multiSelectionKey) ? multiSelectionKey?.modifier : [];
|
||||
|
||||
$: deleteKeyString = typeof deleteKey === 'string' ? deleteKey : deleteKey!.key;
|
||||
$: deleteKeyModifier = isKeyObject(deleteKey) ? deleteKey?.modifier : [];
|
||||
|
||||
@@ -49,6 +60,26 @@
|
||||
],
|
||||
type: 'keyup'
|
||||
}}
|
||||
use:shortcut={{
|
||||
trigger: [
|
||||
{
|
||||
key: multiSelectionKeyString,
|
||||
modifier: multiSelectionKeyModifier,
|
||||
callback: () => multiselectionKeyPressed.set(true)
|
||||
}
|
||||
],
|
||||
type: 'keydown'
|
||||
}}
|
||||
use:shortcut={{
|
||||
trigger: [
|
||||
{
|
||||
key: multiSelectionKeyString,
|
||||
modifier: multiSelectionKeyModifier,
|
||||
callback: () => multiselectionKeyPressed.set(false)
|
||||
}
|
||||
],
|
||||
type: 'keyup'
|
||||
}}
|
||||
use:shortcut={{
|
||||
trigger: [
|
||||
{
|
||||
|
||||
@@ -2,6 +2,7 @@ import type { KeyDefinition } from '$lib/types';
|
||||
|
||||
export type KeyHandlerProps = {
|
||||
selectionKey?: KeyDefinition;
|
||||
multiSelectionKey?: KeyDefinition;
|
||||
deleteKey?: KeyDefinition;
|
||||
panActivationKey?: KeyDefinition;
|
||||
};
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
SvelteComponent,
|
||||
type ComponentType
|
||||
} from 'svelte';
|
||||
import cc from 'classcat';
|
||||
import { get, writable } from 'svelte/store';
|
||||
import cc from 'classcat';
|
||||
import { errorMessages, Position, type NodeProps } from '@xyflow/system';
|
||||
|
||||
import drag from '$lib/actions/drag';
|
||||
@@ -44,7 +44,13 @@
|
||||
export { className as class };
|
||||
|
||||
const store = useStore();
|
||||
const { nodeTypes, nodeDragThreshold, addSelectedNodes, updateNodeDimensions } = store;
|
||||
const {
|
||||
nodeTypes,
|
||||
nodeDragThreshold,
|
||||
selectNodesOnDrag,
|
||||
handleNodeSelection,
|
||||
updateNodeDimensions
|
||||
} = store;
|
||||
const nodeType = type || 'default';
|
||||
|
||||
let nodeRef: HTMLDivElement;
|
||||
@@ -56,7 +62,6 @@
|
||||
|
||||
const nodeComponent: ComponentType<SvelteComponent<NodeProps>> =
|
||||
$nodeTypes[nodeType] || DefaultNode;
|
||||
const selectNodesOnDrag = false;
|
||||
const dispatch = createEventDispatcher<{
|
||||
nodeclick: { node: Node; event: MouseEvent | TouchEvent };
|
||||
nodecontextmenu: { node: Node; event: MouseEvent | TouchEvent };
|
||||
@@ -113,12 +118,12 @@
|
||||
});
|
||||
|
||||
function onSelectNodeHandler(event: MouseEvent | TouchEvent) {
|
||||
if (selectable && (!selectNodesOnDrag || !draggable || get(nodeDragThreshold) > 0)) {
|
||||
// this handler gets called within the drag start event when selectNodesOnDrag=true
|
||||
addSelectedNodes([id]);
|
||||
if (selectable && (!get(selectNodesOnDrag) || !draggable || get(nodeDragThreshold) > 0)) {
|
||||
// this handler gets called by XYDrag on drag start when selectNodesOnDrag=true
|
||||
// here we only need to call it when selectNodesOnDrag=false
|
||||
handleNodeSelection(id);
|
||||
}
|
||||
|
||||
// @todo: support multiselection
|
||||
dispatch('nodeclick', { node, event });
|
||||
}
|
||||
|
||||
@@ -135,6 +140,7 @@
|
||||
disabled: false,
|
||||
handleSelector: dragHandle,
|
||||
noDragClass: 'nodrag',
|
||||
onNodeMouseDown: handleNodeSelection,
|
||||
onDrag: (event, _, node, nodes) => {
|
||||
dispatch('nodedrag', { event, node, nodes });
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user