* refactor(keys): add zoomActivationKey and allow null #3618
This commit is contained in:
@@ -8,8 +8,8 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"preinstall": "npx only-allow pnpm",
|
"preinstall": "npx only-allow pnpm",
|
||||||
"dev": "turbo run dev --parallel --concurrency 12",
|
"dev": "turbo run dev --parallel --concurrency 12",
|
||||||
"dev:svelte": "turbo run dev --filter=svelte --filter=system",
|
"dev:svelte": "turbo run dev --filter=svelte-examples...",
|
||||||
"dev:react": "turbo run dev --filter=react-examples ",
|
"dev:react": "turbo run dev --filter=react-examples...",
|
||||||
"test:svelte": "pnpm --filter=playwright run test:svelte",
|
"test:svelte": "pnpm --filter=playwright run test:svelte",
|
||||||
"test:svelte:ui": "pnpm --filter=playwright run test:svelte:ui",
|
"test:svelte:ui": "pnpm --filter=playwright run test:svelte:ui",
|
||||||
"test:react": "pnpm --filter=playwright run test:react",
|
"test:react": "pnpm --filter=playwright run test:react",
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { shortcut } from '@svelte-put/shortcut';
|
import { shortcut, type ShortcutModifierDefinition } from '@svelte-put/shortcut';
|
||||||
|
|
||||||
import { useStore } from '$lib/store';
|
import { useStore } from '$lib/store';
|
||||||
import type { KeyHandlerProps } from './types';
|
import type { KeyHandlerProps } from './types';
|
||||||
@@ -12,40 +12,66 @@
|
|||||||
export let multiSelectionKey: $$Props['multiSelectionKey'] = isMacOs() ? 'Meta' : 'Control';
|
export let multiSelectionKey: $$Props['multiSelectionKey'] = isMacOs() ? 'Meta' : 'Control';
|
||||||
export let deleteKey: $$Props['deleteKey'] = 'Backspace';
|
export let deleteKey: $$Props['deleteKey'] = 'Backspace';
|
||||||
export let panActivationKey: $$Props['panActivationKey'] = ' ';
|
export let panActivationKey: $$Props['panActivationKey'] = ' ';
|
||||||
|
export let zoomActivationKey: $$Props['zoomActivationKey'] = isMacOs() ? 'Meta' : 'Control';
|
||||||
|
|
||||||
const {
|
const {
|
||||||
selectionKeyPressed,
|
selectionKeyPressed,
|
||||||
multiselectionKeyPressed,
|
multiselectionKeyPressed,
|
||||||
deleteKeyPressed,
|
deleteKeyPressed,
|
||||||
panActivationKeyPressed
|
panActivationKeyPressed,
|
||||||
|
zoomActivationKeyPressed
|
||||||
} = useStore();
|
} = useStore();
|
||||||
|
|
||||||
function isKeyObject(key?: KeyDefinition): key is KeyDefinitionObject {
|
function isKeyObject(key?: KeyDefinition | null): key is KeyDefinitionObject {
|
||||||
return typeof key === 'object';
|
return typeof key === 'object';
|
||||||
}
|
}
|
||||||
|
|
||||||
$: selectionKeyString = typeof selectionKey === 'string' ? selectionKey : selectionKey!.key;
|
function getModifier(key?: KeyDefinition | null): ShortcutModifierDefinition {
|
||||||
$: selectionKeyModifier = isKeyObject(selectionKey) ? selectionKey?.modifier : [];
|
return isKeyObject(key) ? key.modifier || [] : [];
|
||||||
|
}
|
||||||
|
|
||||||
$: multiSelectionKeyString =
|
function getKeyString(key?: KeyDefinition | null): string {
|
||||||
typeof multiSelectionKey === 'string' ? multiSelectionKey : multiSelectionKey!.key;
|
if (key === null || key === undefined) {
|
||||||
$: multiSelectionKeyModifier = isKeyObject(multiSelectionKey) ? multiSelectionKey?.modifier : [];
|
// this is a workaround to check if a key is set
|
||||||
|
// if not we won't call the callback
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
$: deleteKeyString = typeof deleteKey === 'string' ? deleteKey : deleteKey!.key;
|
return isKeyObject(key) ? key.key : key;
|
||||||
$: deleteKeyModifier = isKeyObject(deleteKey) ? deleteKey?.modifier : [];
|
}
|
||||||
|
|
||||||
$: panActivationKeyString =
|
$: selectionKeyDefinition = {
|
||||||
typeof panActivationKey === 'string' ? panActivationKey : panActivationKey!.key;
|
key: getKeyString(selectionKey),
|
||||||
$: panActivationKeyModifier = isKeyObject(panActivationKey) ? panActivationKey?.modifier : [];
|
modifier: getModifier(selectionKey)
|
||||||
|
};
|
||||||
|
|
||||||
|
$: multiSelectionKeyDefinition = {
|
||||||
|
key: getKeyString(multiSelectionKey),
|
||||||
|
modifier: getModifier(multiSelectionKey)
|
||||||
|
};
|
||||||
|
|
||||||
|
$: deleteKeyDefinition = {
|
||||||
|
key: getKeyString(deleteKey),
|
||||||
|
modifier: getModifier(deleteKey)
|
||||||
|
};
|
||||||
|
|
||||||
|
$: panActivationKeyDefinition = {
|
||||||
|
key: getKeyString(panActivationKey),
|
||||||
|
modifier: getModifier(panActivationKey)
|
||||||
|
};
|
||||||
|
|
||||||
|
$: zoomActivationKeyDefinition = {
|
||||||
|
key: getKeyString(zoomActivationKey),
|
||||||
|
modifier: getModifier(zoomActivationKey)
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:window
|
<svelte:window
|
||||||
use:shortcut={{
|
use:shortcut={{
|
||||||
trigger: [
|
trigger: [
|
||||||
{
|
{
|
||||||
key: selectionKeyString,
|
...selectionKeyDefinition,
|
||||||
modifier: selectionKeyModifier,
|
callback: () => selectionKeyDefinition.key && selectionKeyPressed.set(true)
|
||||||
callback: () => selectionKeyPressed.set(true)
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
type: 'keydown'
|
type: 'keydown'
|
||||||
@@ -53,9 +79,8 @@
|
|||||||
use:shortcut={{
|
use:shortcut={{
|
||||||
trigger: [
|
trigger: [
|
||||||
{
|
{
|
||||||
key: selectionKeyString,
|
...selectionKeyDefinition,
|
||||||
modifier: selectionKeyModifier,
|
callback: () => selectionKeyDefinition.key && selectionKeyPressed.set(false)
|
||||||
callback: () => selectionKeyPressed.set(false)
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
type: 'keyup'
|
type: 'keyup'
|
||||||
@@ -63,9 +88,8 @@
|
|||||||
use:shortcut={{
|
use:shortcut={{
|
||||||
trigger: [
|
trigger: [
|
||||||
{
|
{
|
||||||
key: multiSelectionKeyString,
|
...multiSelectionKeyDefinition,
|
||||||
modifier: multiSelectionKeyModifier,
|
callback: () => multiSelectionKeyDefinition.key && multiselectionKeyPressed.set(true)
|
||||||
callback: () => multiselectionKeyPressed.set(true)
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
type: 'keydown'
|
type: 'keydown'
|
||||||
@@ -73,9 +97,8 @@
|
|||||||
use:shortcut={{
|
use:shortcut={{
|
||||||
trigger: [
|
trigger: [
|
||||||
{
|
{
|
||||||
key: multiSelectionKeyString,
|
...multiSelectionKeyDefinition,
|
||||||
modifier: multiSelectionKeyModifier,
|
callback: () => multiSelectionKeyDefinition.key && multiselectionKeyPressed.set(false)
|
||||||
callback: () => multiselectionKeyPressed.set(false)
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
type: 'keyup'
|
type: 'keyup'
|
||||||
@@ -83,11 +106,8 @@
|
|||||||
use:shortcut={{
|
use:shortcut={{
|
||||||
trigger: [
|
trigger: [
|
||||||
{
|
{
|
||||||
key: deleteKeyString,
|
...deleteKeyDefinition,
|
||||||
modifier: deleteKeyModifier,
|
callback: () => deleteKeyDefinition.key && deleteKeyPressed.set(true)
|
||||||
callback: () => {
|
|
||||||
deleteKeyPressed.set(true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
type: 'keydown'
|
type: 'keydown'
|
||||||
@@ -95,9 +115,8 @@
|
|||||||
use:shortcut={{
|
use:shortcut={{
|
||||||
trigger: [
|
trigger: [
|
||||||
{
|
{
|
||||||
key: deleteKeyString,
|
...deleteKeyDefinition,
|
||||||
modifier: deleteKeyModifier,
|
callback: () => deleteKeyDefinition.key && deleteKeyPressed.set(false)
|
||||||
callback: () => deleteKeyPressed.set(false)
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
type: 'keyup'
|
type: 'keyup'
|
||||||
@@ -105,9 +124,8 @@
|
|||||||
use:shortcut={{
|
use:shortcut={{
|
||||||
trigger: [
|
trigger: [
|
||||||
{
|
{
|
||||||
key: panActivationKeyString,
|
...panActivationKeyDefinition,
|
||||||
modifier: panActivationKeyModifier,
|
callback: () => panActivationKeyDefinition.key && panActivationKeyPressed.set(true)
|
||||||
callback: () => panActivationKeyPressed.set(true)
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
type: 'keydown'
|
type: 'keydown'
|
||||||
@@ -115,9 +133,26 @@
|
|||||||
use:shortcut={{
|
use:shortcut={{
|
||||||
trigger: [
|
trigger: [
|
||||||
{
|
{
|
||||||
key: panActivationKeyString,
|
...panActivationKeyDefinition,
|
||||||
modifier: panActivationKeyModifier,
|
callback: () => panActivationKeyDefinition.key && panActivationKeyPressed.set(false)
|
||||||
callback: () => panActivationKeyPressed.set(false)
|
}
|
||||||
|
],
|
||||||
|
type: 'keyup'
|
||||||
|
}}
|
||||||
|
use:shortcut={{
|
||||||
|
trigger: [
|
||||||
|
{
|
||||||
|
...zoomActivationKeyDefinition,
|
||||||
|
callback: () => zoomActivationKeyDefinition.key && zoomActivationKeyPressed.set(true)
|
||||||
|
}
|
||||||
|
],
|
||||||
|
type: 'keydown'
|
||||||
|
}}
|
||||||
|
use:shortcut={{
|
||||||
|
trigger: [
|
||||||
|
{
|
||||||
|
...zoomActivationKeyDefinition,
|
||||||
|
callback: () => zoomActivationKeyDefinition.key && zoomActivationKeyPressed.set(false)
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
type: 'keyup'
|
type: 'keyup'
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import type { KeyDefinition } from '$lib/types';
|
import type { KeyDefinition } from '$lib/types';
|
||||||
|
|
||||||
export type KeyHandlerProps = {
|
export type KeyHandlerProps = {
|
||||||
selectionKey?: KeyDefinition;
|
selectionKey?: KeyDefinition | null;
|
||||||
multiSelectionKey?: KeyDefinition;
|
multiSelectionKey?: KeyDefinition | null;
|
||||||
deleteKey?: KeyDefinition;
|
deleteKey?: KeyDefinition | null;
|
||||||
panActivationKey?: KeyDefinition;
|
panActivationKey?: KeyDefinition | null;
|
||||||
|
zoomActivationKey?: KeyDefinition | null;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -34,6 +34,8 @@
|
|||||||
export let selectionKey: $$Props['selectionKey'] = undefined;
|
export let selectionKey: $$Props['selectionKey'] = undefined;
|
||||||
export let selectionMode: $$Props['selectionMode'] = undefined;
|
export let selectionMode: $$Props['selectionMode'] = undefined;
|
||||||
export let panActivationKey: $$Props['panActivationKey'] = undefined;
|
export let panActivationKey: $$Props['panActivationKey'] = undefined;
|
||||||
|
export let multiSelectionKey: $$Props['multiSelectionKey'] = undefined;
|
||||||
|
export let zoomActivationKey: $$Props['zoomActivationKey'] = undefined;
|
||||||
export let nodesDraggable: $$Props['nodesDraggable'] = undefined;
|
export let nodesDraggable: $$Props['nodesDraggable'] = undefined;
|
||||||
export let nodesConnectable: $$Props['nodesConnectable'] = undefined;
|
export let nodesConnectable: $$Props['nodesConnectable'] = undefined;
|
||||||
export let nodeDragThreshold: $$Props['nodeDragThreshold'] = undefined;
|
export let nodeDragThreshold: $$Props['nodeDragThreshold'] = undefined;
|
||||||
@@ -166,7 +168,13 @@
|
|||||||
{...$$restProps}
|
{...$$restProps}
|
||||||
role="application"
|
role="application"
|
||||||
>
|
>
|
||||||
<KeyHandler {selectionKey} {deleteKey} {panActivationKey} />
|
<KeyHandler
|
||||||
|
{selectionKey}
|
||||||
|
{deleteKey}
|
||||||
|
{panActivationKey}
|
||||||
|
{multiSelectionKey}
|
||||||
|
{zoomActivationKey}
|
||||||
|
/>
|
||||||
<Zoom
|
<Zoom
|
||||||
{initialViewport}
|
{initialViewport}
|
||||||
{onMoveStart}
|
{onMoveStart}
|
||||||
|
|||||||
@@ -34,9 +34,11 @@ export type SvelteFlowProps = DOMAttributes<HTMLDivElement> & {
|
|||||||
edges: Writable<Edge[]>;
|
edges: Writable<Edge[]>;
|
||||||
nodeTypes?: NodeTypes;
|
nodeTypes?: NodeTypes;
|
||||||
edgeTypes?: EdgeTypes;
|
edgeTypes?: EdgeTypes;
|
||||||
selectionKey?: KeyDefinition;
|
selectionKey?: KeyDefinition | null;
|
||||||
panActivationKey?: KeyDefinition;
|
panActivationKey?: KeyDefinition | null;
|
||||||
deleteKey?: KeyDefinition;
|
deleteKey?: KeyDefinition | null;
|
||||||
|
multiSelectionKey?: KeyDefinition | null;
|
||||||
|
zoomActivationKey?: KeyDefinition | null;
|
||||||
fitView?: boolean;
|
fitView?: boolean;
|
||||||
fitViewOptions?: FitViewOptions;
|
fitViewOptions?: FitViewOptions;
|
||||||
nodeOrigin?: NodeOrigin;
|
nodeOrigin?: NodeOrigin;
|
||||||
|
|||||||
@@ -28,7 +28,8 @@
|
|||||||
dragging,
|
dragging,
|
||||||
translateExtent,
|
translateExtent,
|
||||||
lib,
|
lib,
|
||||||
panActivationKeyPressed
|
panActivationKeyPressed,
|
||||||
|
zoomActivationKeyPressed
|
||||||
} = useStore();
|
} = useStore();
|
||||||
|
|
||||||
$: viewPort = initialViewport || { x: 0, y: 0, zoom: 1 };
|
$: viewPort = initialViewport || { x: 0, y: 0, zoom: 1 };
|
||||||
@@ -55,7 +56,7 @@
|
|||||||
panOnDrag: _panOnDrag,
|
panOnDrag: _panOnDrag,
|
||||||
panOnScrollSpeed: 0.5,
|
panOnScrollSpeed: 0.5,
|
||||||
panOnScrollMode: panOnScrollMode || PanOnScrollMode.Free,
|
panOnScrollMode: panOnScrollMode || PanOnScrollMode.Free,
|
||||||
zoomActivationKeyPressed: false,
|
zoomActivationKeyPressed: $zoomActivationKeyPressed,
|
||||||
preventScrolling: typeof preventScrolling === 'boolean' ? preventScrolling : true,
|
preventScrolling: typeof preventScrolling === 'boolean' ? preventScrolling : true,
|
||||||
noPanClassName: 'nopan',
|
noPanClassName: 'nopan',
|
||||||
noWheelClassName: 'nowheel',
|
noWheelClassName: 'nowheel',
|
||||||
|
|||||||
@@ -105,6 +105,7 @@ export const getInitialStore = ({
|
|||||||
multiselectionKeyPressed: writable<boolean>(false),
|
multiselectionKeyPressed: writable<boolean>(false),
|
||||||
deleteKeyPressed: writable<boolean>(false),
|
deleteKeyPressed: writable<boolean>(false),
|
||||||
panActivationKeyPressed: writable<boolean>(false),
|
panActivationKeyPressed: writable<boolean>(false),
|
||||||
|
zoomActivationKeyPressed: writable<boolean>(false),
|
||||||
selectionRectMode: writable<string | null>(null),
|
selectionRectMode: writable<string | null>(null),
|
||||||
selectionMode: writable<SelectionMode>(SelectionMode.Partial),
|
selectionMode: writable<SelectionMode>(SelectionMode.Partial),
|
||||||
nodeTypes: writable<NodeTypes>(initialNodeTypes),
|
nodeTypes: writable<NodeTypes>(initialNodeTypes),
|
||||||
|
|||||||
8
pnpm-lock.yaml
generated
8
pnpm-lock.yaml
generated
@@ -3523,7 +3523,6 @@ packages:
|
|||||||
version: 8.11.2
|
version: 8.11.2
|
||||||
engines: {node: '>=0.4.0'}
|
engines: {node: '>=0.4.0'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
dev: true
|
|
||||||
|
|
||||||
registry.npmjs.org/aggregate-error@3.1.0:
|
registry.npmjs.org/aggregate-error@3.1.0:
|
||||||
resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz}
|
resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz}
|
||||||
@@ -4395,7 +4394,7 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@jridgewell/sourcemap-codec': registry.npmjs.org/@jridgewell/sourcemap-codec@1.4.15
|
'@jridgewell/sourcemap-codec': registry.npmjs.org/@jridgewell/sourcemap-codec@1.4.15
|
||||||
'@types/estree': registry.npmjs.org/@types/estree@1.0.3
|
'@types/estree': registry.npmjs.org/@types/estree@1.0.3
|
||||||
acorn: registry.npmjs.org/acorn@8.10.0
|
acorn: registry.npmjs.org/acorn@8.11.2
|
||||||
estree-walker: registry.npmjs.org/estree-walker@3.0.3
|
estree-walker: registry.npmjs.org/estree-walker@3.0.3
|
||||||
periscopic: registry.npmjs.org/periscopic@3.1.0
|
periscopic: registry.npmjs.org/periscopic@3.1.0
|
||||||
|
|
||||||
@@ -6029,6 +6028,7 @@ packages:
|
|||||||
glob-parent: registry.npmjs.org/glob-parent@5.1.2
|
glob-parent: registry.npmjs.org/glob-parent@5.1.2
|
||||||
merge2: registry.npmjs.org/merge2@1.4.1
|
merge2: registry.npmjs.org/merge2@1.4.1
|
||||||
micromatch: registry.npmjs.org/micromatch@4.0.5
|
micromatch: registry.npmjs.org/micromatch@4.0.5
|
||||||
|
dev: false
|
||||||
|
|
||||||
registry.npmjs.org/fast-glob@3.3.2:
|
registry.npmjs.org/fast-glob@3.3.2:
|
||||||
resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz}
|
resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz}
|
||||||
@@ -10957,7 +10957,7 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@jridgewell/trace-mapping': registry.npmjs.org/@jridgewell/trace-mapping@0.3.20
|
'@jridgewell/trace-mapping': registry.npmjs.org/@jridgewell/trace-mapping@0.3.20
|
||||||
chokidar: registry.npmjs.org/chokidar@3.5.3
|
chokidar: registry.npmjs.org/chokidar@3.5.3
|
||||||
fast-glob: registry.npmjs.org/fast-glob@3.3.1
|
fast-glob: registry.npmjs.org/fast-glob@3.3.2
|
||||||
import-fresh: registry.npmjs.org/import-fresh@3.3.0
|
import-fresh: registry.npmjs.org/import-fresh@3.3.0
|
||||||
picocolors: registry.npmjs.org/picocolors@1.0.0
|
picocolors: registry.npmjs.org/picocolors@1.0.0
|
||||||
sade: registry.npmjs.org/sade@1.8.1
|
sade: registry.npmjs.org/sade@1.8.1
|
||||||
@@ -11230,7 +11230,7 @@ packages:
|
|||||||
'@ampproject/remapping': registry.npmjs.org/@ampproject/remapping@2.2.1
|
'@ampproject/remapping': registry.npmjs.org/@ampproject/remapping@2.2.1
|
||||||
'@jridgewell/sourcemap-codec': registry.npmjs.org/@jridgewell/sourcemap-codec@1.4.15
|
'@jridgewell/sourcemap-codec': registry.npmjs.org/@jridgewell/sourcemap-codec@1.4.15
|
||||||
'@jridgewell/trace-mapping': registry.npmjs.org/@jridgewell/trace-mapping@0.3.20
|
'@jridgewell/trace-mapping': registry.npmjs.org/@jridgewell/trace-mapping@0.3.20
|
||||||
acorn: registry.npmjs.org/acorn@8.10.0
|
acorn: registry.npmjs.org/acorn@8.11.2
|
||||||
aria-query: registry.npmjs.org/aria-query@5.3.0
|
aria-query: registry.npmjs.org/aria-query@5.3.0
|
||||||
axobject-query: registry.npmjs.org/axobject-query@3.2.1
|
axobject-query: registry.npmjs.org/axobject-query@3.2.1
|
||||||
code-red: registry.npmjs.org/code-red@1.0.4
|
code-red: registry.npmjs.org/code-red@1.0.4
|
||||||
|
|||||||
Reference in New Issue
Block a user