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:
Braks
2021-07-17 19:34:32 +02:00
parent 087eb52f1f
commit 61ab006e94
7 changed files with 57 additions and 60 deletions
+1
View File
@@ -21,6 +21,7 @@ const NodesSelection = ({
onSelectionContextMenu onSelectionContextMenu
}: NodesSelectionProps) => { }: NodesSelectionProps) => {
const store = inject<RevueFlowStore>('store'); const store = inject<RevueFlowStore>('store');
console.log('nodesSelection');
const nodeRef = ref<HTMLElement | undefined>(); const nodeRef = ref<HTMLElement | undefined>();
+25 -32
View File
@@ -2,11 +2,7 @@
* The user selection rectangle gets displayed when a user drags the mouse while pressing shift * The user selection rectangle gets displayed when a user drags the mouse while pressing shift
*/ */
import { RevueFlowStore, XYPosition } from '../../types'; import { RevueFlowStore, XYPosition } from '../../types';
import { computed, defineComponent, inject, PropType } from 'vue'; import { computed, defineComponent, inject } from 'vue';
type UserSelectionProps = {
selectionKeyPressed: boolean;
};
function getMousePosition(event: MouseEvent): XYPosition | void { function getMousePosition(event: MouseEvent): XYPosition | void {
const revueFlowNode = (event.target as Element).closest('.revue-flow'); const revueFlowNode = (event.target as Element).closest('.revue-flow');
@@ -26,38 +22,29 @@ const SelectionRect = defineComponent({
setup() { setup() {
const store = inject<RevueFlowStore>('store'); const store = inject<RevueFlowStore>('store');
if (!store?.userSelectionRect.draw) { return () => {
return null; return store?.userSelectionRect.draw ? (
} <div
class="revue-flow__selection"
return () => ( style={{
<div width: `${store?.userSelectionRect.width}px`,
class="revue-flow__selection" height: `${store?.userSelectionRect.height}px`,
style={{ transform: `translate(${store?.userSelectionRect.x}px, ${store?.userSelectionRect.y}px)`
width: `${store?.userSelectionRect.width}px`, }}
height: `${store?.userSelectionRect.height}px`, />
transform: `translate(${store?.userSelectionRect.x}px, ${store?.userSelectionRect.y}px)` ) : (
}} ''
/> );
); };
} }
}); });
export default defineComponent({ export default defineComponent({
components: { SelectionRect }, components: { SelectionRect },
props: { setup() {
selectionKeyPressed: {
type: Boolean as PropType<UserSelectionProps['selectionKeyPressed']>,
required: true
}
},
setup(props) {
const store = inject<RevueFlowStore>('store')!; 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) { if (!shouldRender.value) {
return null; return null;
@@ -69,11 +56,12 @@ export default defineComponent({
return; return;
} }
console.log('mouseDown');
store?.setUserSelection(mousePos); store?.setUserSelection(mousePos);
}; };
const onMouseMove = (event: MouseEvent): void => { const onMouseMove = (event: MouseEvent): void => {
if (!props.selectionKeyPressed || !store?.selectionActive) { if (!store?.selectionActive) {
return; return;
} }
const mousePos = getMousePosition(event); const mousePos = getMousePosition(event);
@@ -81,11 +69,15 @@ export default defineComponent({
if (!mousePos) { if (!mousePos) {
return; return;
} }
console.log('mousemove');
store?.updateUserSelection(mousePos); store?.updateUserSelection(mousePos);
}; };
const onMouseUp = () => store?.unsetUserSelection(); const onMouseUp = () => {
console.log('mosueUp');
store?.unsetUserSelection();
};
const onMouseLeave = () => { const onMouseLeave = () => {
store?.unsetUserSelection(); store?.unsetUserSelection();
@@ -97,6 +89,7 @@ export default defineComponent({
class="revue-flow__selectionpane" class="revue-flow__selectionpane"
onMousedown={onMouseDown} onMousedown={onMouseDown}
onMousemove={onMouseMove} onMousemove={onMouseMove}
onClick={onMouseUp}
onMouseup={onMouseUp} onMouseup={onMouseUp}
onMouseleave={onMouseLeave} onMouseleave={onMouseLeave}
> >
+13 -13
View File
@@ -27,57 +27,57 @@ const FlowRenderer = defineComponent({
onPaneClick: { onPaneClick: {
type: Function as unknown as PropType<FlowRendererProps['onPaneClick']>, type: Function as unknown as PropType<FlowRendererProps['onPaneClick']>,
required: false, required: false,
default: undefined as any default: undefined
}, },
onPaneContextMenu: { onPaneContextMenu: {
type: Function as unknown as PropType<FlowRendererProps['onPaneContextMenu']>, type: Function as unknown as PropType<FlowRendererProps['onPaneContextMenu']>,
required: false, required: false,
default: undefined as any default: undefined
}, },
onPaneScroll: { onPaneScroll: {
type: Function as unknown as PropType<FlowRendererProps['onPaneScroll']>, type: Function as unknown as PropType<FlowRendererProps['onPaneScroll']>,
required: false, required: false,
default: undefined as any default: undefined
}, },
onElementsRemove: { onElementsRemove: {
type: Function as unknown as PropType<FlowRendererProps['onElementsRemove']>, type: Function as unknown as PropType<FlowRendererProps['onElementsRemove']>,
required: false, required: false,
default: undefined as any default: undefined
}, },
onMove: { onMove: {
type: Function as unknown as PropType<FlowRendererProps['onMove']>, type: Function as unknown as PropType<FlowRendererProps['onMove']>,
required: false, required: false,
default: undefined as any default: undefined
}, },
onMoveStart: { onMoveStart: {
type: Function as unknown as PropType<FlowRendererProps['onMoveStart']>, type: Function as unknown as PropType<FlowRendererProps['onMoveStart']>,
required: false, required: false,
default: undefined as any default: undefined
}, },
onMoveEnd: { onMoveEnd: {
type: Function as unknown as PropType<FlowRendererProps['onMoveEnd']>, type: Function as unknown as PropType<FlowRendererProps['onMoveEnd']>,
required: false, required: false,
default: undefined as any default: undefined
}, },
onSelectionDragStart: { onSelectionDragStart: {
type: Function as unknown as PropType<FlowRendererProps['onSelectionDragStart']>, type: Function as unknown as PropType<FlowRendererProps['onSelectionDragStart']>,
required: false, required: false,
default: undefined as any default: undefined
}, },
onSelectionDrag: { onSelectionDrag: {
type: Function as unknown as PropType<FlowRendererProps['onSelectionDrag']>, type: Function as unknown as PropType<FlowRendererProps['onSelectionDrag']>,
required: false, required: false,
default: undefined as any default: undefined
}, },
onSelectionDragStop: { onSelectionDragStop: {
type: Function as unknown as PropType<FlowRendererProps['onSelectionDragStop']>, type: Function as unknown as PropType<FlowRendererProps['onSelectionDragStop']>,
required: false, required: false,
default: undefined as any default: undefined
}, },
onSelectionContextMenu: { onSelectionContextMenu: {
type: Function as unknown as PropType<FlowRendererProps['onSelectionContextMenu']>, type: Function as unknown as PropType<FlowRendererProps['onSelectionContextMenu']>,
required: false, required: false,
default: undefined as any default: undefined
}, },
deleteKeyCode: { deleteKeyCode: {
type: [Number, String] as PropType<FlowRendererProps['deleteKeyCode']>, type: [Number, String] as PropType<FlowRendererProps['deleteKeyCode']>,
@@ -184,7 +184,7 @@ const FlowRenderer = defineComponent({
onMove={props.onMove} onMove={props.onMove}
onMoveStart={props.onMoveStart} onMoveStart={props.onMoveStart}
onMoveEnd={props.onMoveEnd} onMoveEnd={props.onMoveEnd}
selectionKeyPressed={false} selectionKeyPressed={keyPressed.value}
elementsSelectable={props.elementsSelectable} elementsSelectable={props.elementsSelectable}
zoomOnScroll={props.zoomOnScroll} zoomOnScroll={props.zoomOnScroll}
zoomOnPinch={props.zoomOnPinch} zoomOnPinch={props.zoomOnPinch}
@@ -199,7 +199,7 @@ const FlowRenderer = defineComponent({
zoomActivationKeyCode={props.zoomActivationKeyCode} zoomActivationKeyCode={props.zoomActivationKeyCode}
> >
{slots.default ? slots.default() : ''} {slots.default ? slots.default() : ''}
{keyPressed.value ? <UserSelection selectionKeyPressed={keyPressed.value} /> : ''} {keyPressed.value ? <UserSelection track-by={'selection'} /> : ''}
{store?.nodesSelectionActive && ( {store?.nodesSelectionActive && (
<NodesSelection <NodesSelection
onSelectionDragStart={props.onSelectionDragStart} onSelectionDragStart={props.onSelectionDragStart}
+2 -2
View File
@@ -485,12 +485,12 @@ const RevueFlow = defineComponent({
onDrop: { onDrop: {
type: Function as unknown as PropType<(e: DragEvent) => any>, type: Function as unknown as PropType<(e: DragEvent) => any>,
required: false, required: false,
default: undefined as any default: undefined
}, },
onDragover: { onDragover: {
type: Function as unknown as PropType<(e: DragEvent) => any>, type: Function as unknown as PropType<(e: DragEvent) => any>,
required: false, required: false,
default: undefined as any default: undefined
} }
/* // focus events /* // focus events
+5 -5
View File
@@ -3,7 +3,7 @@ import { select, pointer } from 'd3-selection';
import { clamp } from '../../utils'; import { clamp } from '../../utils';
import { FlowTransform, TranslateExtent, PanOnScrollMode, KeyCode } from '../../types'; 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 store from '../../store';
import useKeyPress from '../../hooks/useKeyPress'; import useKeyPress from '../../hooks/useKeyPress';
import useResizeHandler from '../../hooks/useResizeHandler'; import useResizeHandler from '../../hooks/useResizeHandler';
@@ -193,7 +193,7 @@ const ZoomPane = defineComponent({
} }
}); });
onMounted(() => { watchEffect(() => {
if (pinia.d3Zoom) { if (pinia.d3Zoom) {
if (props.selectionKeyPressed) { if (props.selectionKeyPressed) {
pinia.d3Zoom.on('zoom', null); pinia.d3Zoom.on('zoom', null);
@@ -210,7 +210,7 @@ const ZoomPane = defineComponent({
} }
}); });
onMounted(() => { watchEffect(() => {
if (pinia.d3Zoom) { if (pinia.d3Zoom) {
if (props.onMoveStart) { if (props.onMoveStart) {
pinia.d3Zoom.on('start', (event: any) => { pinia.d3Zoom.on('start', (event: any) => {
@@ -227,7 +227,7 @@ const ZoomPane = defineComponent({
} }
}); });
onMounted(() => { watchEffect(() => {
if (pinia.d3Zoom) { if (pinia.d3Zoom) {
if (props.onMoveEnd) { if (props.onMoveEnd) {
pinia.d3Zoom.on('end', (event: any) => { pinia.d3Zoom.on('end', (event: any) => {
@@ -244,7 +244,7 @@ const ZoomPane = defineComponent({
} }
}); });
onMounted(() => { watchEffect(() => {
if (pinia.d3Zoom) { if (pinia.d3Zoom) {
pinia.d3Zoom.filter((event: any) => { pinia.d3Zoom.filter((event: any) => {
const zoomScroll = props.zoomOnScroll; const zoomScroll = props.zoomOnScroll;
+10 -8
View File
@@ -1,7 +1,7 @@
import useKeyPress from './useKeyPress'; import useKeyPress from './useKeyPress';
import { isNode, getConnectedEdges } from '../utils/graph'; import { isNode, getConnectedEdges } from '../utils/graph';
import { Elements, KeyCode, ElementId, FlowElement, RevueFlowStore } from '../types'; import { Elements, KeyCode, ElementId, FlowElement, RevueFlowStore, Edge } from '../types';
import { inject, onMounted } from 'vue'; import { computed, inject, watch } from 'vue';
interface HookParams { interface HookParams {
deleteKeyCode: KeyCode; deleteKeyCode: KeyCode;
@@ -14,12 +14,14 @@ export default ({ deleteKeyCode, multiSelectionKeyCode, onElementsRemove }: Hook
const deleteKeyPressed = useKeyPress(deleteKeyCode); const deleteKeyPressed = useKeyPress(deleteKeyCode);
const multiSelectionKeyPressed = useKeyPress(multiSelectionKeyCode); const multiSelectionKeyPressed = useKeyPress(multiSelectionKeyCode);
const selectedElements = computed(() => store?.selectedElements || []);
const edges = computed(() => store?.edges);
onMounted(() => { watch(selectedElements, () => {
if (onElementsRemove && deleteKeyPressed.value && store?.selectedElements) { if (onElementsRemove && deleteKeyPressed.value && selectedElements.value.length > 0) {
const selectedNodes = store?.selectedElements.filter(isNode); const selectedNodes = selectedElements.value.filter(isNode);
const connectedEdges = getConnectedEdges(selectedNodes, store?.edges); const connectedEdges = getConnectedEdges(selectedNodes, edges.value as Edge[]);
const elementsToRemove = [...store?.selectedElements, ...connectedEdges].reduce( const elementsToRemove = [...selectedElements.value, ...connectedEdges].reduce(
(res, item) => res.set(item.id, item), (res, item) => res.set(item.id, item),
new Map<ElementId, FlowElement>() new Map<ElementId, FlowElement>()
); );
@@ -30,7 +32,7 @@ export default ({ deleteKeyCode, multiSelectionKeyCode, onElementsRemove }: Hook
} }
}); });
onMounted(() => { watch(multiSelectionKeyPressed, () => {
store?.setMultiSelectionActive(multiSelectionKeyPressed.value); store?.setMultiSelectionActive(multiSelectionKeyPressed.value);
}); });
}; };
+1
View File
@@ -5,6 +5,7 @@
"moduleResolution": "node", "moduleResolution": "node",
"strict": true, "strict": true,
"jsx": "preserve", "jsx": "preserve",
"jsxFactory": "",
"sourceMap": true, "sourceMap": true,
"resolveJsonModule": true, "resolveJsonModule": true,
"esModuleInterop": true, "esModuleInterop": true,