{"version":3,"sources":["../src/components/Menu.tsx","../src/components/ItemTrackerProvider.tsx","../src/core/eventManager.ts","../src/hooks/useItemTracker.ts","../src/constants.ts","../src/core/contextMenu.ts","../src/hooks/useContextMenu.ts","../src/components/keyboardController.ts","../src/components/utils.ts","../src/components/Item.tsx","../src/components/Separator.tsx","../src/components/Submenu.tsx","../src/components/Arrow.tsx","../src/components/RightSlot.tsx"],"names":["React","useEffect","useReducer","useRef","useState","cx","useContext","createContext","Context","useItemTrackerContext","ItemTrackerProvider","props","createEventManager","eventList","event","handler","args","eventManager","useItemTracker","NOOP","hideOnEvents","contextMenu","id","position","useContextMenu","params","createKeyboardController","menuList","focusedIndex","parentNode","isRoot","currentItems","forceCloseSubmenu","init","rootMenu","focusSelectedItem","isSubmenuFocused","getSubmenuItems","isFocused","moveDown","closeSubmenu","moveUp","openSubmenu","submenuItems","node","setSubmenuPosition","parent","matchKeys","e","walkAndMatch","items","item","Children","cloneElement","isFn","v","isStr","cloneItems","children","getMousePosition","pos","touch","getPredicateValue","predicate","payload","flushSync","reducer","state","Menu","theme","style","className","animation","preventDefaultOnKeydown","disableBoundariesCheck","onVisibilityChange","rest","setState","nodeRef","itemTracker","menuController","wasVisible","visibilityId","show","hide","checkBoundaries","x","y","innerWidth","innerHeight","offsetWidth","offsetHeight","preventDefault","handleKeyboard","ev","p","handleAnimationEnd","computeAnimationClasses","visible","willLeave","triggerEvent","propsFromTrigger","cssClasses","Item","data","keyMatcher","onClick","disabled","hidden","closeOnClick","handlerEvent","itemNode","handlerParams","isDisabled","isHidden","handleClick","dispatchUserHanlder","registerItem","handleKeyDown","Separator","Arrow","RightSlot","Submenu","arrow","label","parentItemTracker","submenuNode","setPosition","bottom","right","rect","trackRef"],"mappings":"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","sourcesContent":["import React, {\n  ReactNode,\n  useEffect,\n  useReducer,\n  useRef,\n  useState,\n} from 'react';\nimport cx from 'clsx';\n\nimport { ItemTrackerProvider } from './ItemTrackerProvider';\n\nimport { eventManager } from '../core/eventManager';\nimport { TriggerEvent, MenuId, MenuAnimation, Theme } from '../types';\nimport { useItemTracker } from '../hooks';\nimport { createKeyboardController } from './keyboardController';\nimport { CssClass, EVENT, hideOnEvents } from '../constants';\nimport { cloneItems, getMousePosition, isFn, isStr } from './utils';\nimport { flushSync } from 'react-dom';\nimport { ShowContextMenuParams } from '../core';\n\nexport interface MenuProps\n  extends Omit<React.HTMLAttributes<HTMLElement>, 'id'> {\n  /**\n   * Unique id to identify the menu. Use to Trigger the corresponding menu\n   */\n  id: MenuId;\n\n  /**\n   * Any valid node that can be rendered\n   */\n  children: ReactNode;\n\n  /**\n   * Theme is appended to `contexify_theme-${given theme}`.\n   *\n   * Built-in theme are `light` and `dark`\n   */\n  theme?: Theme;\n\n  /**\n   * Animation is appended to\n   * - `.contexify_willEnter-${given animation}`\n   * - `.contexify_willLeave-${given animation}`\n   *\n   * - To disable all animations you can pass `false`\n   * - To disable only the enter or the exit animation you can provide an object `{enter: false, exit: 'exitAnimation'}`\n   *\n   * - default is set to `fade`\n   */\n  animation?: MenuAnimation;\n\n  /**\n   * Disables menu repositioning if outside screen.\n   * This may be neeeded in some cases when using custom position.\n   */\n  disableBoundariesCheck?: boolean;\n\n  /**\n   * Prevents scrolling the window on when typing. Defaults to true.\n   */\n  preventDefaultOnKeydown?: boolean;\n\n  /**\n   * Used to track menu visibility\n   */\n  onVisibilityChange?: (isVisible: boolean) => void;\n}\n\ninterface MenuState {\n  x: number;\n  y: number;\n  visible: boolean;\n  triggerEvent: TriggerEvent;\n  propsFromTrigger: any;\n  willLeave: boolean;\n}\n\nfunction reducer(\n  state: MenuState,\n  payload: Partial<MenuState> | ((state: MenuState) => Partial<MenuState>)\n) {\n  return { ...state, ...(isFn(payload) ? payload(state) : payload) };\n}\n\nexport const Menu: React.FC<MenuProps> = ({\n  id,\n  theme,\n  style,\n  className,\n  children,\n  animation = 'fade',\n  preventDefaultOnKeydown = true,\n  disableBoundariesCheck = false,\n  onVisibilityChange,\n  ...rest\n}) => {\n  const [state, setState] = useReducer(reducer, {\n    x: 0,\n    y: 0,\n    visible: false,\n    triggerEvent: {} as TriggerEvent,\n    propsFromTrigger: null,\n    willLeave: false,\n  });\n  const nodeRef = useRef<HTMLDivElement>(null);\n  const itemTracker = useItemTracker();\n  const [menuController] = useState(() => createKeyboardController());\n  const wasVisible = useRef<boolean>();\n  const visibilityId = useRef<number>();\n\n  // subscribe event manager\n  useEffect(() => {\n    eventManager.on(id, show).on(EVENT.HIDE_ALL, hide);\n\n    return () => {\n      eventManager.off(id, show).off(EVENT.HIDE_ALL, hide);\n    };\n    // hide rely on setState(dispatch), which is guaranted to be the same across render\n  }, [id, animation, disableBoundariesCheck]);\n\n  // collect menu items for keyboard navigation\n  useEffect(() => {\n    !state.visible ? itemTracker.clear() : menuController.init(itemTracker);\n  }, [state.visible, menuController, itemTracker]);\n\n  function checkBoundaries(x: number, y: number) {\n    if (nodeRef.current && !disableBoundariesCheck) {\n      const { innerWidth, innerHeight } = window;\n      const { offsetWidth, offsetHeight } = nodeRef.current;\n\n      if (x + offsetWidth > innerWidth) x -= x + offsetWidth - innerWidth;\n\n      if (y + offsetHeight > innerHeight) y -= y + offsetHeight - innerHeight;\n    }\n\n    return { x, y };\n  }\n\n  // when the menu is transitioning from not visible to visible,\n  // the nodeRef is attached to the dom element this let us check the boundaries\n  useEffect(() => {\n    // state.visible and state{x,y} are updated together\n    if (state.visible) setState(checkBoundaries(state.x, state.y));\n  }, [state.visible]);\n\n  // subscribe dom events\n  useEffect(() => {\n    function preventDefault(e: KeyboardEvent) {\n      if (preventDefaultOnKeydown) e.preventDefault();\n    }\n\n    function handleKeyboard(e: KeyboardEvent) {\n      switch (e.key) {\n        case 'Enter':\n        case ' ':\n          if (!menuController.openSubmenu()) hide();\n          break;\n        case 'Escape':\n          hide();\n          break;\n        case 'ArrowUp':\n          preventDefault(e);\n          menuController.moveUp();\n          break;\n        case 'ArrowDown':\n          preventDefault(e);\n          menuController.moveDown();\n          break;\n        case 'ArrowRight':\n          preventDefault(e);\n          menuController.openSubmenu();\n          break;\n        case 'ArrowLeft':\n          preventDefault(e);\n          menuController.closeSubmenu();\n          break;\n        default:\n          menuController.matchKeys(e);\n          break;\n      }\n    }\n\n    if (state.visible) {\n      window.addEventListener('keydown', handleKeyboard);\n\n      for (const ev of hideOnEvents) window.addEventListener(ev, hide);\n    }\n\n    return () => {\n      window.removeEventListener('keydown', handleKeyboard);\n\n      for (const ev of hideOnEvents) window.removeEventListener(ev, hide);\n    };\n  }, [state.visible, menuController, preventDefaultOnKeydown]);\n\n  function show({ event, props, position }: ShowContextMenuParams) {\n    event.stopPropagation();\n    const p = position || getMousePosition(event);\n    // check boundaries when the menu is already visible\n    const { x, y } = checkBoundaries(p.x, p.y);\n\n    flushSync(() => {\n      setState({\n        visible: true,\n        willLeave: false,\n        x,\n        y,\n        triggerEvent: event,\n        propsFromTrigger: props,\n      });\n    });\n\n    clearTimeout(visibilityId.current);\n    if (!wasVisible.current && isFn(onVisibilityChange)) {\n      onVisibilityChange(true);\n      wasVisible.current = true;\n    }\n  }\n\n  function hide(e?: Event) {\n    type SafariEvent = KeyboardEvent & MouseEvent;\n\n    if (\n      e != null &&\n      // Safari trigger a click event when you ctrl + trackpad\n      ((e as SafariEvent).button === 2 || (e as SafariEvent).ctrlKey) &&\n      // Firefox trigger a click event when right click occur\n      e.type !== 'contextmenu'\n    )\n      return;\n\n    animation && (isStr(animation) || ('exit' in animation && animation.exit))\n      ? setState((state) => ({ willLeave: state.visible }))\n      : setState((state) => ({\n          visible: state.visible ? false : state.visible,\n        }));\n\n    visibilityId.current = setTimeout(() => {\n      isFn(onVisibilityChange) && onVisibilityChange(false);\n      wasVisible.current = false;\n    });\n  }\n\n  function handleAnimationEnd() {\n    if (state.willLeave && state.visible) {\n      flushSync(() => setState({ visible: false, willLeave: false }));\n    }\n  }\n\n  function computeAnimationClasses() {\n    if (isStr(animation)) {\n      return cx({\n        [`${CssClass.animationWillEnter}${animation}`]: visible && !willLeave,\n        [`${CssClass.animationWillLeave}${animation} ${CssClass.animationWillLeave}'disabled'`]:\n          visible && willLeave,\n      });\n    } else if (animation && 'enter' in animation && 'exit' in animation) {\n      return cx({\n        [`${CssClass.animationWillEnter}${animation.enter}`]:\n          animation.enter && visible && !willLeave,\n        [`${CssClass.animationWillLeave}${animation.exit} ${CssClass.animationWillLeave}'disabled'`]:\n          animation.exit && visible && willLeave,\n      });\n    }\n\n    return null;\n  }\n\n  const { visible, triggerEvent, propsFromTrigger, x, y, willLeave } = state;\n  const cssClasses = cx(\n    CssClass.menu,\n    className,\n    { [`${CssClass.theme}${theme}`]: theme },\n    computeAnimationClasses()\n  );\n\n  // TODO: switch to translate instead of top left\n  // requires an additional dom element around the menu\n  return (\n    <ItemTrackerProvider value={itemTracker}>\n      {visible && (\n        <div\n          {...rest}\n          className={cssClasses}\n          onAnimationEnd={handleAnimationEnd}\n          style={{\n            ...style,\n            left: x,\n            top: y,\n            opacity: 1,\n          }}\n          ref={nodeRef}\n          role=\"menu\"\n        >\n          {cloneItems(children, {\n            propsFromTrigger,\n            triggerEvent,\n          })}\n        </div>\n      )}\n    </ItemTrackerProvider>\n  );\n};\n","import React, { useContext, createContext } from 'react';\nimport { ItemTracker } from '../hooks';\n\nconst Context = createContext({} as ItemTracker);\n\nexport const useItemTrackerContext = () => useContext(Context);\n\nexport interface ItemTrackerProviderProps {\n  value: ItemTracker;\n  children?: React.ReactNode;\n}\n\nexport const ItemTrackerProvider: React.FC<ItemTrackerProviderProps> = (\n  props\n) => <Context.Provider {...props} />;\n","export type EventType = string | number | symbol;\nexport type Handler<T = any> = (args: T) => void;\n\nexport interface EventManager<E = EventType> {\n  on<T = any>(event: E, handler: Handler<T>): EventManager<E>;\n  off<T = any>(event: E, handler?: Handler<T>): EventManager<E>;\n  emit<T = any>(event: E, args?: T): EventManager<E>;\n}\n\nfunction createEventManager<E = EventType>(): EventManager<E> {\n  const eventList = new Map<E, Set<Handler>>();\n\n  return {\n    on<T = any>(event: E, handler: Handler<T>) {\n      eventList.has(event)\n        ? eventList.get(event)!.add(handler)\n        : eventList.set(event, new Set([handler]));\n      return this;\n    },\n    off<T = any>(event: E, handler: Handler<T>) {\n      eventList.has(event) && eventList.get(event)!.delete(handler);\n      return this;\n    },\n    emit<T = any>(event: E, args: T) {\n      eventList.has(event) &&\n        eventList.get(event)!.forEach((handler: Handler<T>) => {\n          handler(args);\n        });\n      return this;\n    },\n  };\n}\n\nexport const eventManager = createEventManager();\n","import { useRef } from 'react';\n\nexport interface ItemTrackerRecord {\n  node: HTMLElement;\n  isSubmenu: boolean;\n  submenuRefTracker?: ItemTracker;\n  setSubmenuPosition?: () => void;\n  keyMatcher?: false | ((e: KeyboardEvent) => void);\n}\n\nexport type ItemTracker = ReturnType<typeof useItemTracker>;\n\nexport const useItemTracker = () =>\n  useRef<Map<HTMLElement, ItemTrackerRecord>>(new Map()).current;\n","/*\n * css classes mapping\n * */\nexport const enum CssClass {\n  menu = 'contexify',\n  submenu = 'contexify_submenu',\n  submenuOpen = 'contexify_submenu-isOpen',\n  rightSlot = 'contexify_rightSlot',\n  separator = 'contexify_separator',\n  item = 'contexify_item',\n  itemDisabled = 'contexify_item-disabled',\n  itemContent = 'contexify_itemContent',\n  itemClickedFeedback = 'contexify_item-feedback',\n  theme = 'contexify_theme-',\n  animationWillEnter = 'contexify_willEnter-',\n  animationWillLeave = 'contexify_willLeave-',\n}\n\nexport const enum EVENT {\n  HIDE_ALL,\n}\n\nexport const NOOP = () => {};\n\nexport const hideOnEvents: (keyof GlobalEventHandlersEventMap)[] = [\n  'resize',\n  'contextmenu',\n  'click',\n  'scroll',\n\n  // comment blur in dev so you can toggle console without closing the menu\n  'blur',\n];\n","import { eventManager } from './eventManager';\nimport { MenuId, TriggerEvent } from '../types';\nimport { SyntheticEvent } from 'react';\n\nimport { EVENT } from '../constants';\n\nexport interface ContextMenu {\n  show: <TProps>(params: ShowContextMenuParams<TProps>) => void;\n  hideAll: () => void;\n}\n\nexport interface ShowContextMenuParams<TProps = unknown> {\n  id: MenuId;\n  event: TriggerEvent;\n  props?: TProps;\n  position?: {\n    x: number;\n    y: number;\n  } | null;\n}\n\nconst contextMenu: ContextMenu = {\n  show({ event, id, props, position }) {\n    if (event.preventDefault) event.preventDefault();\n\n    eventManager.emit(EVENT.HIDE_ALL).emit(id, {\n      event: (event as SyntheticEvent).nativeEvent || event,\n      props,\n      position,\n    });\n  },\n  hideAll() {\n    eventManager.emit(EVENT.HIDE_ALL);\n  },\n};\n\nexport { contextMenu };\n","import { contextMenu, ShowContextMenuParams } from '../core';\nimport { MenuId } from '../types';\n\nexport interface UseContextMenuParams<TProps = unknown> {\n  id: MenuId;\n  props?: TProps;\n}\n\ntype MakeOptional<Type, Key extends keyof Type> = Omit<Type, Key> &\n  Partial<Pick<Type, Key>>;\n\nexport function useContextMenu<TProps>(\n  params: UseContextMenuParams<TProps>\n): {\n  show: (params: MakeOptional<ShowContextMenuParams, 'id'>) => void;\n  hideAll: () => void;\n};\n\nexport function useContextMenu<TProps>(\n  params?: Partial<UseContextMenuParams<TProps>>\n): {\n  show: (params: ShowContextMenuParams) => void;\n  hideAll: () => void;\n};\n\nexport function useContextMenu(\n  props?: UseContextMenuParams | Partial<UseContextMenuParams>\n) {\n  return {\n    show(params: ShowContextMenuParams) {\n      contextMenu.show({\n        ...props,\n        ...params,\n      });\n    },\n    hideAll() {\n      contextMenu.hideAll();\n    },\n  };\n}\n","import { ItemTracker, ItemTrackerRecord } from '../hooks';\nimport { CssClass } from '../constants';\n\ninterface Menu<T = ItemTrackerRecord> {\n  items: T[];\n  isRoot: boolean;\n  focusedIndex: number;\n  parentNode: HTMLElement;\n}\n\nexport function createKeyboardController() {\n  const menuList = new Map<HTMLElement, Menu>();\n  let focusedIndex: number;\n  let parentNode: HTMLElement;\n  let isRoot: boolean;\n  let currentItems: ItemTrackerRecord[];\n  let forceCloseSubmenu = false;\n\n  function init(rootMenu: ItemTracker) {\n    currentItems = Array.from(rootMenu.values());\n    focusedIndex = -1;\n    isRoot = true;\n  }\n\n  function focusSelectedItem() {\n    currentItems[focusedIndex].node.focus();\n  }\n\n  const isSubmenuFocused = () =>\n    focusedIndex >= 0 && currentItems[focusedIndex].isSubmenu;\n\n  const getSubmenuItems = () =>\n    Array.from(currentItems[focusedIndex].submenuRefTracker!.values());\n\n  function isFocused() {\n    if (focusedIndex === -1) {\n      // focus first item\n      moveDown();\n      return false;\n    }\n\n    return true;\n  }\n\n  function moveDown() {\n    if (focusedIndex + 1 < currentItems.length) {\n      focusedIndex++;\n    } else if (focusedIndex + 1 === currentItems.length) {\n      focusedIndex = 0;\n    }\n\n    if (forceCloseSubmenu) closeSubmenu();\n\n    focusSelectedItem();\n  }\n\n  function moveUp() {\n    if (focusedIndex === -1 || focusedIndex === 0) {\n      focusedIndex = currentItems.length - 1;\n    } else if (focusedIndex - 1 < currentItems.length) {\n      focusedIndex--;\n    }\n\n    if (forceCloseSubmenu) closeSubmenu();\n\n    focusSelectedItem();\n  }\n\n  function openSubmenu() {\n    if (isFocused() && isSubmenuFocused()) {\n      const submenuItems = getSubmenuItems();\n      const { node, setSubmenuPosition } = currentItems[focusedIndex];\n\n      menuList.set(node, {\n        isRoot,\n        focusedIndex,\n        parentNode: parentNode || node,\n        items: currentItems,\n      });\n\n      setSubmenuPosition!();\n      node.classList.add(CssClass.submenuOpen);\n      parentNode = node;\n\n      if (submenuItems.length > 0) {\n        focusedIndex = 0;\n        currentItems = submenuItems;\n      } else {\n        forceCloseSubmenu = true;\n      }\n\n      isRoot = false;\n\n      focusSelectedItem();\n      return true;\n    }\n    return false;\n  }\n\n  function closeSubmenu() {\n    if (isFocused() && !isRoot) {\n      const parent = menuList.get(parentNode)!;\n\n      parentNode!.classList.remove(CssClass.submenuOpen);\n      currentItems = parent.items;\n      parentNode = parent.parentNode;\n\n      if (parent.isRoot) {\n        isRoot = true;\n        menuList.clear();\n      }\n\n      if (!forceCloseSubmenu) {\n        focusedIndex = parent.focusedIndex;\n        focusSelectedItem();\n      }\n    }\n  }\n\n  function matchKeys(e: KeyboardEvent) {\n    // matches shortcut inside submenu as well even when submenu is not open\n    // it matches native menu behavior\n    function walkAndMatch(items: ItemTrackerRecord[]) {\n      for (const item of items) {\n        if (item.isSubmenu && item.submenuRefTracker)\n          walkAndMatch(Array.from(item.submenuRefTracker.values()));\n\n        item.keyMatcher && item.keyMatcher(e);\n      }\n    }\n    walkAndMatch(currentItems);\n  }\n\n  return {\n    init,\n    moveDown,\n    moveUp,\n    openSubmenu,\n    closeSubmenu,\n    matchKeys,\n  };\n}\n","import { Children, cloneElement, ReactNode, ReactElement } from 'react';\n\nimport { BooleanPredicate, PredicateParams, TriggerEvent } from '../types';\n\nexport function isFn(v: any): v is Function {\n  return typeof v === 'function';\n}\n\nexport function isStr(v: any): v is String {\n  return typeof v === 'string';\n}\n\nexport function cloneItems(\n  children: ReactNode,\n  props: { triggerEvent: TriggerEvent; propsFromTrigger?: object }\n) {\n  return Children.map(\n    // remove null item\n    Children.toArray(children).filter(Boolean),\n    (item) => cloneElement(item as ReactElement<any>, props)\n  );\n}\n\nexport function getMousePosition(e: TriggerEvent) {\n  const pos = {\n    x: (e as MouseEvent).clientX,\n    y: (e as MouseEvent).clientY,\n  };\n\n  const touch = (e as TouchEvent).changedTouches;\n\n  if (touch) {\n    pos.x = touch[0].clientX;\n    pos.y = touch[0].clientY;\n  }\n\n  if (!pos.x || pos.x < 0) pos.x = 0;\n\n  if (!pos.y || pos.y < 0) pos.y = 0;\n\n  return pos;\n}\n\nexport function getPredicateValue(\n  predicate: BooleanPredicate,\n  payload: PredicateParams\n) {\n  return isFn(predicate) ? predicate(payload) : predicate;\n}\n","import React, { ReactNode, useRef } from 'react';\nimport cx from 'clsx';\n\nimport {\n  ItemParams,\n  InternalProps,\n  BooleanPredicate,\n  HandlerParamsEvent,\n  BuiltInOrString,\n} from '../types';\nimport { useItemTrackerContext } from './ItemTrackerProvider';\nimport { NOOP, CssClass } from '../constants';\nimport { getPredicateValue, isFn } from './utils';\nimport { contextMenu } from '../core';\n\nexport interface ItemProps\n  extends InternalProps,\n    Omit<React.HTMLAttributes<HTMLElement>, 'hidden' | 'disabled' | 'onClick'> {\n  /**\n   * Any valid node that can be rendered\n   */\n  children: ReactNode;\n\n  /**\n   * Passed to the `Item` onClick callback. Accessible via `data`\n   */\n  data?: any;\n\n  /**\n   * Disable `Item`. If a function is used, a boolean must be returned\n   *\n   * @param id The item id, when defined\n   * @param props The props passed when you called `show(e, {props: yourProps})`\n   * @param data The data defined on the `Item`\n   * @param triggerEvent The event that triggered the context menu\n   *\n   *\n   * ```\n   * function isItemDisabled({ triggerEvent, props, data }: PredicateParams<type of props, type of data>): boolean\n   * <Item disabled={isItemDisabled} data={data}>content</Item>\n   * ```\n   */\n  disabled?: BooleanPredicate;\n\n  /**\n   * Hide the `Item`. If a function is used, a boolean must be returned\n   *\n   * @param id The item id, when defined\n   * @param props The props passed when you called `show(e, {props: yourProps})`\n   * @param data The data defined on the `Item`\n   * @param triggerEvent The event that triggered the context menu\n   *\n   *\n   * ```\n   * function isItemHidden({ triggerEvent, props, data }: PredicateParams<type of props, type of data>): boolean\n   * <Item hidden={isItemHidden} data={data}>content</Item>\n   * ```\n   */\n  hidden?: BooleanPredicate;\n\n  /**\n   * Callback when the `Item` is clicked.\n   *\n   * @param id The item id, when defined\n   * @param event The event that occured on the Item node\n   * @param props The props passed when you called `show(e, {props: yourProps})`\n   * @param data The data defined on the `Item`\n   * @param triggerEvent The event that triggered the context menu\n   *\n   * ```\n   * function handleItemClick({ id, triggerEvent, event, props, data }: ItemParams<type of props, type of data>){\n   *    // retrieve the id of the Item\n   *    console.log(id) // item-id\n   *\n   *    // access any other dom attribute\n   *    console.log(event.currentTarget.dataset.foo) // 123\n   *\n   *    // access the props and the data\n   *    console.log(props, data);\n   *\n   *    // access the coordinate of the mouse when the menu has been displayed\n   *    const {  clientX, clientY } = triggerEvent;\n   * }\n   *\n   * <Item id=\"item-id\" onClick={handleItemClick} data={{key: 'value'}} data-foo={123} >Something</Item>\n   * ```\n   */\n  onClick?: (args: ItemParams) => void;\n\n  /**\n   * Let you implement keyboard shortcut for the menu item. It will trigger the\n   * `onClick` hander if the given callback returns `true`\n   *\n   * example:\n   *\n   * ```\n   * function handleShortcut(e: React.KeyboardEvent<HTMLElement>){\n   *   // let's say we want to match ⌘ + c\n   *   return e.metaKey && e.key === \"c\";\n   * }\n   *\n   * <Item onClick={doSomething}>Copy <RightSlot>⌘ C</RightSlot></Item>\n   * ```\n   */\n  keyMatcher?: (e: KeyboardEvent) => boolean;\n\n  /**\n   * Useful when using form input inside the Menu\n   *\n   * default: `true`\n   */\n  closeOnClick?: boolean;\n\n  /**\n   * Let you specify another event for the `onClick` handler\n   *\n   * default: `onClick`\n   */\n  handlerEvent?: BuiltInOrString<'onClick' | 'onMouseDown' | 'onMouseUp'>;\n}\n\nexport const Item: React.FC<ItemProps> = ({\n  id,\n  children,\n  className,\n  style,\n  triggerEvent,\n  data,\n  propsFromTrigger,\n  keyMatcher,\n  onClick = NOOP,\n  disabled = false,\n  hidden = false,\n  closeOnClick = true,\n  handlerEvent = 'onClick',\n  ...rest\n}) => {\n  const itemNode = useRef<HTMLElement>();\n  const itemTracker = useItemTrackerContext();\n  const handlerParams = {\n    id,\n    data,\n    triggerEvent: triggerEvent as HandlerParamsEvent,\n    props: propsFromTrigger,\n  } as ItemParams;\n  const isDisabled = getPredicateValue(disabled, handlerParams);\n  const isHidden = getPredicateValue(hidden, handlerParams);\n\n  function handleClick(e: React.MouseEvent<HTMLElement>) {\n    handlerParams.event = e;\n    e.stopPropagation();\n\n    if (!isDisabled) {\n      !closeOnClick ? onClick(handlerParams) : dispatchUserHanlder();\n    }\n  }\n\n  // provide a feedback to the user that the item has been clicked before closing the menu\n  function dispatchUserHanlder() {\n    const node = itemNode.current!;\n    node.focus();\n    node.addEventListener(\n      'animationend',\n      // defer, required for react 17\n      () => setTimeout(contextMenu.hideAll),\n      { once: true }\n    );\n    node.classList.add(CssClass.itemClickedFeedback);\n    onClick(handlerParams);\n  }\n\n  function registerItem(node: HTMLElement | null) {\n    if (node && !isDisabled) {\n      itemNode.current = node;\n      itemTracker.set(node, {\n        node,\n        isSubmenu: false,\n        keyMatcher:\n          !isDisabled &&\n          isFn(keyMatcher) &&\n          ((e: KeyboardEvent) => {\n            if (keyMatcher(e)) {\n              e.stopPropagation();\n              e.preventDefault();\n              handlerParams.event = e;\n              dispatchUserHanlder();\n            }\n          }),\n      });\n    }\n  }\n\n  function handleKeyDown(e: React.KeyboardEvent<HTMLElement>) {\n    if (e.key === 'Enter' || e.key === ' ') {\n      e.stopPropagation();\n      handlerParams.event = e;\n      dispatchUserHanlder();\n    }\n  }\n\n  if (isHidden) return null;\n\n  return (\n    <div\n      {...{ ...rest, [handlerEvent]: handleClick }}\n      className={cx(CssClass.item, className, {\n        [`${CssClass.itemDisabled}`]: isDisabled,\n      })}\n      style={style}\n      onKeyDown={handleKeyDown}\n      ref={registerItem}\n      tabIndex={-1}\n      role=\"menuitem\"\n      aria-disabled={isDisabled}\n    >\n      <div className={CssClass.itemContent}>{children}</div>\n    </div>\n  );\n};\n","import React from 'react';\n\nimport { BooleanPredicate, HandlerParamsEvent, InternalProps } from '../types';\nimport { getPredicateValue } from './utils';\n\nimport { CssClass } from '../constants';\n\nexport interface SeparatorProps extends InternalProps {\n  /**\n   * Passed to the `Separator` hidden predicate. Accessible via `data`\n   */\n  data?: any;\n\n  /**\n   * Hide the `Separator`. If a function is used, a boolean must be returned\n   *\n   * @param props The props passed when you called `show(e, {props: yourProps})`\n   * @param data The data defined on the `Separator`\n   * @param triggerEvent The event that triggered the context menu\n   *\n   *\n   * ```\n   * function isSeparatorHidden({ triggerEvent, props, data }: PredicateParams<type of props, type of data>): boolean\n   * <Separator hidden={isSeparatorHidden} data={data}/>\n   * ```\n   */\n  hidden?: BooleanPredicate;\n}\n\nexport const Separator: React.FC<SeparatorProps> = ({\n  triggerEvent,\n  data,\n  propsFromTrigger,\n  hidden = false,\n}) =>\n  getPredicateValue(hidden, {\n    data,\n    triggerEvent: triggerEvent as HandlerParamsEvent,\n    props: propsFromTrigger,\n  }) ? null : (\n    <div className={CssClass.separator} />\n  );\n","import React, { ReactNode, useRef } from 'react';\nimport cx from 'clsx';\n\nimport { InternalProps, BooleanPredicate, HandlerParamsEvent } from '../types';\nimport {\n  ItemTrackerProvider,\n  useItemTrackerContext,\n} from './ItemTrackerProvider';\nimport { useItemTracker } from '../hooks';\nimport { CssClass } from '../constants';\nimport { cloneItems, getPredicateValue } from './utils';\nimport { Arrow } from './Arrow';\nimport { RightSlot } from './RightSlot';\n\nexport interface SubMenuProps\n  extends InternalProps,\n    Omit<React.HTMLAttributes<HTMLElement>, 'hidden'> {\n  /**\n   * Any valid node that can be rendered\n   */\n  label: ReactNode;\n\n  /**\n   * Any valid node that can be rendered\n   */\n  children: ReactNode;\n\n  /**\n   * Render a custom arrow\n   */\n  arrow?: ReactNode;\n\n  /**\n   * Disable the `Submenu`. If a function is used, a boolean must be returned\n   */\n  disabled?: BooleanPredicate;\n\n  /**\n   * Hide the `Submenu` and his children. If a function is used, a boolean must be returned\n   */\n  hidden?: BooleanPredicate;\n}\n\nexport const Submenu: React.FC<SubMenuProps> = ({\n  arrow,\n  children,\n  disabled = false,\n  hidden = false,\n  label,\n  className,\n  triggerEvent,\n  propsFromTrigger,\n  style,\n  ...rest\n}) => {\n  const parentItemTracker = useItemTrackerContext();\n  const itemTracker = useItemTracker();\n  const submenuNode = useRef<HTMLDivElement>(null);\n  const handlerParams = {\n    triggerEvent: triggerEvent as HandlerParamsEvent,\n    props: propsFromTrigger,\n  };\n  const isDisabled = getPredicateValue(disabled, handlerParams);\n  const isHidden = getPredicateValue(hidden, handlerParams);\n\n  function setPosition() {\n    const node = submenuNode.current;\n    if (node) {\n      const bottom = `${CssClass.submenu}-bottom`;\n      const right = `${CssClass.submenu}-right`;\n\n      // reset to default position before computing position\n      node.classList.remove(bottom, right);\n\n      const rect = node.getBoundingClientRect();\n\n      if (rect.right > window.innerWidth) node.classList.add(right);\n\n      if (rect.bottom > window.innerHeight) node.classList.add(bottom);\n    }\n  }\n\n  function trackRef(node: HTMLElement | null) {\n    if (node && !isDisabled)\n      parentItemTracker.set(node, {\n        node,\n        isSubmenu: true,\n        submenuRefTracker: itemTracker,\n        setSubmenuPosition: setPosition,\n      });\n  }\n\n  if (isHidden) return null;\n\n  const cssClasses = cx(CssClass.item, className, {\n    [`${CssClass.itemDisabled}`]: isDisabled,\n  });\n\n  return (\n    <ItemTrackerProvider value={itemTracker}>\n      <div\n        {...rest}\n        className={cssClasses}\n        ref={trackRef}\n        tabIndex={-1}\n        role=\"menuitem\"\n        aria-haspopup\n        aria-disabled={isDisabled}\n        onMouseEnter={setPosition}\n        onTouchStart={setPosition}\n      >\n        <div\n          className={CssClass.itemContent}\n          onClick={(e) => e.stopPropagation()}\n        >\n          {label}\n          <RightSlot>{arrow || <Arrow />}</RightSlot>\n        </div>\n        <div\n          className={`${CssClass.menu} ${CssClass.submenu}`}\n          ref={submenuNode}\n          style={style}\n        >\n          {cloneItems(children, {\n            propsFromTrigger,\n            // @ts-ignore: injected by the parent\n            triggerEvent,\n          })}\n        </div>\n      </div>\n    </ItemTrackerProvider>\n  );\n};\n","import React from 'react';\n\nexport const Arrow = () => (\n  <svg\n    xmlns=\"http://www.w3.org/2000/svg\"\n    width=\"18\"\n    height=\"18\"\n    viewBox=\"0 0 24 24\"\n    fill=\"none\"\n    stroke=\"currentColor\"\n    strokeWidth=\"2\"\n    strokeLinecap=\"round\"\n    strokeLinejoin=\"round\"\n  >\n    <polyline points=\"9 18 15 12 9 6\" />\n  </svg>\n);\n","import React from 'react';\nimport cx from 'clsx';\n\nimport { CssClass } from '../constants';\n\nexport interface RightSlotProps extends React.HTMLAttributes<HTMLDivElement> {\n  children: React.ReactNode;\n}\n\nexport const RightSlot: React.FC<RightSlotProps> = ({ className, ...rest }) => (\n  <div className={cx(CssClass.rightSlot, className)} {...rest} />\n);\n"]}