diff --git a/examples/main.ts b/examples/main.ts index 27729860..6dbb7045 100644 --- a/examples/main.ts +++ b/examples/main.ts @@ -3,9 +3,11 @@ import './index.css'; import App from './App'; import { router } from './router'; import { DraggablePlugin } from '@braks/revue-draggable'; +import { createPinia } from 'pinia'; const app = createApp(App); app.config.performance = true; app.use(router); app.use(DraggablePlugin); +app.use(createPinia()); app.mount('#root'); diff --git a/package.json b/package.json index 02488be4..d3ec2fae 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "lint": "yarn lint:js" }, "dependencies": { - "@braks/revue-draggable": "^0.1.2", + "@braks/revue-draggable": "^0.1.3", "@types/d3": "^7.0.0", "d3": "^7.0.0", "d3-selection": "^3.0.0", diff --git a/src/components/UserSelection/index.tsx b/src/components/UserSelection/index.tsx index cd38131c..4cd6f9be 100644 --- a/src/components/UserSelection/index.tsx +++ b/src/components/UserSelection/index.tsx @@ -1,9 +1,8 @@ /** * The user selection rectangle gets displayed when a user drags the mouse while pressing shift */ -import { XYPosition } from '../../types'; -import { defineComponent, PropType } from 'vue'; -import store from '../../store'; +import { RevueFlowStore, XYPosition } from '../../types'; +import { computed, defineComponent, inject, PropType } from 'vue'; type UserSelectionProps = { selectionKeyPressed: boolean; @@ -25,19 +24,20 @@ function getMousePosition(event: MouseEvent): XYPosition | void { const SelectionRect = defineComponent({ setup() { - const pinia = store(); + const store = inject('store'); - if (!pinia.userSelectionRect.draw) { + if (!store?.userSelectionRect.draw) { return null; } + console.log('selectionrect'); return () => (
); @@ -53,10 +53,14 @@ export default defineComponent({ } }, setup(props) { - const pinia = store(); - const renderUserSelectionPane = pinia.selectionActive || props.selectionKeyPressed; + const store = inject('store')!; + const renderUserSelectionPane = computed(() => { + return props.selectionKeyPressed || store.selectionActive; + }); - if (!pinia.elementsSelectable || !renderUserSelectionPane) { + const shouldRender = computed(() => renderUserSelectionPane.value || store.elementsSelectable); + + if (!shouldRender.value) { return null; } @@ -66,11 +70,11 @@ export default defineComponent({ return; } - pinia.setUserSelection(mousePos); + store?.setUserSelection(mousePos); }; const onMouseMove = (event: MouseEvent): void => { - if (!props.selectionKeyPressed || !pinia.selectionActive) { + if (!props.selectionKeyPressed || !store?.selectionActive) { return; } const mousePos = getMousePosition(event); @@ -79,14 +83,14 @@ export default defineComponent({ return; } - pinia.updateUserSelection(mousePos); + store?.updateUserSelection(mousePos); }; - const onMouseUp = () => pinia.unsetUserSelection(); + const onMouseUp = () => store?.unsetUserSelection(); const onMouseLeave = () => { - pinia.unsetUserSelection(); - pinia.unsetNodesSelection(); + store?.unsetUserSelection(); + store?.unsetNodesSelection(); }; return () => ( diff --git a/src/container/FlowRenderer/index.tsx b/src/container/FlowRenderer/index.tsx index 1ce91bb3..84aa2923 100644 --- a/src/container/FlowRenderer/index.tsx +++ b/src/container/FlowRenderer/index.tsx @@ -157,8 +157,7 @@ const FlowRenderer = defineComponent({ }, setup(props, { slots }) { const store = inject('store'); - - const selectionKeyPressed = useKeyPress(props.selectionKeyCode); + const keyPressed = useKeyPress(props.selectionKeyCode); useGlobalKeyHandler({ onElementsRemove: props.onElementsRemove, @@ -200,7 +199,7 @@ const FlowRenderer = defineComponent({ zoomActivationKeyCode={props.zoomActivationKeyCode} > {slots.default ? slots.default() : ''} - + {keyPressed.value ? : ''} {store?.nodesSelectionActive && ( { - const pinia = store(); + const store = inject('store'); const deleteKeyPressed = useKeyPress(deleteKeyCode); const multiSelectionKeyPressed = useKeyPress(multiSelectionKeyCode); onMounted(() => { - const { edges, selectedElements } = pinia; - - if (onElementsRemove && deleteKeyPressed && selectedElements) { - const selectedNodes = selectedElements.filter(isNode); - const connectedEdges = getConnectedEdges(selectedNodes, edges); - const elementsToRemove = [...selectedElements, ...connectedEdges].reduce( + if (onElementsRemove && deleteKeyPressed.value && store?.selectedElements) { + const selectedNodes = store?.selectedElements.filter(isNode); + const connectedEdges = getConnectedEdges(selectedNodes, store?.edges); + const elementsToRemove = [...store?.selectedElements, ...connectedEdges].reduce( (res, item) => res.set(item.id, item), new Map() ); onElementsRemove(Array.from(elementsToRemove.values())); - pinia.unsetNodesSelection(); - pinia.resetSelectedElements(); + store?.unsetNodesSelection(); + store?.resetSelectedElements(); } }); onMounted(() => { - pinia.setMultiSelectionActive(multiSelectionKeyPressed); + store?.setMultiSelectionActive(multiSelectionKeyPressed.value); }); }; diff --git a/src/hooks/useKeyPress.ts b/src/hooks/useKeyPress.ts index 571784b1..3fca3dcf 100644 --- a/src/hooks/useKeyPress.ts +++ b/src/hooks/useKeyPress.ts @@ -1,38 +1,45 @@ import { isInputDOMNode } from '../utils'; import { KeyCode } from '../types'; -import { onMounted, ref } from 'vue'; +import { onBeforeUnmount, onMounted, ref, Ref } from 'vue'; -export default (keyCode?: KeyCode): boolean => { +export default (keyCode?: KeyCode): Ref => { const keyPressed = ref(false); - onMounted(() => { + const downHandler = (event: KeyboardEvent) => { + if (!isInputDOMNode(event) && (event.key === keyCode || event.keyCode === keyCode)) { + event.preventDefault(); + keyPressed.value = true; + } + }; + + const upHandler = (event: KeyboardEvent) => { + if (!isInputDOMNode(event) && (event.key === keyCode || event.keyCode === keyCode)) { + keyPressed.value = false; + } + }; + + const resetHandler = () => (keyPressed.value = false); + + const bindEvents = () => { if (typeof keyCode !== 'undefined') { - const downHandler = (event: KeyboardEvent) => { - if (!isInputDOMNode(event) && (event.key === keyCode || event.keyCode === keyCode)) { - event.preventDefault(); - keyPressed.value = true; - } - }; - - const upHandler = (event: KeyboardEvent) => { - if (!isInputDOMNode(event) && (event.key === keyCode || event.keyCode === keyCode)) { - keyPressed.value = false; - } - }; - - const resetHandler = () => (keyPressed.value = false); - window.addEventListener('keydown', downHandler); window.addEventListener('keyup', upHandler); window.addEventListener('blur', resetHandler); - - return () => { - window.removeEventListener('keydown', downHandler); - window.removeEventListener('keyup', upHandler); - window.removeEventListener('blur', resetHandler); - }; } + }; + + const unbindEvents = () => { + window.removeEventListener('keydown', downHandler); + window.removeEventListener('keyup', upHandler); + window.removeEventListener('blur', resetHandler); + }; + + onMounted(() => { + bindEvents(); + }); + onBeforeUnmount(() => { + unbindEvents(); }); - return keyPressed.value; + return keyPressed; }; diff --git a/src/store/configure-store.ts b/src/store/configure-store.ts index 4f2f004b..6bdef40a 100644 --- a/src/store/configure-store.ts +++ b/src/store/configure-store.ts @@ -191,13 +191,13 @@ export default function configureStore( const nextSelectedElements = [...selectedNodes, ...selectedEdges]; const selectedElementsChanged = !isEqual(nextSelectedElements, this.selectedElements); const selectedElementsUpdate = selectedElementsChanged - ? { - selectedElements: nextSelectedElements.length > 0 ? nextSelectedElements : null - } - : {}; + ? nextSelectedElements.length > 0 + ? nextSelectedElements + : [] + : []; this.userSelectionRect = nextUserSelectRect; - this.selectedElements = selectedElementsUpdate.selectedElements as any; + this.selectedElements = selectedElementsUpdate; }, unsetUserSelection() { const selectedNodes = this.selectedElements?.filter((node) => isNode(node) && node.__rf) as Node[]; @@ -206,9 +206,11 @@ export default function configureStore( this.userSelectionRect.draw = false; if (!selectedNodes || selectedNodes.length === 0) { + console.log('Foo'); this.selectedElements = null; this.nodesSelectionActive = false; } else { + console.log('bar'); this.selectedNodesBbox = getRectOfNodes(selectedNodes); this.nodesSelectionActive = true; } diff --git a/src/utils/index.ts b/src/utils/index.ts index 2b90d0cd..12544a4c 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,9 +1,9 @@ import { Dimensions, XYPosition, NodeExtent } from '../types'; +import { DraggableEvent } from '@braks/revue-draggable'; -export const isInputDOMNode = (e: MouseEvent | /* DraggableEvent | */ KeyboardEvent): boolean => { +export const isInputDOMNode = (e: MouseEvent | DraggableEvent | KeyboardEvent): boolean => { const target = e.target as HTMLElement; - - return ['INPUT', 'SELECT', 'TEXTAREA', 'BUTTON'].includes(target.nodeName) || target.hasAttribute('contenteditable'); + return ['INPUT', 'SELECT', 'TEXTAREA', 'BUTTON'].includes(target.nodeName) || target.hasAttribute('contentEditable'); }; export const getDimensions = (node: HTMLDivElement): Dimensions => ({ @@ -13,7 +13,7 @@ export const getDimensions = (node: HTMLDivElement): Dimensions => ({ export const clamp = (val: number, min = 0, max = 1): number => Math.min(Math.max(val, min), max); -export const clampPosition = (position: XYPosition, extent: NodeExtent) => ({ +export const clampPosition = (position: XYPosition, extent: NodeExtent): XYPosition => ({ x: clamp(position.x, extent[0][0], extent[1][0]), y: clamp(position.y, extent[0][1], extent[1][1]) }); diff --git a/yarn.lock b/yarn.lock index 083dc963..9107211f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -262,10 +262,10 @@ "@babel/helper-validator-identifier" "^7.14.5" to-fast-properties "^2.0.0" -"@braks/revue-draggable@^0.1.2": - version "0.1.2" - resolved "https://registry.yarnpkg.com/@braks/revue-draggable/-/revue-draggable-0.1.2.tgz#7eb53c5ecd3cdae905b873a4c70418d2f4f649b7" - integrity sha512-sgtLSL4NClw2ajU/8IS7/qhUPRSO1uHd3iKCRmsCF1Lrygkj9qJ7m5DjiN7R8ifrCGvnYA9BDqNnYMcPKr/d8g== +"@braks/revue-draggable@^0.1.3": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@braks/revue-draggable/-/revue-draggable-0.1.3.tgz#837a46bde7c87f8f6642ed4fb85697653ee6d068" + integrity sha512-9Ad35cUzkuaC7wTXSpJIYAH2kmgIh/VtL062MXTiFZ9OIZxAUMUfCnIgDTWY0sZNoxmO8CPD3XUP/YfbxoMESQ== dependencies: vue-demi latest