right click context menu custom effect

This commit is contained in:
Michael Peters 2021-12-30 21:04:14 -06:00
parent 640b671568
commit e8ca0d0ed4
4 changed files with 42 additions and 24 deletions

View File

@ -5,6 +5,10 @@
padding: 4px 16px;
user-select: text;
.context {
user-select: none;
}
&.continued {
margin-top: -4px;

View File

@ -1,11 +1,12 @@
import React, { FC, MouseEvent, useCallback, useMemo, useRef, useState } from 'react';
import React, { FC, useCallback, useMemo, useRef } from 'react';
import CombinedGuild from '../../../guild-combined';
import GuildsManager from '../../../guilds-manager';
import ContextMenu from '../../contexts/components/context-menu';
import BasicHover, { BasicHoverSide } from '../../contexts/context-hover-basic';
import BaseElements from '../../require/base-elements';
import { IAlignment } from '../../require/elements-util';
import GuildSubscriptions from '../../require/guild-subscriptions';
import ReactHelper from '../../require/react-helper';
import ReactHelper, { useContextClickContextMenu } from '../../require/react-helper';
export interface GuildListElementProps {
guildsManager: GuildsManager;
@ -50,12 +51,10 @@ const GuildListElement: FC<GuildListElementProps> = (props: GuildListElementProp
await guildsManager.removeGuild(guild);
}, [ guildsManager, guild ])
const [ contextClickPos, setContextClickPos ] = useState<{ x: number, y: number }>({ x: 0, y: 0 });
const [ contextClickMenu, toggleMenu, closeMenu, openMenu ] = ReactHelper.useContextMenu((close: () => void) => {
const [ contextClickMenu, onContextClick ] = useContextClickContextMenu((alignment: IAlignment, relativeToPos: { x: number, y: number }, close: () => void) => {
return (
<ContextMenu
alignment={{ top: 'centerY', left: 'centerX' }}
relativeToPos={contextClickPos} close={close}
alignment={alignment} relativeToPos={relativeToPos} close={close}
>
<div className="guild-context">
<div className="item red leave-guild" onClick={leaveGuildCallable}>Leave Guild</div>
@ -63,10 +62,6 @@ const GuildListElement: FC<GuildListElementProps> = (props: GuildListElementProp
</ContextMenu>
)
}, [ leaveGuildCallable ]);
const onContextMenu = useCallback((e: MouseEvent<HTMLDivElement>) => {
setContextClickPos({ x: e.clientX, y: e.clientY });
openMenu();
}, [ openMenu ]);
const className = useMemo(() => {
return activeGuild && guild.id === activeGuild.id ? 'guild active' : 'guild';
@ -77,7 +72,7 @@ const GuildListElement: FC<GuildListElementProps> = (props: GuildListElementProp
<div
className={className} ref={rootRef}
onClick={setSelfActiveGuild}
onContextMenu={onContextMenu}
onContextMenu={onContextClick}
onMouseEnter={mouseEnterCallable} onMouseLeave={mouseLeaveCallable}
>
<div className="pill" />

View File

@ -1,12 +1,12 @@
import moment from 'moment';
import React, { Dispatch, FC, MouseEvent, ReactNode, SetStateAction, useCallback, useMemo, useState } from 'react';
import React, { Dispatch, FC, ReactNode, SetStateAction, useCallback, useMemo } from 'react';
import { Member, Message } from '../../../data-types';
import CombinedGuild from '../../../guild-combined';
import ImageContextMenu from '../../contexts/context-menu-image';
import ImageOverlay from '../../overlays/overlay-image';
import ElementsUtil from '../../require/elements-util';
import ElementsUtil, { IAlignment } from '../../require/elements-util';
import GuildSubscriptions from '../../require/guild-subscriptions';
import ReactHelper from '../../require/react-helper';
import ReactHelper, { useContextClickContextMenu } from '../../require/react-helper';
interface ResourceElementProps {
guild: CombinedGuild;
@ -55,26 +55,20 @@ const PreviewImageElement: FC<PreviewImageElementProps> = (props: PreviewImageEl
// TODO: Handle resourceError
const [ previewImgSrc, previewResource, previewResourceError ] = GuildSubscriptions.useSoftImageSrcResourceSubscription(guild, resourcePreviewId);
const [ relativeToPos, setRelativeToPos ] = useState<{ x: number, y: number }>({ x: 0, y: 0 });
const [ contextMenu, toggleContextMenu ] = ReactHelper.useContextMenu((close: () => void) => {
const [ contextMenu, onContextMenu ] = useContextClickContextMenu((alignment: IAlignment, relativeToPos: { x: number, y: number }, close: () => void) => {
if (!previewResource) return null;
return (
<ImageContextMenu
relativeToPos={relativeToPos} close={close}
resourceName={resourceName} resourceBuff={previewResource.data} isPreview={true}
/>
)
}, [ previewResource, relativeToPos, resourceName ]);
);
}, [ previewResource, resourceName ]);
const openImageOverlay = useCallback(() => {
setOverlay(<ImageOverlay guild={guild} resourceId={resourceId} resourceName={resourceName} close={() => setOverlay(null)} />);
}, [ guild, resourceId, resourceName ]);
const onContextMenu = useCallback((event: MouseEvent<HTMLImageElement>) => {
setRelativeToPos({ x: event.clientX, y: event.clientY });
toggleContextMenu();
}, [ toggleContextMenu ]);
return (
<div className="content image" style={{ width: previewWidth, height: previewHeight }}>
<img

View File

@ -478,7 +478,7 @@ export default class ReactHelper {
setIsOpen(oldIsOpen => !!contextMenu && !oldIsOpen);
}, [ contextMenu ]);
const open = useCallback(() => {
setIsOpen(!!contextMenu);
setIsOpen(true);
}, [ contextMenu ]);
return [ isOpen ? contextMenu : null, toggle, close, open, isOpen ];
@ -544,3 +544,28 @@ export default class ReactHelper {
return [ dropTarget ];
}
}
export function useContextClickContextMenu(
createContextMenu: (alignment: IAlignment, relativeToPos: { x: number, y: number }, close: () => void) => ReactNode,
createContextMenuDeps: DependencyList
): [
contextMenu: ReactNode,
onContextMenu: (event: React.MouseEvent<HTMLElement>) => void
] {
const [ relativeToPos, setRelativeToPos ] = useState<{ x: number, y: number }>({ x: 0, y: 0 });
const alignment = useMemo(() => ({ top: 'centerY', left: 'centerX' }), [])
const createContextMenuWithRelativeToPos = useCallback((close: () => void) => {
return createContextMenu(alignment, relativeToPos, close);
}, [ alignment, relativeToPos ]);
const [ contextMenu, toggle, close, open ] = ReactHelper.useContextMenu(createContextMenuWithRelativeToPos, createContextMenuDeps);
const onContextMenu = useCallback((event: React.MouseEvent<HTMLElement>) => {
setRelativeToPos({ x: event.clientX, y: event.clientY });
open();
}, [ open ]);
return [ contextMenu, onContextMenu ];
}