Axonpack

The context menu

The package decides which actions apply. You render the popover.

The package computes which actions apply to a node and what each one does to the expansion state. You render the menu itself.

It cannot ship one. A floating menu has to escape its scroll container, which needs a Modal on React Native and a portal or position: fixed on the DOM. React Native has no portal and the DOM has no modal, so there is no shared subset to write against.

const [menu, setMenu] = useState<{ items: MenuItem[]; x: number; y: number } | null>(null);

<JsonTree
  primitives={{ View, Text, Pressable }}
  value={response}
  onCopy={Clipboard.setStringAsync}
  onRequestMenu={(items, event) => {
    const { pageX, pageY } = (event as GestureResponderEvent).nativeEvent;
    setMenu({ items, x: pageX, y: pageY });
  }}
/>;

MenuItem is { label: string; onSelect: () => void; copyText?: string }. Render the labels and call onSelect on press.

A copy item also carries copyText, the text it copies. It is for a host that has to do the copying itself, somewhere onSelect does not run: a browser drawing the menu for a tree that lives on a device, for example, where the browser's clipboard is the one that matters.

Which items appear

ItemWhen
Copy value, Copy objectonCopy is set
Expand, CollapseThe node is a container with children
Expand recursively, Collapse recursivelyThe node is a container with children

onRequestMenu is what enables the gesture, which is long-press on React Native and right-click on the web. Without it, no menu is requested.

event is unknown because the package never reads it. Cast it at this one call site: nativeEvent.pageX on React Native, clientX on a DOM mouse event.

On this page