| 1 | import * as Haptics from "expo-haptics"; |
| 2 | import { cloneElement, isValidElement, type ReactElement } from "react"; |
| 3 | import { AndroidAnchoredMenu } from "./AndroidAnchoredMenu"; |
| 4 | import type { ControlPillMenuProps } from "./ControlPillMenu.types"; |
| 5 | |
| 6 | /** Uses the same actions as iOS menus, with Android appearance and editor anchoring. */ |
| 7 | export function ControlPillMenu(props: ControlPillMenuProps) { |
| 8 | // Long-press menus keep their child interactive: the child element gets |
| 9 | // an injected onLongPress (mirroring the iOS context-menu interaction) |
| 10 | // so its own tap handling still works. |
| 11 | if (props.shouldOpenOnLongPress && isValidElement(props.children)) { |
| 12 | const child = props.children as ReactElement<{ onLongPress?: () => void }>; |
| 13 | return ( |
| 14 | <AndroidAnchoredMenu |
| 15 | actions={props.actions} |
| 16 | className={props.className} |
| 17 | title={props.title} |
| 18 | style={props.style} |
| 19 | onPressAction={props.onPressAction} |
| 20 | > |
| 21 | {(open) => |
| 22 | cloneElement(child, { |
| 23 | onLongPress: () => { |
| 24 | void Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Medium); |
| 25 | open(); |
| 26 | }, |
| 27 | }) |
| 28 | } |
| 29 | </AndroidAnchoredMenu> |
| 30 | ); |
| 31 | } |
| 32 | return ( |
| 33 | <AndroidAnchoredMenu |
| 34 | actions={props.actions} |
| 35 | className={props.className} |
| 36 | title={props.title} |
| 37 | style={props.style} |
| 38 | onPressAction={props.onPressAction} |
| 39 | > |
| 40 | {props.children} |
| 41 | </AndroidAnchoredMenu> |
| 42 | ); |
| 43 | } |