refactor(viewpane): accept KeyFilter instead of KeyCode
# What's changed? * accept type of `KeyFilter` instead of `KeyCode` for zoom/select/delete keypress * don't filter on input dom elements
This commit is contained in:
@@ -1,43 +1,32 @@
|
||||
import type { Ref } from 'vue'
|
||||
import { onKeyDown, onKeyPressed, onKeyUp } from '@vueuse/core'
|
||||
import type { KeyFilter } from '@vueuse/core'
|
||||
import useWindow from './useWindow'
|
||||
import type { KeyCode } from '~/types'
|
||||
import { isInputDOMNode } from '~/utils'
|
||||
|
||||
export default (keyCode: Ref<KeyCode>, onChange?: (keyPressed: boolean) => void): Ref<boolean> => {
|
||||
export default (keyFilter: KeyFilter, onChange?: (keyPressed: boolean) => void): Ref<boolean> => {
|
||||
const window = useWindow()
|
||||
|
||||
let isPressed = $ref(false)
|
||||
|
||||
watchEffect(
|
||||
() => {
|
||||
if (onChange && typeof onChange === 'function') onChange(isPressed)
|
||||
},
|
||||
{ flush: 'post' },
|
||||
)
|
||||
watch($$(isPressed), () => {
|
||||
if (onChange && typeof onChange === 'function') onChange(isPressed)
|
||||
})
|
||||
|
||||
onKeyPressed(
|
||||
(e) => !isInputDOMNode(e) && (e.key === keyCode.value || e.keyCode === keyCode.value),
|
||||
onKeyStroke(
|
||||
keyFilter,
|
||||
(e) => {
|
||||
e.preventDefault()
|
||||
isPressed = true
|
||||
},
|
||||
{ eventName: 'keydown' },
|
||||
)
|
||||
|
||||
onKeyDown(
|
||||
(e) => !isInputDOMNode(e) && (e.key === keyCode.value || e.keyCode === keyCode.value),
|
||||
(e) => {
|
||||
e.preventDefault()
|
||||
isPressed = true
|
||||
},
|
||||
)
|
||||
|
||||
onKeyUp(
|
||||
(e) => !isInputDOMNode(e) && (e.key === keyCode.value || e.keyCode === keyCode.value),
|
||||
onKeyStroke(
|
||||
keyFilter,
|
||||
(e) => {
|
||||
e.preventDefault()
|
||||
isPressed = false
|
||||
},
|
||||
{ eventName: 'keyup' },
|
||||
)
|
||||
|
||||
if (typeof window.addEventListener !== 'undefined') {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<script lang="ts" setup>
|
||||
import type { EdgeChange, GraphNode, NodeChange } from '../../types'
|
||||
import type { GraphNode } from '../../types'
|
||||
import { useKeyPress, useVueFlow } from '../../composables'
|
||||
import { getConnectedEdges } from '../../utils'
|
||||
import { NodesSelection, UserSelection } from '../../components'
|
||||
|
||||
const {
|
||||
@@ -41,7 +40,7 @@ const onMouseLeave = (event: MouseEvent) => emits.paneMouseLeave(event)
|
||||
|
||||
const onMouseMove = (event: MouseEvent) => emits.paneMouseMove(event)
|
||||
|
||||
useKeyPress($$(deleteKeyCode), (keyPressed) => {
|
||||
useKeyPress(deleteKeyCode, (keyPressed) => {
|
||||
const nodesToRemove = getNodes.reduce<GraphNode[]>((res, node) => {
|
||||
if (!node.selected && node.parentNode && res.find((n) => n.id === node.parentNode)) {
|
||||
res.push(node)
|
||||
@@ -71,13 +70,13 @@ useKeyPress($$(deleteKeyCode), (keyPressed) => {
|
||||
}
|
||||
})
|
||||
|
||||
useKeyPress($$(multiSelectionKeyCode), (keyPressed) => {
|
||||
useKeyPress(multiSelectionKeyCode, (keyPressed) => {
|
||||
setState({
|
||||
multiSelectionActive: keyPressed,
|
||||
})
|
||||
})
|
||||
|
||||
const selectionKeyPressed = useKeyPress($$(selectionKeyCode), (keyPressed) => {
|
||||
const selectionKeyPressed = useKeyPress(selectionKeyCode, (keyPressed) => {
|
||||
if (userSelectionActive && keyPressed) return
|
||||
setState({
|
||||
userSelectionActive: keyPressed && elementsSelectable,
|
||||
|
||||
@@ -97,7 +97,7 @@ onMounted(() => {
|
||||
viewportRef: viewportEl.value,
|
||||
})
|
||||
|
||||
const selectionKeyPressed = useKeyPress($$(selectionKeyCode), (keyPress) => {
|
||||
const selectionKeyPressed = useKeyPress(selectionKeyCode, (keyPress) => {
|
||||
if (keyPress && !isZoomingOrPanning) {
|
||||
d3Zoom.on('zoom', null)
|
||||
} else if (!keyPress) {
|
||||
@@ -109,7 +109,7 @@ onMounted(() => {
|
||||
}
|
||||
})
|
||||
|
||||
const zoomKeyPressed = useKeyPress($$(zoomActivationKeyCode))
|
||||
const zoomKeyPressed = useKeyPress(zoomActivationKeyCode)
|
||||
|
||||
d3Zoom.on('start', (event: D3ZoomEvent<HTMLDivElement, any>) => {
|
||||
isZoomingOrPanning = true
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import type { CSSProperties } from 'vue'
|
||||
import type { KeyFilter } from '@vueuse/core'
|
||||
import type { DefaultEdgeOptions, Edge, GraphEdge } from './edge'
|
||||
import type { CoordinateExtent, GraphNode, Node } from './node'
|
||||
import type { ConnectionLineOptions, ConnectionLineType, ConnectionMode, Connector } from './connection'
|
||||
import type { KeyCode, PanOnScrollMode } from './zoom'
|
||||
import type { PanOnScrollMode } from './zoom'
|
||||
import type { EdgeTypesObject, NodeTypesObject } from './components'
|
||||
|
||||
export type ElementData = any
|
||||
@@ -90,10 +91,10 @@ export interface FlowProps {
|
||||
/** @deprecated use {@link ConnectionLineOptions.style} */
|
||||
connectionLineStyle?: CSSProperties | null
|
||||
connectionLineOptions?: ConnectionLineOptions
|
||||
deleteKeyCode?: KeyCode
|
||||
selectionKeyCode?: KeyCode
|
||||
multiSelectionKeyCode?: KeyCode
|
||||
zoomActivationKeyCode?: KeyCode
|
||||
deleteKeyCode?: KeyFilter
|
||||
selectionKeyCode?: KeyFilter
|
||||
multiSelectionKeyCode?: KeyFilter
|
||||
zoomActivationKeyCode?: KeyFilter
|
||||
snapToGrid?: boolean
|
||||
snapGrid?: SnapGrid
|
||||
onlyRenderVisibleElements?: boolean
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import type { CSSProperties, ComputedRef, ToRefs } from 'vue'
|
||||
import type { KeyFilter } from '@vueuse/core'
|
||||
import type { Dimensions, Elements, FlowElements, FlowExportObject, FlowOptions, SnapGrid, XYPosition } from './flow'
|
||||
import type { DefaultEdgeTypes, DefaultNodeTypes, EdgeComponent, NodeComponent } from './components'
|
||||
import type { Connection, ConnectionLineOptions, ConnectionLineType, ConnectionMode, Connector } from './connection'
|
||||
import type { DefaultEdgeOptions, Edge, GraphEdge } from './edge'
|
||||
import type { CoordinateExtent, GraphNode, Node } from './node'
|
||||
import type { D3Selection, D3Zoom, D3ZoomHandler, KeyCode, PanOnScrollMode, Viewport, ViewportFunctions } from './zoom'
|
||||
import type { D3Selection, D3Zoom, D3ZoomHandler, PanOnScrollMode, Viewport, ViewportFunctions } from './zoom'
|
||||
import type { FlowHooks, FlowHooksEmit, FlowHooksOn } from './hooks'
|
||||
import type { EdgeChange, NodeChange, NodeDragItem } from './changes'
|
||||
import type { HandleType, StartHandle } from './handle'
|
||||
@@ -54,10 +55,10 @@ export interface State extends Omit<FlowOptions, 'id' | 'modelValue'> {
|
||||
userSelectionActive: boolean
|
||||
multiSelectionActive: boolean
|
||||
|
||||
deleteKeyCode: KeyCode
|
||||
selectionKeyCode: KeyCode
|
||||
multiSelectionKeyCode: KeyCode
|
||||
zoomActivationKeyCode: KeyCode
|
||||
deleteKeyCode: KeyFilter
|
||||
selectionKeyCode: KeyFilter
|
||||
multiSelectionKeyCode: KeyFilter
|
||||
zoomActivationKeyCode: KeyFilter
|
||||
|
||||
connectionNodeId: string | null
|
||||
connectionHandleId: string | null
|
||||
|
||||
@@ -12,8 +12,6 @@ export interface Viewport {
|
||||
zoom: number
|
||||
}
|
||||
|
||||
export type KeyCode = number | string
|
||||
|
||||
export enum PanOnScrollMode {
|
||||
Free = 'free',
|
||||
Vertical = 'vertical',
|
||||
|
||||
@@ -19,16 +19,6 @@ import type {
|
||||
} from '~/types'
|
||||
import { useWindow } from '~/composables'
|
||||
|
||||
const isHTMLElement = (el: EventTarget): el is HTMLElement => ('nodeName' || 'hasAttribute') in el
|
||||
|
||||
export const isInputDOMNode = (e: KeyboardEvent | MouseEvent): boolean => {
|
||||
const target = e.target
|
||||
if (target && isHTMLElement(target)) {
|
||||
return ['INPUT', 'SELECT', 'TEXTAREA', 'BUTTON'].includes(target.nodeName) || target.hasAttribute('contentEditable')
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
export const getDimensions = (node: HTMLElement): Dimensions => ({
|
||||
width: node.offsetWidth,
|
||||
height: node.offsetHeight,
|
||||
|
||||
Reference in New Issue
Block a user