refactor: use injected store so we can use a distinct instance not a global one

This commit is contained in:
Braks
2021-07-13 16:13:15 +02:00
parent 8f727a4d93
commit 6c9d88b09d
13 changed files with 327 additions and 217 deletions
+50 -59
View File
@@ -1,12 +1,11 @@
import { Node, WrapNodeProps } from '../../types';
import { computed, CSSProperties, defineComponent, onMounted, provide, ref } from 'vue';
import store from '../../store';
import { Node, RevueFlowStore, WrapNodeProps } from '../../types';
import { computed, CSSProperties, defineComponent, inject, onMounted, provide, ref } from 'vue';
export default (NodeComponent: any) => {
return defineComponent({
props: WrapNodeProps,
setup(props) {
const pinia = store();
const store = inject<RevueFlowStore>('store');
provide('NodeIdContext', props.id);
const nodeElement = ref<HTMLDivElement | null>(null);
@@ -70,10 +69,10 @@ export default (NodeComponent: any) => {
const onSelectNodeHandler = (event: MouseEvent) => {
if (!props.isDraggable) {
if (props.isSelectable) {
pinia.unsetNodesSelection();
store?.unsetNodesSelection();
if (!props.selected) {
pinia.addSelectedElements([node.value as Node]);
store?.addSelectedElements([node.value as Node]);
}
}
@@ -81,70 +80,62 @@ export default (NodeComponent: any) => {
}
};
/**
const onDragStart = (event: DraggableEvent) => {
onNodeDragStart?.(event as MouseEvent, node);
const onDragStart = (event: DragEvent) => {
props.onNodeDragStart?.(event as MouseEvent, node.value as Node);
if (selectNodesOnDrag && isSelectable) {
unsetNodesSelection();
if (props.selectNodesOnDrag && props.isSelectable) {
store?.unsetNodesSelection();
if (!selected) {
addSelectedElements(node);
if (!props.selected) {
store?.addSelectedElements([node.value as Node]);
}
} else if (!selectNodesOnDrag && !selected && isSelectable) {
unsetNodesSelection();
addSelectedElements([]);
} else if (!props.selectNodesOnDrag && !props.selected && props.isSelectable) {
store?.unsetNodesSelection();
store?.addSelectedElements([]);
}
};
const onDrag = useCallback(
(event: DraggableEvent, draggableData: DraggableData) => {
if (onNodeDrag) {
node.position.x += draggableData.deltaX;
node.position.y += draggableData.deltaY;
onNodeDrag(event as MouseEvent, node);
const onDrag = (event: DragEvent, draggableData: any) => {
if (props.onNodeDrag) {
node.value.position.x += draggableData.deltaX;
node.value.position.y += draggableData.deltaY;
props.onNodeDrag(event as MouseEvent, node.value as Node);
}
store?.updateNodePosDiff({
id: props.id as string,
diff: {
x: draggableData.deltaX,
y: draggableData.deltaY
},
isDragging: true
});
};
const onDragStop = (event: DragEvent) => {
// onDragStop also gets called when user just clicks on a node.
// Because of that we set dragging to true inside the onDrag handler and handle the click here
if (!props.isDragging) {
if (props.isSelectable && !props.selectNodesOnDrag && !props.selected) {
store?.addSelectedElements([node.value as Node]);
}
updateNodePosDiff({
id,
diff: {
x: draggableData.deltaX,
y: draggableData.deltaY
},
isDragging: true
});
},
[id, node, onNodeDrag]
);
props.onClick?.(event as MouseEvent, node.value as Node);
const onDragStop = useCallback(
(event: DraggableEvent) => {
// onDragStop also gets called when user just clicks on a node.
// Because of that we set dragging to true inside the onDrag handler and handle the click here
if (!isDragging) {
if (isSelectable && !selectNodesOnDrag && !selected) {
addSelectedElements(node);
}
return;
}
onClick?.(event as MouseEvent, node);
store?.updateNodePosDiff({
id: node.value.id as string,
isDragging: false
});
return;
}
updateNodePosDiff({
id: node.id,
isDragging: false
});
onNodeDragStop?.(event as MouseEvent, node);
},
[node, isSelectable, selectNodesOnDrag, onClick, onNodeDragStop, isDragging, selected]
);
*/
props.onNodeDragStop?.(event as MouseEvent, node.value as Node);
};
onMounted(() => {
if (nodeElement.value && !props.isHidden) {
pinia.updateNodeDimensions([{ id: props.id || '', nodeElement: nodeElement.value, forceUpdate: true }]);
store?.updateNodeDimensions([{ id: props.id || '', nodeElement: nodeElement.value, forceUpdate: true }]);
}
});
@@ -161,18 +152,18 @@ export default (NodeComponent: any) => {
return null;
}
const nodeClasses = [
const nodeClasses = computed(() => [
'revue-flow__node',
`revue-flow__node-${props.type}`,
{
selected: props.selected,
selectable: props.isSelectable
}
];
]);
return () => (
<div
class={nodeClasses}
class={nodeClasses.value}
ref={nodeElement}
style={nodeStyle.value}
onMouseenter={onMouseEnterHandler}
+103
View File
@@ -0,0 +1,103 @@
/**
* The nodes selection rectangle gets displayed when a user
* made a selectio with on or several nodes
*/
import VueDraggable, { MoveEvent } from 'vuedraggable';
import { isNode } from '../../utils/graph';
import { Node, RevueFlowStore } from '../../types';
import { computed, inject, ref } from 'vue';
export interface NodesSelectionProps {
onSelectionDragStart?: (event: MouseEvent, nodes: Node[]) => void;
onSelectionDrag?: (event: MouseEvent, nodes: Node[]) => void;
onSelectionDragStop?: (event: MouseEvent, nodes: Node[]) => void;
onSelectionContextMenu?: (event: MouseEvent, nodes: Node[]) => void;
}
const NodesSelection = ({
onSelectionDragStart,
onSelectionDrag,
onSelectionDragStop,
onSelectionContextMenu
}: NodesSelectionProps) => {
const store = inject<RevueFlowStore>('store');
const nodeRef = ref(null);
const grid = computed(() => (store?.snapToGrid ? store?.snapGrid : [1, 1])! as [number, number]);
const selectedNodes = computed(() =>
store?.selectedElements
? store?.selectedElements.filter(isNode).map((selectedNode) => {
const matchingNode = store?.nodes.find((node) => node.id === selectedNode.id);
return {
...matchingNode,
position: matchingNode?.__rf.position
} as Node;
})
: []
);
const style = computed(() => ({
transform: `translate(${store?.transform[0]}px,${store?.transform[1]}px) scale(${store?.transform[2]})`
}));
const innerStyle = computed(() => ({
width: store?.selectedNodesBbox.width,
height: store?.selectedNodesBbox.height,
top: store?.selectedNodesBbox.y,
left: store?.selectedNodesBbox.x
}));
const onStart = (event: MouseEvent) => {
onSelectionDragStart?.(event, selectedNodes.value);
};
const onDrag = (event: MouseEvent, data: MoveEvent<any>) => {
if (onSelectionDrag) {
onSelectionDrag(event, selectedNodes.value);
}
console.log('dragging', data);
};
const onStop = (event: MouseEvent) => {
store?.updateNodePosDiff({
isDragging: false
});
onSelectionDragStop?.(event, selectedNodes.value);
};
const onContextMenu = (event: MouseEvent) => {
const selectedNodes = store?.selectedElements
? store?.selectedElements.filter(isNode).map((selectedNode) => store?.nodes.find((node) => node.id === selectedNode.id))
: [];
onSelectionContextMenu?.(event, selectedNodes as any);
};
if (!store?.selectedElements || store?.selectionActive) {
return null;
}
return (
<div class="revue-flow__nodesselection" style={style.value}>
<VueDraggable
scale={store?.transform[2]}
grid={grid}
onStart={(event: MouseEvent) => onStart(event)}
onDrag={(event: MouseEvent, data: any) => onDrag(event, data)}
onStop={(event: MouseEvent) => onStop(event)}
nodeRef={nodeRef}
enableUserSelectHack={false}
>
<div ref={nodeRef} class="revue-flow__nodesselection-rect" onContextmenu={onContextMenu} style={innerStyle.value} />
</VueDraggable>
</div>
);
};
export default NodesSelection;