From c03db3e0d55f2ba14a8d82ba1380e9838769efe1 Mon Sep 17 00:00:00 2001 From: ricewind012 <58827198+ricewind012@users.noreply.github.com> Date: Sat, 25 Jan 2025 12:23:52 +0000 Subject: [PATCH] fix(Menu): add missing arg to showContextMenu and document it --- src/components/Dropdown.ts | 8 +-- src/components/Menu.ts | 125 ++++++++++++++++++++++++++++++++++++- 2 files changed, 124 insertions(+), 9 deletions(-) diff --git a/src/components/Dropdown.ts b/src/components/Dropdown.ts index 8e63c0c..92e8af3 100644 --- a/src/components/Dropdown.ts +++ b/src/components/Dropdown.ts @@ -3,6 +3,7 @@ import { ReactNode, FC } from 'react'; import { CommonUIModule } from '../webpack'; import { ItemProps } from './Item'; import { createPropListRegex } from '../utils'; +import type { ContextMenuPositionOptions } from './Menu'; export interface SingleDropdownOption { data: any; @@ -20,11 +21,6 @@ export interface MultiDropdownOption { export type DropdownOption = SingleDropdownOption | MultiDropdownOption; -export interface DropdownMenuPositionOptions { - [_: string]: unknown - bMatchWidth?: boolean -} - export interface DropdownProps { rgOptions: DropdownOption[]; selectedOption: any; @@ -32,7 +28,7 @@ export interface DropdownProps { onMenuWillOpen?(showMenu: () => void): void; onMenuOpened?(): void; onChange?(data: SingleDropdownOption): void; - contextMenuPositionOptions?: DropdownMenuPositionOptions; + contextMenuPositionOptions?: ContextMenuPositionOptions; menuLabel?: string; strDefaultLabel?: string; renderButtonValue?(element: ReactNode): ReactNode; diff --git a/src/components/Menu.ts b/src/components/Menu.ts index 50ad9ad..863ccd6 100755 --- a/src/components/Menu.ts +++ b/src/components/Menu.ts @@ -3,9 +3,128 @@ import { FC, ReactNode } from 'react'; import { Export, findModuleByExport, findModuleExport } from '../webpack'; import { FooterLegendProps } from './FooterLegend'; -export const showContextMenu: (children: ReactNode, parent?: EventTarget) => void = findModuleExport( - (e: Export) => typeof e === 'function' && e.toString().includes('GetContextMenuManagerFromWindow(') - && e.toString().includes('.CreateContextMenuInstance('), +interface PopupCreationOptions { + /** + * Initially hidden, make it appear with {@link ContextMenuInstance.Show}. + */ + bCreateHidden?: boolean; + + bModal?: boolean; + + /** + * Document title. + */ + title?: string; +} + +// Separate interface, since one of webpack module exports uses this exact object, +// so maybe it could be reused elsewhere. +interface MonitorOptions { + targetMonitor: { + flMonitorScale: number; + nScreenLeft: number; + nScreenTop: number; + nScreenWidth: number; + nScreenHeight: number; + }; + flGamepadScale: number; +} + +export interface ContextMenuPositionOptions extends PopupCreationOptions, Partial { + /** + * When {@link bForcePopup} is true, makes the window appear above everything else. + */ + bAlwaysOnTop?: boolean; + + /** + * Disables the mouse overlay, granting the ability to click anywhere while + * the menu's active. + */ + bDisableMouseOverlay?: boolean; + + /** + * Disables the {@link bPreferPopTop} behavior. + */ + bDisablePopTop?: boolean; + + bFitToWindow?: boolean; + + /** + * Forces the menu to open in a separate window instead of inside the parent. + */ + bForcePopup?: boolean; + + /** + * Like {@link bMatchWidth}, but don't shrink below the menu's minimum width. + */ + bGrowToElementWidth?: boolean; + + /** + * Match the parent's exact height. + */ + bMatchHeight?: boolean; + + /** + * Match the parent's exact width. + */ + bMatchWidth?: boolean; + + bNoFocusWhenShown?: boolean; + + /** + * Makes the menu **invisible**, instead of getting removed from the DOM. + */ + bRetainOnHide?: boolean; + + bScreenCoordinates?: boolean; + + /** + * Set to `true` to not account for the parent's width. + */ + bOverlapHorizontal?: boolean; + + /** + * Set to `true` to not account for the parent's height. + */ + bOverlapVertical?: boolean; + + /** + * Set to `true` to make the entire menu try to appear on the left side from + * the parent. + */ + bPreferPopLeft?: boolean; + + /** + * Set to `true` to make the entire menu try to appear above the parent. + */ + bPreferPopTop?: boolean; + + bShiftToFitWindow?: boolean; + + // different window creation flags (StandaloneContextMenu vs PopupContextMenu) + bStandalone?: boolean; + + /** + * Class name **replacement** for the container element, i.e. it replaces the + * default class. + */ + strClassName?: string; +} + +interface ContextMenuInstance { + Hide(): void; + Show(): void; +} + +export const showContextMenu: ( + children: ReactNode, + parent?: EventTarget, + options?: ContextMenuPositionOptions, +) => ContextMenuInstance = findModuleExport( + (e: Export) => + typeof e === 'function' && + e.toString().includes('GetContextMenuManagerFromWindow(') && + e.toString().includes('.CreateContextMenuInstance('), ); export interface MenuProps extends FooterLegendProps {