mirror of
https://github.com/CommunityOx/ox_lib.git
synced 2026-08-18 15:36:02 +01:00
feat(web/context): mouse enter and mouse leave events (#218)
* feat(web/context): mouse enter and mouse leave events * chore(web/context): condense into one function for onHover * feat(resource/context): cache last hovered option
This commit is contained in:
committed by
GitHub
parent
6fe8f5257f
commit
7a22da68e6
@@ -6,6 +6,7 @@ interface ContextMenuItem {
|
|||||||
icon?: IconName | [IconPrefix, IconName];
|
icon?: IconName | [IconPrefix, IconName];
|
||||||
iconColor?: string;
|
iconColor?: string;
|
||||||
onSelect?: (args: any) => void;
|
onSelect?: (args: any) => void;
|
||||||
|
onHover?: (hoverState: boolean, args: any) => void;
|
||||||
arrow?: boolean;
|
arrow?: boolean;
|
||||||
description?: string;
|
description?: string;
|
||||||
metadata?: string | { [key: string]: any } | string[];
|
metadata?: string | { [key: string]: any } | string[];
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
local contextMenus = {}
|
local contextMenus = {}
|
||||||
|
local lastHoveredContextItem = nil
|
||||||
local openContextMenu = nil
|
local openContextMenu = nil
|
||||||
local keepInput = IsNuiFocusKeepingInput()
|
local keepInput = IsNuiFocusKeepingInput()
|
||||||
|
|
||||||
@@ -8,6 +9,7 @@ local keepInput = IsNuiFocusKeepingInput()
|
|||||||
---@field icon? string
|
---@field icon? string
|
||||||
---@field iconColor? string
|
---@field iconColor? string
|
||||||
---@field onSelect? fun(args: any)
|
---@field onSelect? fun(args: any)
|
||||||
|
---@field onHover? fun(hoverState: boolean, args: any)
|
||||||
---@field arrow? boolean
|
---@field arrow? boolean
|
||||||
---@field description? string
|
---@field description? string
|
||||||
---@field metadata? string | { [string]: any } | string[]
|
---@field metadata? string | { [string]: any } | string[]
|
||||||
@@ -41,9 +43,25 @@ local function closeContext(_, cb, onExit)
|
|||||||
|
|
||||||
if not cb then SendNUIMessage({ action = 'hideContext' }) end
|
if not cb then SendNUIMessage({ action = 'hideContext' }) end
|
||||||
|
|
||||||
|
if lastHoveredContextItem then
|
||||||
|
local data = contextMenus[openContextMenu].options[lastHoveredContextItem]
|
||||||
|
if data.onHover then data.onHover(false, data.args) end
|
||||||
|
lastHoveredContextItem = nil
|
||||||
|
end
|
||||||
|
|
||||||
openContextMenu = nil
|
openContextMenu = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function checkID(id)
|
||||||
|
if math.type(tonumber(id)) == 'float' then
|
||||||
|
id = math.tointeger(id)
|
||||||
|
elseif tonumber(id) then
|
||||||
|
id += 1
|
||||||
|
end
|
||||||
|
|
||||||
|
return id
|
||||||
|
end
|
||||||
|
|
||||||
---@param id string
|
---@param id string
|
||||||
function lib.showContext(id)
|
function lib.showContext(id)
|
||||||
if not contextMenus[id] then error('No context menu of such id found.') end
|
if not contextMenus[id] then error('No context menu of such id found.') end
|
||||||
@@ -89,14 +107,11 @@ RegisterNUICallback('openContext', function(data, cb)
|
|||||||
lib.showContext(data.id)
|
lib.showContext(data.id)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
|
||||||
RegisterNUICallback('clickContext', function(id, cb)
|
RegisterNUICallback('clickContext', function(id, cb)
|
||||||
cb(1)
|
cb(1)
|
||||||
|
|
||||||
if math.type(tonumber(id)) == 'float' then
|
local id = checkID(id)
|
||||||
id = math.tointeger(id)
|
|
||||||
elseif tonumber(id) then
|
|
||||||
id += 1
|
|
||||||
end
|
|
||||||
|
|
||||||
local data = contextMenus[openContextMenu].options[id]
|
local data = contextMenus[openContextMenu].options[id]
|
||||||
|
|
||||||
@@ -110,12 +125,35 @@ RegisterNUICallback('clickContext', function(id, cb)
|
|||||||
if data.event then TriggerEvent(data.event, data.args) end
|
if data.event then TriggerEvent(data.event, data.args) end
|
||||||
if data.serverEvent then TriggerServerEvent(data.serverEvent, data.args) end
|
if data.serverEvent then TriggerServerEvent(data.serverEvent, data.args) end
|
||||||
|
|
||||||
|
if lastHoveredContextItem then
|
||||||
|
local data = contextMenus[openContextMenu].options[lastHoveredContextItem]
|
||||||
|
if data.onHover then data.onHover(false, data.args) end
|
||||||
|
lastHoveredContextItem = nil
|
||||||
|
end
|
||||||
|
|
||||||
SendNUIMessage({
|
SendNUIMessage({
|
||||||
action = 'hideContext'
|
action = 'hideContext'
|
||||||
})
|
})
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
RegisterNUICallback('onHover', function(data, cb)
|
||||||
|
cb(1)
|
||||||
|
|
||||||
|
local id = checkID(data.id)
|
||||||
|
local hoverState = data.hoverState
|
||||||
|
|
||||||
|
local data = contextMenus[openContextMenu].options[id]
|
||||||
|
|
||||||
|
if not data.onHover then return end
|
||||||
|
|
||||||
|
if data.onHover and hoverState == true then
|
||||||
|
lastHoveredContextItem = id
|
||||||
|
data.onHover(true, data.args)
|
||||||
|
end
|
||||||
|
if data.onHover and hoverState == false then
|
||||||
|
lastHoveredContextItem = nil
|
||||||
|
data.onHover(false, data.args)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
RegisterNUICallback('closeContext', closeContext)
|
RegisterNUICallback('closeContext', closeContext)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -8,10 +8,6 @@ const openMenu = (id: string | undefined) => {
|
|||||||
fetchNui<ContextMenuProps>('openContext', { id: id, back: false });
|
fetchNui<ContextMenuProps>('openContext', { id: id, back: false });
|
||||||
};
|
};
|
||||||
|
|
||||||
const clickContext = (id: string) => {
|
|
||||||
fetchNui('clickContext', id);
|
|
||||||
};
|
|
||||||
|
|
||||||
const useStyles = createStyles((theme, params: { disabled?: boolean }) => ({
|
const useStyles = createStyles((theme, params: { disabled?: boolean }) => ({
|
||||||
inner: {
|
inner: {
|
||||||
justifyContent: 'flex-start',
|
justifyContent: 'flex-start',
|
||||||
@@ -51,7 +47,11 @@ const ContextButton: React.FC<{
|
|||||||
<HoverCard.Target>
|
<HoverCard.Target>
|
||||||
<Button
|
<Button
|
||||||
classNames={{ inner: classes.inner, label: classes.label }}
|
classNames={{ inner: classes.inner, label: classes.label }}
|
||||||
onClick={() => (!button.disabled ? (button.menu ? openMenu(button.menu) : clickContext(buttonKey)) : null)}
|
onClick={() =>
|
||||||
|
!button.disabled ? (button.menu ? openMenu(button.menu) : fetchNui('clickContext', buttonKey)) : null
|
||||||
|
}
|
||||||
|
onMouseEnter={() => (!button.disabled ? fetchNui('onHover', { hoverState: true, id: buttonKey }) : null)}
|
||||||
|
onMouseLeave={() => (!button.disabled ? fetchNui('onHover', { hoverState: false, id: buttonKey }) : null)}
|
||||||
variant="default"
|
variant="default"
|
||||||
h="fit-content"
|
h="fit-content"
|
||||||
p={10}
|
p={10}
|
||||||
@@ -90,17 +90,19 @@ const ContextButton: React.FC<{
|
|||||||
<HoverCard.Dropdown className={classes.dropdown}>
|
<HoverCard.Dropdown className={classes.dropdown}>
|
||||||
{button.image && <Image src={button.image} />}
|
{button.image && <Image src={button.image} />}
|
||||||
{Array.isArray(button.metadata) ? (
|
{Array.isArray(button.metadata) ? (
|
||||||
button.metadata.map((metadata: string | { label: string; value?: any; progress?: number }, index: number) => (
|
button.metadata.map(
|
||||||
|
(metadata: string | { label: string; value?: any; progress?: number }, index: number) => (
|
||||||
<>
|
<>
|
||||||
<Text key={`context-metadata-${index}`}>
|
<Text key={`context-metadata-${index}`}>
|
||||||
{typeof metadata === 'string' ? `${metadata}` : `${metadata.label}: ${metadata?.value ?? ""}`}
|
{typeof metadata === 'string' ? `${metadata}` : `${metadata.label}: ${metadata?.value ?? ''}`}
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
{typeof metadata === 'object' && metadata.progress !== undefined && (
|
{typeof metadata === 'object' && metadata.progress !== undefined && (
|
||||||
<Progress value={metadata.progress} size="sm" color={button.colorScheme || 'dark.3'} />
|
<Progress value={metadata.progress} size="sm" color={button.colorScheme || 'dark.3'} />
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
))
|
)
|
||||||
|
)
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
{typeof button.metadata === 'object' &&
|
{typeof button.metadata === 'object' &&
|
||||||
|
|||||||
Reference in New Issue
Block a user