fix: node selection rect not properly rendering on key press and mousemove
* issue came from some reactivity problems; a component shouldn't return null, else it'll basically do nothing ever again if it's not completely remounted * some type fixes, removed some any's
This commit is contained in:
@@ -21,6 +21,7 @@ const NodesSelection = ({
|
||||
onSelectionContextMenu
|
||||
}: NodesSelectionProps) => {
|
||||
const store = inject<RevueFlowStore>('store');
|
||||
console.log('nodesSelection');
|
||||
|
||||
const nodeRef = ref<HTMLElement | undefined>();
|
||||
|
||||
|
||||
@@ -2,11 +2,7 @@
|
||||
* The user selection rectangle gets displayed when a user drags the mouse while pressing shift
|
||||
*/
|
||||
import { RevueFlowStore, XYPosition } from '../../types';
|
||||
import { computed, defineComponent, inject, PropType } from 'vue';
|
||||
|
||||
type UserSelectionProps = {
|
||||
selectionKeyPressed: boolean;
|
||||
};
|
||||
import { computed, defineComponent, inject } from 'vue';
|
||||
|
||||
function getMousePosition(event: MouseEvent): XYPosition | void {
|
||||
const revueFlowNode = (event.target as Element).closest('.revue-flow');
|
||||
@@ -26,38 +22,29 @@ const SelectionRect = defineComponent({
|
||||
setup() {
|
||||
const store = inject<RevueFlowStore>('store');
|
||||
|
||||
if (!store?.userSelectionRect.draw) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return () => (
|
||||
<div
|
||||
class="revue-flow__selection"
|
||||
style={{
|
||||
width: `${store?.userSelectionRect.width}px`,
|
||||
height: `${store?.userSelectionRect.height}px`,
|
||||
transform: `translate(${store?.userSelectionRect.x}px, ${store?.userSelectionRect.y}px)`
|
||||
}}
|
||||
/>
|
||||
);
|
||||
return () => {
|
||||
return store?.userSelectionRect.draw ? (
|
||||
<div
|
||||
class="revue-flow__selection"
|
||||
style={{
|
||||
width: `${store?.userSelectionRect.width}px`,
|
||||
height: `${store?.userSelectionRect.height}px`,
|
||||
transform: `translate(${store?.userSelectionRect.x}px, ${store?.userSelectionRect.y}px)`
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
''
|
||||
);
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
export default defineComponent({
|
||||
components: { SelectionRect },
|
||||
props: {
|
||||
selectionKeyPressed: {
|
||||
type: Boolean as PropType<UserSelectionProps['selectionKeyPressed']>,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
setup(props) {
|
||||
setup() {
|
||||
const store = inject<RevueFlowStore>('store')!;
|
||||
const renderUserSelectionPane = computed(() => {
|
||||
return props.selectionKeyPressed || store.selectionActive;
|
||||
});
|
||||
|
||||
const shouldRender = computed(() => renderUserSelectionPane.value || store.elementsSelectable);
|
||||
const shouldRender = computed(() => store.selectionActive || store.elementsSelectable);
|
||||
|
||||
if (!shouldRender.value) {
|
||||
return null;
|
||||
@@ -69,11 +56,12 @@ export default defineComponent({
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('mouseDown');
|
||||
store?.setUserSelection(mousePos);
|
||||
};
|
||||
|
||||
const onMouseMove = (event: MouseEvent): void => {
|
||||
if (!props.selectionKeyPressed || !store?.selectionActive) {
|
||||
if (!store?.selectionActive) {
|
||||
return;
|
||||
}
|
||||
const mousePos = getMousePosition(event);
|
||||
@@ -81,11 +69,15 @@ export default defineComponent({
|
||||
if (!mousePos) {
|
||||
return;
|
||||
}
|
||||
console.log('mousemove');
|
||||
|
||||
store?.updateUserSelection(mousePos);
|
||||
};
|
||||
|
||||
const onMouseUp = () => store?.unsetUserSelection();
|
||||
const onMouseUp = () => {
|
||||
console.log('mosueUp');
|
||||
store?.unsetUserSelection();
|
||||
};
|
||||
|
||||
const onMouseLeave = () => {
|
||||
store?.unsetUserSelection();
|
||||
@@ -97,6 +89,7 @@ export default defineComponent({
|
||||
class="revue-flow__selectionpane"
|
||||
onMousedown={onMouseDown}
|
||||
onMousemove={onMouseMove}
|
||||
onClick={onMouseUp}
|
||||
onMouseup={onMouseUp}
|
||||
onMouseleave={onMouseLeave}
|
||||
>
|
||||
|
||||
@@ -27,57 +27,57 @@ const FlowRenderer = defineComponent({
|
||||
onPaneClick: {
|
||||
type: Function as unknown as PropType<FlowRendererProps['onPaneClick']>,
|
||||
required: false,
|
||||
default: undefined as any
|
||||
default: undefined
|
||||
},
|
||||
onPaneContextMenu: {
|
||||
type: Function as unknown as PropType<FlowRendererProps['onPaneContextMenu']>,
|
||||
required: false,
|
||||
default: undefined as any
|
||||
default: undefined
|
||||
},
|
||||
onPaneScroll: {
|
||||
type: Function as unknown as PropType<FlowRendererProps['onPaneScroll']>,
|
||||
required: false,
|
||||
default: undefined as any
|
||||
default: undefined
|
||||
},
|
||||
onElementsRemove: {
|
||||
type: Function as unknown as PropType<FlowRendererProps['onElementsRemove']>,
|
||||
required: false,
|
||||
default: undefined as any
|
||||
default: undefined
|
||||
},
|
||||
onMove: {
|
||||
type: Function as unknown as PropType<FlowRendererProps['onMove']>,
|
||||
required: false,
|
||||
default: undefined as any
|
||||
default: undefined
|
||||
},
|
||||
onMoveStart: {
|
||||
type: Function as unknown as PropType<FlowRendererProps['onMoveStart']>,
|
||||
required: false,
|
||||
default: undefined as any
|
||||
default: undefined
|
||||
},
|
||||
onMoveEnd: {
|
||||
type: Function as unknown as PropType<FlowRendererProps['onMoveEnd']>,
|
||||
required: false,
|
||||
default: undefined as any
|
||||
default: undefined
|
||||
},
|
||||
onSelectionDragStart: {
|
||||
type: Function as unknown as PropType<FlowRendererProps['onSelectionDragStart']>,
|
||||
required: false,
|
||||
default: undefined as any
|
||||
default: undefined
|
||||
},
|
||||
onSelectionDrag: {
|
||||
type: Function as unknown as PropType<FlowRendererProps['onSelectionDrag']>,
|
||||
required: false,
|
||||
default: undefined as any
|
||||
default: undefined
|
||||
},
|
||||
onSelectionDragStop: {
|
||||
type: Function as unknown as PropType<FlowRendererProps['onSelectionDragStop']>,
|
||||
required: false,
|
||||
default: undefined as any
|
||||
default: undefined
|
||||
},
|
||||
onSelectionContextMenu: {
|
||||
type: Function as unknown as PropType<FlowRendererProps['onSelectionContextMenu']>,
|
||||
required: false,
|
||||
default: undefined as any
|
||||
default: undefined
|
||||
},
|
||||
deleteKeyCode: {
|
||||
type: [Number, String] as PropType<FlowRendererProps['deleteKeyCode']>,
|
||||
@@ -184,7 +184,7 @@ const FlowRenderer = defineComponent({
|
||||
onMove={props.onMove}
|
||||
onMoveStart={props.onMoveStart}
|
||||
onMoveEnd={props.onMoveEnd}
|
||||
selectionKeyPressed={false}
|
||||
selectionKeyPressed={keyPressed.value}
|
||||
elementsSelectable={props.elementsSelectable}
|
||||
zoomOnScroll={props.zoomOnScroll}
|
||||
zoomOnPinch={props.zoomOnPinch}
|
||||
@@ -199,7 +199,7 @@ const FlowRenderer = defineComponent({
|
||||
zoomActivationKeyCode={props.zoomActivationKeyCode}
|
||||
>
|
||||
{slots.default ? slots.default() : ''}
|
||||
{keyPressed.value ? <UserSelection selectionKeyPressed={keyPressed.value} /> : ''}
|
||||
{keyPressed.value ? <UserSelection track-by={'selection'} /> : ''}
|
||||
{store?.nodesSelectionActive && (
|
||||
<NodesSelection
|
||||
onSelectionDragStart={props.onSelectionDragStart}
|
||||
|
||||
@@ -485,12 +485,12 @@ const RevueFlow = defineComponent({
|
||||
onDrop: {
|
||||
type: Function as unknown as PropType<(e: DragEvent) => any>,
|
||||
required: false,
|
||||
default: undefined as any
|
||||
default: undefined
|
||||
},
|
||||
onDragover: {
|
||||
type: Function as unknown as PropType<(e: DragEvent) => any>,
|
||||
required: false,
|
||||
default: undefined as any
|
||||
default: undefined
|
||||
}
|
||||
|
||||
/* // focus events
|
||||
|
||||
@@ -3,7 +3,7 @@ import { select, pointer } from 'd3-selection';
|
||||
|
||||
import { clamp } from '../../utils';
|
||||
import { FlowTransform, TranslateExtent, PanOnScrollMode, KeyCode } from '../../types';
|
||||
import { defineComponent, onMounted, PropType, ref, watch } from 'vue';
|
||||
import { defineComponent, onMounted, PropType, ref, watch, watchEffect } from 'vue';
|
||||
import store from '../../store';
|
||||
import useKeyPress from '../../hooks/useKeyPress';
|
||||
import useResizeHandler from '../../hooks/useResizeHandler';
|
||||
@@ -193,7 +193,7 @@ const ZoomPane = defineComponent({
|
||||
}
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
watchEffect(() => {
|
||||
if (pinia.d3Zoom) {
|
||||
if (props.selectionKeyPressed) {
|
||||
pinia.d3Zoom.on('zoom', null);
|
||||
@@ -210,7 +210,7 @@ const ZoomPane = defineComponent({
|
||||
}
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
watchEffect(() => {
|
||||
if (pinia.d3Zoom) {
|
||||
if (props.onMoveStart) {
|
||||
pinia.d3Zoom.on('start', (event: any) => {
|
||||
@@ -227,7 +227,7 @@ const ZoomPane = defineComponent({
|
||||
}
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
watchEffect(() => {
|
||||
if (pinia.d3Zoom) {
|
||||
if (props.onMoveEnd) {
|
||||
pinia.d3Zoom.on('end', (event: any) => {
|
||||
@@ -244,7 +244,7 @@ const ZoomPane = defineComponent({
|
||||
}
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
watchEffect(() => {
|
||||
if (pinia.d3Zoom) {
|
||||
pinia.d3Zoom.filter((event: any) => {
|
||||
const zoomScroll = props.zoomOnScroll;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import useKeyPress from './useKeyPress';
|
||||
import { isNode, getConnectedEdges } from '../utils/graph';
|
||||
import { Elements, KeyCode, ElementId, FlowElement, RevueFlowStore } from '../types';
|
||||
import { inject, onMounted } from 'vue';
|
||||
import { Elements, KeyCode, ElementId, FlowElement, RevueFlowStore, Edge } from '../types';
|
||||
import { computed, inject, watch } from 'vue';
|
||||
|
||||
interface HookParams {
|
||||
deleteKeyCode: KeyCode;
|
||||
@@ -14,12 +14,14 @@ export default ({ deleteKeyCode, multiSelectionKeyCode, onElementsRemove }: Hook
|
||||
|
||||
const deleteKeyPressed = useKeyPress(deleteKeyCode);
|
||||
const multiSelectionKeyPressed = useKeyPress(multiSelectionKeyCode);
|
||||
const selectedElements = computed(() => store?.selectedElements || []);
|
||||
const edges = computed(() => store?.edges);
|
||||
|
||||
onMounted(() => {
|
||||
if (onElementsRemove && deleteKeyPressed.value && store?.selectedElements) {
|
||||
const selectedNodes = store?.selectedElements.filter(isNode);
|
||||
const connectedEdges = getConnectedEdges(selectedNodes, store?.edges);
|
||||
const elementsToRemove = [...store?.selectedElements, ...connectedEdges].reduce(
|
||||
watch(selectedElements, () => {
|
||||
if (onElementsRemove && deleteKeyPressed.value && selectedElements.value.length > 0) {
|
||||
const selectedNodes = selectedElements.value.filter(isNode);
|
||||
const connectedEdges = getConnectedEdges(selectedNodes, edges.value as Edge[]);
|
||||
const elementsToRemove = [...selectedElements.value, ...connectedEdges].reduce(
|
||||
(res, item) => res.set(item.id, item),
|
||||
new Map<ElementId, FlowElement>()
|
||||
);
|
||||
@@ -30,7 +32,7 @@ export default ({ deleteKeyCode, multiSelectionKeyCode, onElementsRemove }: Hook
|
||||
}
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
watch(multiSelectionKeyPressed, () => {
|
||||
store?.setMultiSelectionActive(multiSelectionKeyPressed.value);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
"moduleResolution": "node",
|
||||
"strict": true,
|
||||
"jsx": "preserve",
|
||||
"jsxFactory": "",
|
||||
"sourceMap": true,
|
||||
"resolveJsonModule": true,
|
||||
"esModuleInterop": true,
|
||||
|
||||
Reference in New Issue
Block a user