mirror of
https://github.com/billsonnn/nitro-react.git
synced 2025-01-31 10:22:36 +01:00
collapsable context menu
This commit is contained in:
parent
1266b79989
commit
c4fc67ac19
@ -87,7 +87,7 @@ export const AvatarInfoUseProductView: FC<AvatarInfoUseProductViewProps> = props
|
|||||||
}, [ item, updateConfirmingProduct ]);
|
}, [ item, updateConfirmingProduct ]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ContextMenuView objectId={ item.id } category={ RoomObjectCategory.UNIT } userType={ RoomObjectType.PET } close={ close }>
|
<ContextMenuView objectId={ item.id } category={ RoomObjectCategory.UNIT } userType={ RoomObjectType.PET } close={ close } collapsable={ true }>
|
||||||
<ContextMenuHeaderView>
|
<ContextMenuHeaderView>
|
||||||
{ item.name }
|
{ item.name }
|
||||||
</ContextMenuHeaderView>
|
</ContextMenuHeaderView>
|
||||||
|
@ -213,7 +213,7 @@ export const AvatarInfoWidgetAvatarView: FC<AvatarInfoWidgetAvatarViewProps> = p
|
|||||||
}, [ userData ]);
|
}, [ userData ]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ContextMenuView objectId={ userData.roomIndex } category={ RoomObjectCategory.UNIT } userType={ userData.userType } close={ close }>
|
<ContextMenuView objectId={ userData.roomIndex } category={ RoomObjectCategory.UNIT } userType={ userData.userType } close={ close } collapsable={ true }>
|
||||||
<ContextMenuHeaderView className="cursor-pointer" onClick={ event => GetUserProfile(userData.webID) }>
|
<ContextMenuHeaderView className="cursor-pointer" onClick={ event => GetUserProfile(userData.webID) }>
|
||||||
{ userData.name }
|
{ userData.name }
|
||||||
</ContextMenuHeaderView>
|
</ContextMenuHeaderView>
|
||||||
|
@ -121,7 +121,8 @@ export const AvatarInfoWidgetOwnAvatarView: FC<AvatarInfoWidgetOwnAvatarViewProp
|
|||||||
const isRidingHorse = IsRidingHorse();
|
const isRidingHorse = IsRidingHorse();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ContextMenuView objectId={ userData.roomIndex } category={ RoomObjectCategory.UNIT } userType={ userData.userType } close={ close }>
|
<ContextMenuView objectId={ userData.roomIndex } category={ RoomObjectCategory.UNIT } userType={ userData.userType } close={ close } collapsable={ true }>
|
||||||
|
|
||||||
<ContextMenuHeaderView className="cursor-pointer" onClick={ event => GetUserProfile(userData.webID) }>
|
<ContextMenuHeaderView className="cursor-pointer" onClick={ event => GetUserProfile(userData.webID) }>
|
||||||
{ userData.name }
|
{ userData.name }
|
||||||
</ContextMenuHeaderView>
|
</ContextMenuHeaderView>
|
||||||
|
@ -142,7 +142,7 @@ export const AvatarInfoWidgetOwnPetView: FC<AvatarInfoWidgetOwnPetViewProps> = p
|
|||||||
}, [ petData ]);
|
}, [ petData ]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ContextMenuView objectId={ petData.roomIndex } category={ RoomObjectCategory.UNIT } userType={ RoomObjectType.PET } close={ close }>
|
<ContextMenuView objectId={ petData.roomIndex } category={ RoomObjectCategory.UNIT } userType={ RoomObjectType.PET } close={ close } collapsable={ true }>
|
||||||
<ContextMenuHeaderView>
|
<ContextMenuHeaderView>
|
||||||
{ petData.name }
|
{ petData.name }
|
||||||
</ContextMenuHeaderView>
|
</ContextMenuHeaderView>
|
||||||
|
@ -109,7 +109,7 @@ export const AvatarInfoWidgetPetView: FC<AvatarInfoWidgetPetViewProps> = props =
|
|||||||
}, [ petData ]);
|
}, [ petData ]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ContextMenuView objectId={ petData.roomIndex } category={ RoomObjectCategory.UNIT } userType={ RoomObjectType.PET } close={ close }>
|
<ContextMenuView objectId={ petData.roomIndex } category={ RoomObjectCategory.UNIT } userType={ RoomObjectType.PET } close={ close } collapsable={ true }>
|
||||||
<ContextMenuHeaderView>
|
<ContextMenuHeaderView>
|
||||||
{ petData.name }
|
{ petData.name }
|
||||||
</ContextMenuHeaderView>
|
</ContextMenuHeaderView>
|
||||||
|
@ -136,7 +136,7 @@ export const AvatarInfoWidgetRentableBotView: FC<AvatarInfoWidgetRentableBotView
|
|||||||
const canControl = (rentableBotData.amIOwner || rentableBotData.amIAnyRoomController);
|
const canControl = (rentableBotData.amIOwner || rentableBotData.amIAnyRoomController);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ContextMenuView objectId={ rentableBotData.roomIndex } category={ RoomObjectCategory.UNIT } userType={ RoomObjectType.RENTABLE_BOT } close={ close }>
|
<ContextMenuView objectId={ rentableBotData.roomIndex } category={ RoomObjectCategory.UNIT } userType={ RoomObjectType.RENTABLE_BOT } close={ close } collapsable={ true }>
|
||||||
<ContextMenuHeaderView>
|
<ContextMenuHeaderView>
|
||||||
{ rentableBotData.name }
|
{ rentableBotData.name }
|
||||||
</ContextMenuHeaderView>
|
</ContextMenuHeaderView>
|
||||||
|
@ -20,9 +20,11 @@
|
|||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:not(.name-only) {
|
&:not(.name-only):not(.menu-hidden) {
|
||||||
min-width: 125px;
|
min-width: 125px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(.name-only) {
|
||||||
&:after {
|
&:after {
|
||||||
content: "";
|
content: "";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@ -49,6 +51,22 @@
|
|||||||
margin-bottom: 2px;
|
margin-bottom: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.menu-hidden {
|
||||||
|
.menu-footer {
|
||||||
|
padding-top:2px;
|
||||||
|
padding-bottom:0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-footer {
|
||||||
|
color: $white;
|
||||||
|
font-size: 16px;
|
||||||
|
width:100%;
|
||||||
|
min-width: 25px;
|
||||||
|
padding-bottom:2px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
.menu-list-split-3 {
|
.menu-list-split-3 {
|
||||||
|
|
||||||
.menu-item {
|
.menu-item {
|
||||||
|
@ -0,0 +1,25 @@
|
|||||||
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
|
import { FC, useMemo } from 'react';
|
||||||
|
import { Flex, FlexProps } from '../../../../common';
|
||||||
|
|
||||||
|
interface CaretViewProps extends FlexProps
|
||||||
|
{
|
||||||
|
collapsed?: boolean;
|
||||||
|
}
|
||||||
|
export const ContextMenuCaretView: FC<CaretViewProps> = props =>
|
||||||
|
{
|
||||||
|
const { justifyContent = 'center', alignItems = 'center', classNames = [], collapsed = true, ...rest } = props;
|
||||||
|
|
||||||
|
const getClassNames = useMemo(() =>
|
||||||
|
{
|
||||||
|
const newClassNames: string[] = [ 'menu-footer' ];
|
||||||
|
|
||||||
|
if(classNames.length) newClassNames.push(...classNames);
|
||||||
|
|
||||||
|
return newClassNames;
|
||||||
|
}, [ classNames ]);
|
||||||
|
|
||||||
|
return <Flex justifyContent={ justifyContent } alignItems={ alignItems } classNames={ getClassNames } { ...rest }>
|
||||||
|
<FontAwesomeIcon icon={ !collapsed ? 'caret-down' : 'caret-up' } className="align-self-center" />
|
||||||
|
</Flex>
|
||||||
|
}
|
@ -2,6 +2,7 @@ import { FixedSizeStack, NitroPoint, NitroRectangle, RoomObjectType } from '@nit
|
|||||||
import { CSSProperties, FC, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
import { CSSProperties, FC, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||||
import { GetNitroInstance, GetRoomObjectBounds, GetRoomObjectScreenLocation, GetRoomSession, GetTicker } from '../../../../api';
|
import { GetNitroInstance, GetRoomObjectBounds, GetRoomObjectScreenLocation, GetRoomSession, GetTicker } from '../../../../api';
|
||||||
import { Base, BaseProps } from '../../../../common';
|
import { Base, BaseProps } from '../../../../common';
|
||||||
|
import { ContextMenuCaretView } from './ContextMenuCaretView';
|
||||||
|
|
||||||
interface ContextMenuViewProps extends BaseProps<HTMLDivElement>
|
interface ContextMenuViewProps extends BaseProps<HTMLDivElement>
|
||||||
{
|
{
|
||||||
@ -10,6 +11,7 @@ interface ContextMenuViewProps extends BaseProps<HTMLDivElement>
|
|||||||
userType?: number;
|
userType?: number;
|
||||||
fades?: boolean;
|
fades?: boolean;
|
||||||
close: () => void;
|
close: () => void;
|
||||||
|
collapsable?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const LOCATION_STACK_SIZE: number = 25;
|
const LOCATION_STACK_SIZE: number = 25;
|
||||||
@ -18,9 +20,11 @@ const fadeDelay = 3000;
|
|||||||
const fadeLength = 75;
|
const fadeLength = 75;
|
||||||
const SPACE_AROUND_EDGES = 10;
|
const SPACE_AROUND_EDGES = 10;
|
||||||
|
|
||||||
|
let COLLAPSED = false;
|
||||||
|
|
||||||
export const ContextMenuView: FC<ContextMenuViewProps> = props =>
|
export const ContextMenuView: FC<ContextMenuViewProps> = props =>
|
||||||
{
|
{
|
||||||
const { objectId = -1, category = -1, userType = -1, fades = false, close = null, position = 'absolute', classNames = [], style = {}, ...rest } = props;
|
const { objectId = -1, category = -1, userType = -1, fades = false, close = null, position = 'absolute', classNames = [], style = {}, children = null, collapsable = false, ...rest } = props;
|
||||||
const [ pos, setPos ] = useState<{ x: number, y: number }>({ x: null, y: null });
|
const [ pos, setPos ] = useState<{ x: number, y: number }>({ x: null, y: null });
|
||||||
const [ deltaYStack, setDeltaYStack ] = useState<FixedSizeStack>(null);
|
const [ deltaYStack, setDeltaYStack ] = useState<FixedSizeStack>(null);
|
||||||
const [ currentDeltaY, setCurrentDeltaY ] = useState(-1000000);
|
const [ currentDeltaY, setCurrentDeltaY ] = useState(-1000000);
|
||||||
@ -30,6 +34,8 @@ export const ContextMenuView: FC<ContextMenuViewProps> = props =>
|
|||||||
const [ isFrozen, setIsFrozen ] = useState(false);
|
const [ isFrozen, setIsFrozen ] = useState(false);
|
||||||
const elementRef = useRef<HTMLDivElement>();
|
const elementRef = useRef<HTMLDivElement>();
|
||||||
|
|
||||||
|
const [ collapsed, setCollapsed ] = useState(COLLAPSED);
|
||||||
|
|
||||||
const getOffset = useCallback((bounds: NitroRectangle) =>
|
const getOffset = useCallback((bounds: NitroRectangle) =>
|
||||||
{
|
{
|
||||||
let height = -(elementRef.current.offsetHeight);
|
let height = -(elementRef.current.offsetHeight);
|
||||||
@ -118,13 +124,15 @@ export const ContextMenuView: FC<ContextMenuViewProps> = props =>
|
|||||||
const getClassNames = useMemo(() =>
|
const getClassNames = useMemo(() =>
|
||||||
{
|
{
|
||||||
const newClassNames: string[] = [ 'nitro-context-menu' ];
|
const newClassNames: string[] = [ 'nitro-context-menu' ];
|
||||||
|
|
||||||
|
if (collapsed) newClassNames.push('menu-hidden');
|
||||||
|
|
||||||
newClassNames.push((pos.x !== null) ? 'visible' : 'invisible');
|
newClassNames.push((pos.x !== null) ? 'visible' : 'invisible');
|
||||||
|
|
||||||
if(classNames.length) newClassNames.push(...classNames);
|
if(classNames.length) newClassNames.push(...classNames);
|
||||||
|
|
||||||
return newClassNames;
|
return newClassNames;
|
||||||
}, [ pos, classNames ]);
|
}, [ pos, classNames, collapsed ]);
|
||||||
|
|
||||||
const getStyle = useMemo(() =>
|
const getStyle = useMemo(() =>
|
||||||
{
|
{
|
||||||
@ -170,6 +178,15 @@ export const ContextMenuView: FC<ContextMenuViewProps> = props =>
|
|||||||
|
|
||||||
return () => clearTimeout(timeout);
|
return () => clearTimeout(timeout);
|
||||||
}, [ fades ]);
|
}, [ fades ]);
|
||||||
|
|
||||||
|
|
||||||
return <Base innerRef={ elementRef } position={ position } classNames={ getClassNames } style={ getStyle } onMouseOver={ event => setIsFrozen(true) } onMouseOut={ event => setIsFrozen(false) } { ...rest } />;
|
const toggleCollapse = () =>
|
||||||
|
{
|
||||||
|
COLLAPSED = !COLLAPSED;
|
||||||
|
setCollapsed(COLLAPSED)
|
||||||
|
}
|
||||||
|
return <Base innerRef={ elementRef } position={ position } classNames={ getClassNames } style={ getStyle } onMouseOver={ event => setIsFrozen(true) } onMouseOut={ event => setIsFrozen(false) } { ...rest }>
|
||||||
|
{ !(collapsable && COLLAPSED) && children }
|
||||||
|
{ collapsable && <ContextMenuCaretView onClick={ () => toggleCollapse() } collapsed={ collapsed } /> }
|
||||||
|
</Base>;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user