import { useImperativeHandle, forwardRef, useMemo, useRef, useState, type Ref } from 'react' import { View, Animated, TouchableHighlight } from 'react-native' import { useWindowSize } from '@/utils/hooks' import Modal, { type ModalType } from './Modal' import { createStyle } from '@/utils/tools' import { useTheme } from '@/store/theme/hook' import Text from './Text' import { scaleSizeH, scaleSizeW } from '@/utils/pixelRatio' const menuItemHeight = scaleSizeH(40) const menuItemWidth = scaleSizeW(100) export interface Position { w: number, h: number, x: number, y: number, menuWidth?: number, menuHeight?: number } export interface MenuSize { width?: number, height?: number } export type Menus = Readonly> const styles = createStyle({ mask: { position: 'absolute', top: 0, bottom: 0, left: 0, right: 0, opacity: 0, backgroundColor: 'black', }, menu: { position: 'absolute', // borderWidth: StyleSheet.hairlineWidth, borderColor: 'lightgray', borderRadius: 2, backgroundColor: 'white', elevation: 3, }, menuItem: { paddingLeft: 10, paddingRight: 10, // height: menuItemHeight, // width: menuItemWidth, // alignItems: 'center', justifyContent: 'center', // backgroundColor: '#ccc', }, // menuText: { // // textAlign: 'center', // fontSize: 14, // }, }) interface Props { menus: Readonly onPress?: (menu: M[number]) => void buttonPosition: Position menuSize: MenuSize onHide: () => void width?: number height?: number fontSize?: number center?: boolean activeId?: M[number]['action'] | null } const Menu = ({ buttonPosition, menuSize, menus, onPress = () => {}, onHide, activeId, fontSize = 15, center = false, }: Props) => { const theme = useTheme() const windowSize = useWindowSize() // const fadeAnim = useRef(new Animated.Value(0)).current // console.log(buttonPosition) const menuItemStyle = useMemo(() => { return { width: menuSize.width ?? menuItemWidth, height: menuSize.height ?? menuItemHeight, } }, [menuSize]) const menuStyle = useMemo(() => { let menuHeight = menus.length * menuItemStyle.height const topHeight = buttonPosition.y - 20 const bottomHeight = windowSize.height - buttonPosition.y - buttonPosition.h - 20 if (menuHeight > topHeight && menuHeight > bottomHeight) menuHeight = Math.max(topHeight, bottomHeight) const menuWidth = menuItemStyle.width const bottomSpace = windowSize.height - buttonPosition.y - buttonPosition.h - 20 const rightSpace = windowSize.width - buttonPosition.x - menuWidth const showInBottom = bottomSpace >= menuHeight const showInRight = rightSpace >= menuWidth const frameStyle: { height: number width: number top: number left?: number right?: number } = { height: menuHeight, top: showInBottom ? buttonPosition.y + buttonPosition.h : buttonPosition.y - menuHeight, width: menuWidth, } if (showInRight) { frameStyle.left = buttonPosition.x } else { frameStyle.right = windowSize.width - buttonPosition.x - buttonPosition.w } return frameStyle }, [menus.length, menuItemStyle, buttonPosition, windowSize]) const menuPress = (menu: Menus[number]) => { // if (menu.disabled) return onPress(menu) onHide() } // console.log('render menu') // console.log(activeId) // console.log(menuStyle) // console.log(menuItemStyle) return ( true}> { menus.map((menu, index) => ( menu.disabled ? ( {menu.label} ) : menu.action == activeId ? ( {menu.label} ) : ( { menuPress(menu) }} > {menu.label} ) )) } ) } export interface MenuProps { menus: M onPress: (menu: M[number]) => void onHide?: () => void width?: number height?: number fontSize?: number center?: boolean activeId?: M[number]['action'] | null } export interface MenuType { show: (position: Position, menuSize?: MenuSize) => void hide: () => void } const Component = ({ menus, activeId, onHide, onPress, fontSize, center }: MenuProps, ref: Ref) => { // console.log(visible) const modalRef = useRef(null) const [position, setPosition] = useState({ w: 0, h: 0, x: 0, y: 0 }) const [menuSize, setMenuSize] = useState({ }) const hide = () => { modalRef.current?.setVisible(false) } useImperativeHandle(ref, () => ({ show(newPosition, menuSize) { setPosition(newPosition) if (menuSize) setMenuSize(menuSize) modalRef.current?.setVisible(true) }, hide() { hide() }, })) return ( ) } // export default forwardRef(Component) as ForwardRefFn export default forwardRef(Component) as (p: MenuProps & { ref?: Ref }) => JSX.Element | null