diff --git a/apps/web/src/components/list-item/index.js b/apps/web/src/components/list-item/index.js index 89c112a71..7104f568e 100644 --- a/apps/web/src/components/list-item/index.js +++ b/apps/web/src/components/list-item/index.js @@ -4,19 +4,34 @@ import * as Icon from "react-feather"; import Dropdown, { DropdownTrigger, DropdownContent } from "../dropdown"; import Menu from "../menu"; import { useStore } from "../../stores/note-store"; +import useContextMenu from "../../utils/useContextMenu"; + +const ActionsMenu = props => ( + +); const ListItem = props => { const selectedNote = useStore(store => store.selectedNote); const isSelected = selectedNote === props.id; + const [parentRef, closeContextMenu] = useContextMenu( + `contextMenu${props.index}` + ); return ( { style={{ zIndex: 1, marginRight: -4 }} ref={ref => (props.dropdownRefs[props.index] = ref)} > - + closeContextMenu()}> { - + )} + ); }; diff --git a/apps/web/src/components/menu/index.js b/apps/web/src/components/menu/index.js index ca08afb04..4c468f7cc 100644 --- a/apps/web/src/components/menu/index.js +++ b/apps/web/src/components/menu/index.js @@ -5,13 +5,16 @@ import Dropdown from "../dropdown"; function Menu(props) { return ( diff --git a/apps/web/src/utils/useContextMenu.js b/apps/web/src/utils/useContextMenu.js new file mode 100644 index 000000000..88f701b85 --- /dev/null +++ b/apps/web/src/utils/useContextMenu.js @@ -0,0 +1,103 @@ +import { useEffect, useRef } from "react"; +import Dropdown from "../components/dropdown"; + +var oldOpenedMenu; + +function isMouseInside(e, element) { + if (!e || !element) return false; + return element.contains(e.target); +} + +function contextMenuHandler(event, ref, menuId) { + if ( + isMouseInside(event, ref.current) && + !isMouseInside(event, oldOpenedMenu) + ) { + Dropdown.closeLastOpened(); + dismissMenu(oldOpenedMenu); + + event.preventDefault(); + const menu = document.getElementById(menuId); + menu.style.display = "block"; + positionMenu(event, menu); + oldOpenedMenu = menu; + } +} + +function onKeyDown(event) { + if (event.keyCode === 27) dismissMenu(oldOpenedMenu); +} + +function onClick() { + dismissMenu(oldOpenedMenu); +} + +function dismissMenu(menu) { + if (menu) menu.style.display = "none"; +} + +function useContextMenu(menuId) { + const ref = useRef(); + useEffect(() => { + const parent = ref.current; + const handler = e => contextMenuHandler(e, ref, menuId); + parent.addEventListener("contextmenu", handler); + window.onkeydown = onKeyDown; + window.onclick = onClick; + return () => { + parent.removeEventListener("contextmenu", handler); + }; + }); + return [ref, onClick]; +} + +function getPosition(e) { + var posx = 0; + var posy = 0; + + if (!e) e = window.event; + + if (e.pageX || e.pageY) { + posx = e.pageX; + posy = e.pageY; + } else if (e.clientX || e.clientY) { + posx = + e.clientX + + document.body.scrollLeft + + document.documentElement.scrollLeft; + posy = + e.clientY + document.body.scrollTop + document.documentElement.scrollTop; + } + + return { + x: posx - 50, + y: posy - 100 + }; +} + +// updated positionMenu function +function positionMenu(e, menu) { + const clickCoords = getPosition(e); + const clickCoordsX = clickCoords.x; + const clickCoordsY = clickCoords.y; + + const menuWidth = menu.offsetWidth + 4; + const menuHeight = menu.offsetHeight + 4; + + const windowWidth = window.innerWidth; + const windowHeight = window.innerHeight; + + if (windowWidth - clickCoordsX < menuWidth) { + menu.style.left = windowWidth - menuWidth + "px"; + } else { + menu.style.left = clickCoordsX + "px"; + } + + if (windowHeight - clickCoordsY < menuHeight) { + menu.style.top = windowHeight - menuHeight + "px"; + } else { + menu.style.top = clickCoordsY + "px"; + } +} + +export default useContextMenu; diff --git a/apps/web/yarn.lock b/apps/web/yarn.lock index 5dd61947c..57ffd943d 100644 --- a/apps/web/yarn.lock +++ b/apps/web/yarn.lock @@ -6812,8 +6812,8 @@ normalize-url@^3.0.0, normalize-url@^3.0.1: integrity sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg== "notes-core@https://github.com/thecodrr/notes-core.git": - version "1.1.0" - resolved "https://github.com/thecodrr/notes-core.git#b270a0640f2a8195d86e21a64bf40e651034c545" + version "1.2.0" + resolved "https://github.com/thecodrr/notes-core.git#f9b8bc23e4fe779cd569f7e58c2f5fc2ae92729f" dependencies: fast-sort "^2.0.1" fuzzysearch "^1.0.3"