{"version":3,"file":"MenuSubTrigger.cjs","sources":["../../src/Menu/MenuSubTrigger.vue"],"sourcesContent":["<script lang=\"ts\">\nimport type { MenuItemImplProps } from './MenuItemImpl.vue'\nimport type { Side } from './utils'\n\nexport interface MenuSubTriggerProps extends MenuItemImplProps {}\n</script>\n\n<script setup lang=\"ts\">\nimport { type ComponentPublicInstance, nextTick, onUnmounted, ref } from 'vue'\nimport MenuItemImpl from './MenuItemImpl.vue'\nimport { injectMenuContext, injectMenuRootContext } from './MenuRoot.vue'\nimport { injectMenuSubContext } from './MenuSub.vue'\nimport { injectMenuContentContext } from './MenuContentImpl.vue'\nimport { useId } from '@/shared'\nimport { SUB_OPEN_KEYS, getOpenState, isMouseEvent } from './utils'\nimport MenuAnchor from './MenuAnchor.vue'\n\nconst props = defineProps<MenuSubTriggerProps>()\n\nconst menuContext = injectMenuContext()\nconst rootContext = injectMenuRootContext()\nconst subContext = injectMenuSubContext()\nconst contentContext = injectMenuContentContext()\n\nconst openTimerRef = ref<number | null>(null)\n\nsubContext.triggerId ||= useId(undefined, 'reka-menu-sub-trigger')\n\nfunction clearOpenTimer() {\n  if (openTimerRef.value)\n    window.clearTimeout(openTimerRef.value)\n  openTimerRef.value = null\n}\n\nonUnmounted(() => {\n  clearOpenTimer()\n})\n\nfunction handlePointerMove(event: PointerEvent) {\n  if (!isMouseEvent(event))\n    return\n  const defaultPrevented = contentContext.onItemEnter(event)\n  if (defaultPrevented)\n    return\n\n  if (!props.disabled && !menuContext.open.value && !openTimerRef.value) {\n    contentContext.onPointerGraceIntentChange(null)\n    openTimerRef.value = window.setTimeout(() => {\n      menuContext.onOpenChange(true)\n      clearOpenTimer()\n    }, 100)\n  }\n}\n\nasync function handlePointerLeave(event: PointerEvent) {\n  if (!isMouseEvent(event))\n    return\n  clearOpenTimer()\n\n  const contentRect = menuContext.content.value?.getBoundingClientRect()\n  if (contentRect?.width) {\n    // TODO (Radix UI): make sure to update this when we change positioning logic\n    // https://github.com/radix-ui/primitives/blob/main/packages/react/menu/src/Menu.tsx#L1088\n    const side = menuContext.content.value?.dataset.side as Side\n\n    const rightSide = side === 'right'\n    const bleed = rightSide ? -5 : +5\n    const contentNearEdge = contentRect[rightSide ? 'left' : 'right']\n    const contentFarEdge = contentRect[rightSide ? 'right' : 'left']\n\n    contentContext.onPointerGraceIntentChange({\n      area: [\n        // Apply a bleed on clientX to ensure that our exit point is\n        // consistently within polygon bounds\n        { x: event.clientX + bleed, y: event.clientY },\n        { x: contentNearEdge, y: contentRect.top },\n        { x: contentFarEdge, y: contentRect.top },\n        { x: contentFarEdge, y: contentRect.bottom },\n        { x: contentNearEdge, y: contentRect.bottom },\n      ],\n      side,\n    })\n\n    window.clearTimeout(contentContext.pointerGraceTimerRef.value)\n    contentContext.pointerGraceTimerRef.value = window.setTimeout(\n      () => contentContext.onPointerGraceIntentChange(null),\n      300,\n    )\n  }\n  else {\n    const defaultPrevented = contentContext.onTriggerLeave(event)\n    if (defaultPrevented)\n      return\n\n    // There's 100ms where the user may leave an item before the submenu was opened.\n    contentContext.onPointerGraceIntentChange(null)\n  }\n}\n\nasync function handleKeyDown(event: KeyboardEvent) {\n  const isTypingAhead = contentContext.searchRef.value !== ''\n  if (props.disabled || (isTypingAhead && event.key === ' '))\n    return\n  if (SUB_OPEN_KEYS[rootContext.dir.value].includes(event.key)) {\n    menuContext.onOpenChange(true)\n\n    await nextTick()\n    // The trigger may hold focus if opened via pointer interaction\n    // so we ensure content is given focus again when switching to keyboard.\n    menuContext.content.value?.focus()\n    // prevent window from scrolling\n    event.preventDefault()\n  }\n}\n</script>\n\n<template>\n  <MenuAnchor as-child>\n    <MenuItemImpl\n      v-bind=\"props\"\n      :id=\"subContext.triggerId\"\n      :ref=\"\n        (vnode: ComponentPublicInstance) => {\n          // @ts-ignore\n          subContext?.onTriggerChange(vnode?.$el);\n          return undefined\n        }\n      \"\n      aria-haspopup=\"menu\"\n      :aria-expanded=\"menuContext.open.value\"\n      :aria-controls=\"subContext.contentId\"\n      :data-state=\"getOpenState(menuContext.open.value)\"\n      @click=\"\n        async (event) => {\n          if (props.disabled || event.defaultPrevented) return;\n          /**\n           * We manually focus because iOS Safari doesn't always focus on click (e.g. buttons)\n           * and we rely heavily on `onFocusOutside` for submenus to close when switching\n           * between separate submenus.\n           */\n          event.currentTarget.focus();\n          if (!menuContext.open.value) menuContext.onOpenChange(true);\n        }\n      \"\n      @pointermove=\"handlePointerMove\"\n      @pointerleave=\"handlePointerLeave\"\n      @keydown=\"handleKeyDown\"\n    >\n      <slot />\n    </MenuItemImpl>\n  </MenuAnchor>\n</template>\n"],"names":["injectMenuContext","injectMenuRootContext","injectMenuSubContext","injectMenuContentContext","ref","useId","onUnmounted","isMouseEvent","SUB_OPEN_KEYS","nextTick"],"mappings":"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"}