11 changed files with 326 additions and 18 deletions
@ -4,7 +4,7 @@ specifiers: |
|||||
'@emeraldpay/hashicon-react': ^0.5.2 |
'@emeraldpay/hashicon-react': ^0.5.2 |
||||
'@floating-ui/react-dom': ^0.4.3 |
'@floating-ui/react-dom': ^0.4.3 |
||||
'@meshtastic/components': ^1.0.23 |
'@meshtastic/components': ^1.0.23 |
||||
'@meshtastic/meshtasticjs': ^0.6.43 |
'@meshtastic/meshtasticjs': ^0.6.45 |
||||
'@reduxjs/toolkit': ^1.7.2 |
'@reduxjs/toolkit': ^1.7.2 |
||||
'@types/mapbox-gl': ^2.6.1 |
'@types/mapbox-gl': ^2.6.1 |
||||
'@types/react': ^17.0.39 |
'@types/react': ^17.0.39 |
||||
@ -62,7 +62,7 @@ dependencies: |
|||||
'@emeraldpay/hashicon-react': 0.5.2 |
'@emeraldpay/hashicon-react': 0.5.2 |
||||
'@floating-ui/react-dom': 0.4.3_b8fdba992ce7d797017dc07106486496 |
'@floating-ui/react-dom': 0.4.3_b8fdba992ce7d797017dc07106486496 |
||||
'@meshtastic/components': 1.0.23_@[email protected] |
'@meshtastic/components': 1.0.23_@[email protected] |
||||
'@meshtastic/meshtasticjs': 0.6.43 |
'@meshtastic/meshtasticjs': 0.6.45 |
||||
'@reduxjs/toolkit': 1.7[email protected][email protected] |
'@reduxjs/toolkit': 1.7[email protected][email protected] |
||||
base64-js: 1.5.1 |
base64-js: 1.5.1 |
||||
framer-motion: 6.2[email protected][email protected] |
framer-motion: 6.2[email protected][email protected] |
||||
@ -1587,8 +1587,8 @@ packages: |
|||||
- '@types/react' |
- '@types/react' |
||||
dev: false |
dev: false |
||||
|
|
||||
/@meshtastic/meshtasticjs/0.6.43: |
/@meshtastic/meshtasticjs/0.6.45: |
||||
resolution: {integrity: sha512-INI9hj3AzjkXzJIp2yq65eV908wTCk6Ih5/5fMknKhwOgx14eC6d5qhlWxjC85kHB6gu8c/2KF3LUCFKHh+1fg==} |
resolution: {integrity: sha512-icAGMofpQ3hYqWhjYMLqMyhb0Xtk3GozEgOXScFTKVOaecDY0XIJmuvoBDfgD2lxNxDDPr0Dj77js+3JGxTcRg==} |
||||
dependencies: |
dependencies: |
||||
'@protobuf-ts/runtime': 2.2.2 |
'@protobuf-ts/runtime': 2.2.2 |
||||
sub-events: 1.8.9 |
sub-events: 1.8.9 |
||||
|
|||||
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 6.3 KiB |
|
After Width: | Height: | Size: 6.4 KiB |
@ -0,0 +1,93 @@ |
|||||
|
import React from 'react'; |
||||
|
|
||||
|
import { m } from 'framer-motion'; |
||||
|
import { FiActivity, FiAperture, FiTag } from 'react-icons/fi'; |
||||
|
|
||||
|
export interface ContextMenuProps { |
||||
|
children: React.ReactNode; |
||||
|
} |
||||
|
|
||||
|
export const ContextMenu = ({ children }: ContextMenuProps): JSX.Element => { |
||||
|
const [visible, setVisible] = React.useState(false); |
||||
|
const [position, setPosition] = React.useState({ x: 0, y: 0 }); |
||||
|
const [selectedValue, setSelectedValue] = React.useState<string>(); |
||||
|
const doSomething = (selectedValue: string) => { |
||||
|
setSelectedValue(selectedValue); |
||||
|
}; |
||||
|
|
||||
|
const showContextMenu = (event: React.MouseEvent<HTMLDivElement>) => { |
||||
|
event.preventDefault(); |
||||
|
|
||||
|
setVisible(false); |
||||
|
const newPosition = { |
||||
|
x: event.pageX, |
||||
|
y: event.pageY, |
||||
|
}; |
||||
|
|
||||
|
setPosition(newPosition); |
||||
|
setVisible(true); |
||||
|
}; |
||||
|
|
||||
|
const hideContextMenu = (event: React.MouseEvent<HTMLDivElement>) => { |
||||
|
setVisible(false); |
||||
|
}; |
||||
|
|
||||
|
return ( |
||||
|
<div |
||||
|
className="h-full" |
||||
|
onContextMenu={showContextMenu} |
||||
|
onClick={hideContextMenu} |
||||
|
> |
||||
|
{children} |
||||
|
{selectedValue && <h1>{selectedValue} is selected</h1>} |
||||
|
|
||||
|
{visible && ( |
||||
|
<div |
||||
|
style={{ top: position.y, left: position.x }} |
||||
|
className="fixed z-50 w-60 gap-2 divide-y divide-gray-300 rounded-md border border-gray-300 font-medium shadow-md backdrop-blur-xl dark:divide-gray-600 dark:border-gray-600 dark:text-gray-400" |
||||
|
> |
||||
|
<div className="cursor-pointer first:rounded-t-md last:rounded-b-md hover:dark:bg-secondaryDark"> |
||||
|
<m.div |
||||
|
whileHover={{ scale: 1.01 }} |
||||
|
whileTap={{ scale: 0.99 }} |
||||
|
className="flex gap-2 p-2" |
||||
|
> |
||||
|
<div className="my-auto"> |
||||
|
<FiActivity /> |
||||
|
</div> |
||||
|
<div className="truncate">Menu item</div> |
||||
|
</m.div> |
||||
|
</div> |
||||
|
|
||||
|
<div className="cursor-pointer first:rounded-t-md last:rounded-b-md hover:dark:bg-secondaryDark"> |
||||
|
<m.div |
||||
|
whileHover={{ scale: 1.01 }} |
||||
|
whileTap={{ scale: 0.99 }} |
||||
|
className="flex gap-2 p-2" |
||||
|
> |
||||
|
<div className="my-auto"> |
||||
|
<FiAperture /> |
||||
|
</div> |
||||
|
<div className="truncate">Menu item 2</div> |
||||
|
</m.div> |
||||
|
</div> |
||||
|
|
||||
|
<div className="cursor-pointer first:rounded-t-md last:rounded-b-md hover:dark:bg-secondaryDark"> |
||||
|
<m.div |
||||
|
whileHover={{ scale: 1.01 }} |
||||
|
whileTap={{ scale: 0.99 }} |
||||
|
className="flex gap-2 p-2" |
||||
|
> |
||||
|
<div className="my-auto"> |
||||
|
<FiTag /> |
||||
|
</div> |
||||
|
<div className="truncate"> |
||||
|
Menu item 3 with a very long name that should wrap |
||||
|
</div> |
||||
|
</m.div> |
||||
|
</div> |
||||
|
</div> |
||||
|
)} |
||||
|
</div> |
||||
|
); |
||||
|
}; |
||||
Loading…
Reference in new issue