Svelte Flow: possible to add multiple keys

This commit is contained in:
peterkogo
2024-03-18 14:29:25 +01:00
parent 24a63391fc
commit 35a4356d4f
3 changed files with 74 additions and 109 deletions
@@ -1,5 +1,9 @@
<script lang="ts">
import { shortcut, type ShortcutModifierDefinition } from '@svelte-put/shortcut';
import {
shortcut,
type ShortcutEventDetail,
type ShortcutModifierDefinition
} from '@svelte-put/shortcut';
import { isInputDOMNode, isMacOs } from '@xyflow/system';
import { useStore } from '$lib/store';
@@ -40,140 +44,101 @@
return isKeyObject(key) ? key.key : key;
}
$: selectionKeyDefinition = {
key: getKeyString(selectionKey),
modifier: getModifier(selectionKey)
};
function getShortcutDefinition(keyString: KeyDefinition | KeyDefinition[] | null | undefined) {
return Array.isArray(keyString)
? keyString.map((key) => ({
key: getKeyString(key),
modifier: getModifier(key)
}))
: [
{
key: getKeyString(keyString),
modifier: getModifier(keyString)
}
];
}
$: multiSelectionKeyDefinition = {
key: getKeyString(multiSelectionKey),
modifier: getModifier(multiSelectionKey)
};
function getShortcutTrigger(
keyDefinition: KeyDefinitionObject[],
callback: (detail: ShortcutEventDetail) => void
) {
return keyDefinition.map((definition) => ({
...definition,
enabled: definition.key !== null,
callback
}));
}
$: deleteKeyDefinition = {
key: getKeyString(deleteKey),
modifier: getModifier(deleteKey)
};
$: selectionKeyDefinition = getShortcutDefinition(selectionKey);
$: panActivationKeyDefinition = {
key: getKeyString(panActivationKey),
modifier: getModifier(panActivationKey)
};
$: multiSelectionKeyDefinition = getShortcutDefinition(multiSelectionKey);
$: zoomActivationKeyDefinition = {
key: getKeyString(zoomActivationKey),
modifier: getModifier(zoomActivationKey)
};
$: deleteKeyDefinition = getShortcutDefinition(deleteKey);
$: panActivationKeyDefinition = getShortcutDefinition(panActivationKey);
$: zoomActivationKeyDefinition = getShortcutDefinition(zoomActivationKey);
</script>
<svelte:window
use:shortcut={{
trigger: [
{
...selectionKeyDefinition,
enabled: selectionKeyDefinition.key !== null,
callback: () => selectionKeyPressed.set(true)
}
],
trigger: getShortcutTrigger(selectionKeyDefinition, () => selectionKeyPressed.set(true)),
type: 'keydown'
}}
use:shortcut={{
trigger: [
{
...selectionKeyDefinition,
enabled: selectionKeyDefinition.key !== null,
callback: () => selectionKeyPressed.set(false)
}
],
trigger: getShortcutTrigger(selectionKeyDefinition, () => selectionKeyPressed.set(false)),
type: 'keyup'
}}
use:shortcut={{
trigger: [
{
...multiSelectionKeyDefinition,
enabled: multiSelectionKeyDefinition.key !== null,
callback: () => multiselectionKeyPressed.set(true)
}
],
trigger: getShortcutTrigger(multiSelectionKeyDefinition, () =>
multiselectionKeyPressed.set(true)
),
type: 'keydown'
}}
use:shortcut={{
trigger: [
{
...multiSelectionKeyDefinition,
enabled: multiSelectionKeyDefinition.key !== null,
callback: () => multiselectionKeyPressed.set(false)
}
],
trigger: getShortcutTrigger(multiSelectionKeyDefinition, () =>
multiselectionKeyPressed.set(false)
),
type: 'keyup'
}}
use:shortcut={{
trigger: [
{
...deleteKeyDefinition,
enabled: deleteKeyDefinition.key !== null,
callback: (detail) => {
const isModifierKey =
detail.originalEvent.ctrlKey ||
detail.originalEvent.metaKey ||
detail.originalEvent.shiftKey;
if (!isModifierKey && !isInputDOMNode(detail.originalEvent)) {
deleteKeyPressed.set(true);
}
}
trigger: getShortcutTrigger(deleteKeyDefinition, (detail) => {
const isModifierKey =
detail.originalEvent.ctrlKey ||
detail.originalEvent.metaKey ||
detail.originalEvent.shiftKey;
if (!isModifierKey && !isInputDOMNode(detail.originalEvent)) {
deleteKeyPressed.set(true);
}
],
}),
type: 'keydown'
}}
use:shortcut={{
trigger: [
{
...deleteKeyDefinition,
enabled: deleteKeyDefinition.key !== null,
callback: () => deleteKeyPressed.set(false)
}
],
trigger: getShortcutTrigger(deleteKeyDefinition, () => deleteKeyPressed.set(false)),
type: 'keyup'
}}
use:shortcut={{
trigger: [
{
...panActivationKeyDefinition,
enabled: panActivationKeyDefinition.key !== null,
callback: () => panActivationKeyPressed.set(true)
}
],
trigger: getShortcutTrigger(panActivationKeyDefinition, () =>
panActivationKeyPressed.set(true)
),
type: 'keydown'
}}
use:shortcut={{
trigger: [
{
...panActivationKeyDefinition,
enabled: panActivationKeyDefinition.key !== null,
callback: () => panActivationKeyPressed.set(false)
}
],
trigger: getShortcutTrigger(panActivationKeyDefinition, () =>
panActivationKeyPressed.set(false)
),
type: 'keyup'
}}
use:shortcut={{
trigger: [
{
...zoomActivationKeyDefinition,
enabled: zoomActivationKeyDefinition.key !== null,
callback: () => zoomActivationKeyPressed.set(true)
}
],
trigger: getShortcutTrigger(zoomActivationKeyDefinition, () =>
zoomActivationKeyPressed.set(true)
),
type: 'keydown'
}}
use:shortcut={{
trigger: [
{
...zoomActivationKeyDefinition,
enabled: zoomActivationKeyDefinition.key !== null,
callback: () => zoomActivationKeyPressed.set(false)
}
],
trigger: getShortcutTrigger(zoomActivationKeyDefinition, () =>
zoomActivationKeyPressed.set(false)
),
type: 'keyup'
}}
/>
@@ -1,9 +1,9 @@
import type { KeyDefinition } from '$lib/types';
export type KeyHandlerProps = {
selectionKey?: KeyDefinition | null;
multiSelectionKey?: KeyDefinition | null;
deleteKey?: KeyDefinition | null;
panActivationKey?: KeyDefinition | null;
zoomActivationKey?: KeyDefinition | null;
selectionKey?: KeyDefinition | KeyDefinition[] | null;
multiSelectionKey?: KeyDefinition | KeyDefinition[] | null;
deleteKey?: KeyDefinition | KeyDefinition[] | null;
panActivationKey?: KeyDefinition | KeyDefinition[] | null;
zoomActivationKey?: KeyDefinition | KeyDefinition[] | null;
};
@@ -86,27 +86,27 @@ export type SvelteFlowProps = DOMAttributes<HTMLDivElement> & {
/** Pressing down this key you can select multiple elements with a selection box.
* @default 'Shift'
*/
selectionKey?: KeyDefinition | null;
selectionKey?: KeyDefinition | KeyDefinition[] | null;
/** If a key is set, you can pan the viewport while that key is held down even if panOnScroll is set to false.
*
* By setting this prop to null you can disable this functionality.
* @default 'Space'
*/
panActivationKey?: KeyDefinition | null;
panActivationKey?: KeyDefinition | KeyDefinition[] | null;
/** Pressing down this key deletes all selected nodes & edges.
* @default 'Backspace'
*/
deleteKey?: KeyDefinition | null;
deleteKey?: KeyDefinition | KeyDefinition[] | null;
/** Pressing down this key you can select multiple elements by clicking.
* @default 'Meta' for macOS, "Ctrl" for other systems
*/
multiSelectionKey?: KeyDefinition | null;
multiSelectionKey?: KeyDefinition | KeyDefinition[] | null;
/** If a key is set, you can zoom the viewport while that key is held down even if panOnScroll is set to false.
*
* By setting this prop to null you can disable this functionality.
* @default 'Meta' for macOS, "Ctrl" for other systems
* */
zoomActivationKey?: KeyDefinition | null;
zoomActivationKey?: KeyDefinition | KeyDefinition[] | null;
/** If set, initial viewport will show all nodes & edges */
fitView?: boolean;
/** Options to be used in combination with fitView