{"version":3,"file":"ContextMenu.cjs","names":[],"sources":["../../../src/components/Menu/ContextMenu.tsx"],"sourcesContent":["/*\nCopyright 2023 New Vector Ltd.\n\nSPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial\nPlease see LICENSE files in the repository root for full details.\n*/\n\nimport React, {\n  type FC,\n  type ReactNode,\n  useCallback,\n  useMemo,\n  useState,\n} from \"react\";\nimport {\n  Root,\n  Trigger,\n  Portal,\n  Content,\n  ContextMenuItem,\n  ContextMenuSub,\n  ContextMenuSubTrigger,\n  ContextMenuSubContent,\n  ContextMenuPortal,\n} from \"@radix-ui/react-context-menu\";\nimport { FloatingMenu } from \"./FloatingMenu\";\nimport { Drawer } from \"vaul\";\nimport classnames from \"classnames\";\nimport drawerStyles from \"./DrawerMenu.module.css\";\nimport {\n  MenuContext,\n  type MenuData,\n  type MenuItemWrapperProps,\n  type SubMenuWrapperProps,\n} from \"./MenuContext\";\nimport { DrawerMenu } from \"./DrawerMenu\";\nimport { getPlatform } from \"../../utils/platform\";\n\ninterface Props {\n  /**\n   * The menu title.\n   */\n  title: string;\n  /**\n   * Wether the title is displayed.\n   * @default true\n   */\n  showTitle?: boolean;\n  /**\n   * Event handler called when the open state of the menu changes.\n   */\n  onOpenChange?: (open: boolean) => void;\n  /**\n   * The trigger that can be right-clicked or long-pressed to open the menu.\n   * This must be a component that accepts a ref and spreads props.\n   * https://www.radix-ui.com/primitives/docs/guides/composition\n   */\n  trigger: ReactNode;\n  /**\n   * Whether the functionality of this menu is available through some other\n   * keyboard-accessible means. Preferably this should be true, because context\n   * menus are potentially difficult to discover, but if false the trigger will\n   * become focusable so that it can be opened via keyboard navigation.\n   */\n  hasAccessibleAlternative: boolean;\n  /**\n   * The menu contents.\n   */\n  children: ReactNode;\n}\n\nconst ContextMenuItemWrapper: FC<MenuItemWrapperProps> = ({\n  onSelect,\n  children,\n}) => (\n  <ContextMenuItem onSelect={onSelect ?? undefined} asChild>\n    {children}\n  </ContextMenuItem>\n);\n\nconst ContextSubMenuWrapper: FC<SubMenuWrapperProps> = ({\n  trigger,\n  children,\n  open,\n  onOpenChange,\n}) => (\n  <ContextMenuSub open={open} onOpenChange={onOpenChange}>\n    <ContextMenuSubTrigger asChild>{trigger}</ContextMenuSubTrigger>\n    <ContextMenuPortal>\n      <ContextMenuSubContent asChild alignOffset={-20}>\n        <FloatingMenu title=\"\" showTitle={false}>\n          {children}\n        </FloatingMenu>\n      </ContextMenuSubContent>\n    </ContextMenuPortal>\n  </ContextMenuSub>\n);\n\n/**\n * A menu opened by right-clicking or long-pressing another UI element.\n */\nexport const ContextMenu: FC<Props> = ({\n  title,\n  showTitle = true,\n  onOpenChange: onOpenChangeProp,\n  trigger: triggerProp,\n  hasAccessibleAlternative,\n  children: childrenProp,\n}) => {\n  const [open, setOpen] = useState(false);\n  const onOpenChange = useCallback(\n    (value: boolean) => {\n      setOpen(value);\n      onOpenChangeProp?.(value);\n    },\n    [setOpen, onOpenChangeProp],\n  );\n\n  // Normally, the menu takes the form of a floating box. But on Android and\n  // iOS, the menu should morph into a drawer\n  const platform = getPlatform();\n  const drawer = platform === \"android\" || platform === \"ios\";\n  const context: MenuData = useMemo(\n    () => ({\n      MenuItemWrapper: drawer ? null : ContextMenuItemWrapper,\n      SubMenuWrapper: drawer ? null : ContextSubMenuWrapper,\n      onOpenChange,\n    }),\n    [onOpenChange],\n  );\n  const children = (\n    <MenuContext.Provider value={context}>{childrenProp}</MenuContext.Provider>\n  );\n\n  const trigger = (\n    <Trigger\n      aria-haspopup=\"menu\"\n      tabIndex={hasAccessibleAlternative ? undefined : 0}\n      asChild\n    >\n      {triggerProp}\n    </Trigger>\n  );\n\n  // This is a small hack: Vaul drawers only support buttons as triggers, so\n  // we end up mounting an empty Radix context menu tree alongside the\n  // drawer tree, purely so we can use its Trigger component (which supports\n  // touch for free). The resulting behavior and DOM tree looks exactly the\n  // same as if Vaul provided a long-press trigger of its own, so I think\n  // this is fine.\n  return drawer ? (\n    <>\n      <Root onOpenChange={onOpenChange}>{trigger}</Root>\n      <Drawer.Root open={open} onOpenChange={onOpenChange}>\n        <Drawer.Portal>\n          <Drawer.Overlay className={classnames(drawerStyles.bg)} />\n          <Drawer.Content asChild>\n            <DrawerMenu title={title}>{children}</DrawerMenu>\n          </Drawer.Content>\n        </Drawer.Portal>\n      </Drawer.Root>\n    </>\n  ) : (\n    <Root onOpenChange={onOpenChange}>\n      {trigger}\n      <Portal>\n        <Content asChild>\n          <FloatingMenu showTitle={showTitle} title={title}>\n            {children}\n          </FloatingMenu>\n        </Content>\n      </Portal>\n    </Root>\n  );\n};\n"],"mappings":";;;;;;;;;;;;;;AAuEA,IAAM,0BAAoD,EACxD,UACA,eAEA,iBAAA,GAAA,kBAAA,KAAC,6BAAA,iBAAD;CAAiB,UAAU,YAAY,KAAA;CAAW,SAAA;CAC/C;CACe,CAAA;AAGpB,IAAM,yBAAkD,EACtD,SACA,UACA,MACA,mBAEA,iBAAA,GAAA,kBAAA,MAAC,6BAAA,gBAAD;CAAsB;CAAoB;WAA1C,CACE,iBAAA,GAAA,kBAAA,KAAC,6BAAA,uBAAD;EAAuB,SAAA;YAAS;EAAgC,CAAA,EAChE,iBAAA,GAAA,kBAAA,KAAC,6BAAA,mBAAD,EAAA,UACE,iBAAA,GAAA,kBAAA,KAAC,6BAAA,uBAAD;EAAuB,SAAA;EAAQ,aAAa;YAC1C,iBAAA,GAAA,kBAAA,KAAC,qBAAA,cAAD;GAAc,OAAM;GAAG,WAAW;GAC/B;GACY,CAAA;EACO,CAAA,EACN,CAAA,CACL;;;;;AAMnB,IAAa,eAA0B,EACrC,OACA,YAAY,MACZ,cAAc,kBACd,SAAS,aACT,0BACA,UAAU,mBACN;CACJ,MAAM,CAAC,MAAM,YAAA,GAAA,MAAA,UAAoB,MAAM;CACvC,MAAM,gBAAA,GAAA,MAAA,cACH,UAAmB;AAClB,UAAQ,MAAM;AACd,qBAAmB,MAAM;IAE3B,CAAC,SAAS,iBAAiB,CAC5B;CAID,MAAM,WAAW,iBAAA,aAAa;CAC9B,MAAM,SAAS,aAAa,aAAa,aAAa;CACtD,MAAM,WAAA,GAAA,MAAA,gBACG;EACL,iBAAiB,SAAS,OAAO;EACjC,gBAAgB,SAAS,OAAO;EAChC;EACD,GACD,CAAC,aAAa,CACf;CACD,MAAM,WACJ,iBAAA,GAAA,kBAAA,KAAC,oBAAA,YAAY,UAAb;EAAsB,OAAO;YAAU;EAAoC,CAAA;CAG7E,MAAM,UACJ,iBAAA,GAAA,kBAAA,KAAC,6BAAA,SAAD;EACE,iBAAc;EACd,UAAU,2BAA2B,KAAA,IAAY;EACjD,SAAA;YAEC;EACO,CAAA;AASZ,QAAO,SACL,iBAAA,GAAA,kBAAA,MAAA,kBAAA,UAAA,EAAA,UAAA,CACE,iBAAA,GAAA,kBAAA,KAAC,6BAAA,MAAD;EAAoB;YAAe;EAAe,CAAA,EAClD,iBAAA,GAAA,kBAAA,KAAC,KAAA,OAAO,MAAR;EAAmB;EAAoB;YACrC,iBAAA,GAAA,kBAAA,MAAC,KAAA,OAAO,QAAR,EAAA,UAAA,CACE,iBAAA,GAAA,kBAAA,KAAC,KAAA,OAAO,SAAR,EAAgB,YAAA,GAAA,WAAA,SAAsB,0BAAA,QAAa,GAAG,EAAI,CAAA,EAC1D,iBAAA,GAAA,kBAAA,KAAC,KAAA,OAAO,SAAR;GAAgB,SAAA;aACd,iBAAA,GAAA,kBAAA,KAAC,mBAAA,YAAD;IAAmB;IAAQ;IAAsB,CAAA;GAClC,CAAA,CACH,EAAA,CAAA;EACJ,CAAA,CACb,EAAA,CAAA,GAEH,iBAAA,GAAA,kBAAA,MAAC,6BAAA,MAAD;EAAoB;YAApB,CACG,SACD,iBAAA,GAAA,kBAAA,KAAC,6BAAA,QAAD,EAAA,UACE,iBAAA,GAAA,kBAAA,KAAC,6BAAA,SAAD;GAAS,SAAA;aACP,iBAAA,GAAA,kBAAA,KAAC,qBAAA,cAAD;IAAyB;IAAkB;IACxC;IACY,CAAA;GACP,CAAA,EACH,CAAA,CACJ"}