import React, { useEffect, useState, useContext } from "react"; import { Box, Input, Flex, Text, IconButton } from "theme-ui"; import Slider from "../Slider"; import MapMenu from "../map/MapMenu"; import colors, { colorOptions } from "../../helpers/colors"; import usePrevious from "../../helpers/usePrevious"; import LockIcon from "../../icons/TokenLockIcon"; import UnlockIcon from "../../icons/TokenUnlockIcon"; import ShowIcon from "../../icons/TokenShowIcon"; import HideIcon from "../../icons/TokenHideIcon"; import AuthContext from "../../contexts/AuthContext"; const defaultNoteMaxSize = 6; function NoteMenu({ isOpen, onRequestClose, note, noteNode, onNoteChange, map, }) { const { userId } = useContext(AuthContext); const wasOpen = usePrevious(isOpen); const [noteMaxSize, setNoteMaxSize] = useState(defaultNoteMaxSize); const [menuLeft, setMenuLeft] = useState(0); const [menuTop, setMenuTop] = useState(0); useEffect(() => { if (isOpen && !wasOpen && note) { setNoteMaxSize(Math.max(note.size, defaultNoteMaxSize)); // Update menu position if (noteNode) { const nodeRect = noteNode.getClientRect(); const mapElement = document.querySelector(".map"); const mapRect = mapElement.getBoundingClientRect(); // Center X for the menu which is 156px wide setMenuLeft(mapRect.left + nodeRect.x + nodeRect.width / 2 - 156 / 2); // Y 12px from the bottom setMenuTop(mapRect.top + nodeRect.y + nodeRect.height + 12); } } }, [isOpen, note, wasOpen, noteNode]); function handleTextChange(event) { const text = event.target.value; note && onNoteChange({ ...note, text: text }); } function handleColorChange(color) { if (!note) { return; } onNoteChange({ ...note, color: color }); } function handleSizeChange(event) { const newSize = parseInt(event.target.value); note && onNoteChange({ ...note, size: newSize }); } function handleVisibleChange() { note && onNoteChange({ ...note, visible: !note.visible }); } function handleLockChange() { note && onNoteChange({ ...note, locked: !note.locked }); } function handleModalContent(node) { if (node) { // Focus input const tokenLabelInput = node.querySelector("#changeNoteText"); tokenLabelInput.focus(); tokenLabelInput.select(); // Ensure menu is in bounds const nodeRect = node.getBoundingClientRect(); const mapElement = document.querySelector(".map"); const mapRect = mapElement.getBoundingClientRect(); setMenuLeft((prevLeft) => Math.min( mapRect.right - nodeRect.width, Math.max(mapRect.left, prevLeft) ) ); setMenuTop((prevTop) => Math.min(mapRect.bottom - nodeRect.height, prevTop) ); } } return ( { e.preventDefault(); onRequestClose(); }} sx={{ alignItems: "center" }} > {colorOptions.map((color) => ( handleColorChange(color)} aria-label={`Note label Color ${color}`} > {note && note.color === color && ( )} ))} Size: {/* Only show hide and lock token actions to map owners */} {map && map.owner === userId && ( {note && note.visible ? : } {note && note.locked ? : } )} ); } export default NoteMenu;