{"version":3,"sources":["../src/menu-item.tsx"],"sourcesContent":["import type { CSSUIObject, FC, HTMLUIProps } from \"@yamada-ui/core\"\nimport type {\n  KeyboardEvent,\n  KeyboardEventHandler,\n  MouseEvent,\n  ReactElement,\n} from \"react\"\nimport { forwardRef, ui } from \"@yamada-ui/core\"\nimport { useClickable } from \"@yamada-ui/use-clickable\"\nimport {\n  cx,\n  dataAttr,\n  funcAll,\n  handlerAll,\n  isActiveElement,\n  isHTMLElement,\n  mergeRefs,\n  useUpdateEffect,\n} from \"@yamada-ui/utils\"\nimport { useCallback, useId, useRef, useState } from \"react\"\nimport {\n  UpstreamMenuItemProvider,\n  useMenu,\n  useMenuDescendant,\n  useUpstreamMenuItem,\n} from \"./menu-context\"\n\nconst isTargetMenuItem = (target: EventTarget | null) => {\n  return (\n    isHTMLElement(target) &&\n    !!target.getAttribute(\"role\")?.startsWith(\"menuitem\")\n  )\n}\n\ninterface MenuItemOptions {\n  /**\n   * If `true`, the list element will be closed when selected.\n   *\n   * @default false\n   */\n  closeOnSelect?: boolean\n  /**\n   * Right-aligned label text content, useful for displaying hotkeys.\n   */\n  command?: string\n  /**\n   * If `true`, the menu item will be disabled.\n   *\n   * @default false\n   */\n  disabled?: boolean\n  /**\n   * If `true`, the menu item will be focusable.\n   *\n   * @default false\n   */\n  focusable?: boolean\n  /**\n   * The menu item icon to use.\n   */\n  icon?: ReactElement\n  /**\n   * If `true`, the menu item will be disabled.\n   *\n   * @default false\n   *\n   * @deprecated Use `disabled` instead.\n   */\n  isDisabled?: boolean\n  /**\n   * If `true`, the menu item will be focusable.\n   *\n   * @default false\n   *\n   * @deprecated Use `focusable` instead.\n   */\n  isFocusable?: boolean\n}\n\nexport interface MenuItemProps extends HTMLUIProps, MenuItemOptions {}\n\nexport const MenuItem = forwardRef<MenuItemProps, \"div\">(\n  (\n    {\n      id,\n      className,\n      children,\n      closeOnSelect: customCloseOnSelect,\n      command,\n      isDisabled,\n      disabled = isDisabled,\n      isFocusable,\n      focusable = isFocusable,\n      icon,\n      ...props\n    },\n    ref,\n  ) => {\n    const {\n      closeOnSelect,\n      focusedIndex,\n      menuRef,\n      nested,\n      open,\n      requestAnimationFrameId,\n      setFocusedIndex,\n      styles,\n      onClose,\n      onUpstreamClose,\n    } = useMenu()\n    const { onUpstreamRestoreFocus } = useUpstreamMenuItem() ?? {}\n    const [downstreamOpen, setDownstreamOpen] = useState<boolean>(false)\n    const uuid = useId()\n    const itemRef = useRef<HTMLDivElement>(null)\n    const hasDownstreamRef = useRef<boolean>(false)\n    const onKeyDownRef = useRef<KeyboardEventHandler<HTMLDivElement>>(\n      () => void 0,\n    )\n    const trulyDisabled = disabled && !focusable\n    const type = itemRef.current?.getAttribute(\"type\")\n    const role = !!type\n      ? type === \"checkbox\"\n        ? \"menuitemcheckbox\"\n        : \"menuitemradio\"\n      : \"menuitem\"\n    const { index, register } = useMenuDescendant({ disabled: trulyDisabled })\n    const focused = index === focusedIndex\n    const css: CSSUIObject = {\n      alignItems: \"center\",\n      color: \"inherit\",\n      display: \"flex\",\n      flex: \"0 0 auto\",\n      gap: \"0.75rem\",\n      outline: 0,\n      textAlign: \"start\",\n      textDecoration: \"none\",\n      userSelect: \"none\",\n      width: \"100%\",\n      ...styles.item,\n    }\n\n    id ??= uuid\n\n    const onMouseOver = useCallback(() => {\n      if (disabled) return\n\n      setFocusedIndex(index)\n    }, [index, disabled, setFocusedIndex])\n\n    const onMouseLeave = useCallback(() => {\n      if (disabled) return\n\n      setFocusedIndex(-1)\n    }, [setFocusedIndex, disabled])\n\n    const onClick = useCallback(\n      (ev: MouseEvent<HTMLDivElement>) => {\n        if (!isTargetMenuItem(ev.currentTarget)) return\n\n        const hasDownstream = hasDownstreamRef.current\n\n        if (customCloseOnSelect ?? (!hasDownstream && closeOnSelect)) {\n          onClose()\n          onUpstreamClose?.()\n        }\n      },\n      [customCloseOnSelect, closeOnSelect, onClose, onUpstreamClose],\n    )\n\n    const onFocus = useCallback(() => {\n      setFocusedIndex(index)\n    }, [setFocusedIndex, index])\n\n    const onRestoreFocus = useCallback(() => {\n      itemRef.current?.focus()\n\n      setFocusedIndex(index)\n    }, [setFocusedIndex, index])\n\n    const onKeyDown = useCallback(\n      (ev: KeyboardEvent<HTMLDivElement>) => {\n        if (ev.key === \" \") ev.key = ev.code\n\n        const actions: { [key: string]: Function | undefined } = {\n          ArrowLeft: nested\n            ? funcAll(onUpstreamRestoreFocus, onClose)\n            : undefined,\n          Space: !hasDownstreamRef.current\n            ? funcAll(onUpstreamClose, onClose)\n            : undefined,\n        }\n\n        const action = actions[ev.key]\n\n        if (!action) return\n\n        ev.preventDefault()\n        ev.stopPropagation()\n\n        action()\n      },\n      [nested, onUpstreamRestoreFocus, onClose, onUpstreamClose],\n    )\n\n    const rest = useClickable<HTMLDivElement>({\n      clickOnSpace: false,\n      focusOnClick: false,\n      ...props,\n      ref: mergeRefs(register, itemRef, ref),\n      disabled,\n      focusable,\n      onClick: handlerAll(props.onClick, onClick),\n      onFocus: handlerAll(props.onFocus, onFocus),\n      onKeyDown: handlerAll(props.onKeyDown, onKeyDown, onKeyDownRef.current),\n      onMouseLeave: handlerAll(props.onMouseLeave, onMouseLeave),\n      onMouseOver: handlerAll(props.onMouseOver, onMouseOver),\n    })\n\n    useUpdateEffect(() => {\n      if (!open) return\n\n      const id = requestAnimationFrameId.current\n\n      if (focused && !trulyDisabled && itemRef.current) {\n        if (id) cancelAnimationFrame(id)\n\n        requestAnimationFrameId.current = requestAnimationFrame(() => {\n          itemRef.current?.focus({ preventScroll: true })\n\n          requestAnimationFrameId.current = null\n        })\n      } else if (menuRef.current && !isActiveElement(menuRef.current)) {\n        menuRef.current.focus({ preventScroll: true })\n      }\n\n      return () => {\n        if (id) cancelAnimationFrame(id)\n      }\n    }, [focused, trulyDisabled, menuRef, open])\n\n    children =\n      icon || command ? (\n        <ui.span style={{ flex: 1 }}>{children}</ui.span>\n      ) : (\n        children\n      )\n\n    return (\n      <UpstreamMenuItemProvider\n        value={{\n          hasDownstreamRef,\n          setDownstreamOpen,\n          onKeyDownRef,\n          onUpstreamRestoreFocus: onRestoreFocus,\n        }}\n      >\n        <ui.div\n          id={id}\n          className={cx(\"ui-menu__item\", className)}\n          data-focus={dataAttr(downstreamOpen)}\n          __css={css}\n          {...rest}\n          role={role}\n          tabIndex={!downstreamOpen && focused ? 0 : -1}\n        >\n          {icon ? <MenuIcon>{icon}</MenuIcon> : null}\n          {children}\n          {command ? <MenuCommand>{command}</MenuCommand> : null}\n        </ui.div>\n      </UpstreamMenuItemProvider>\n    )\n  },\n)\n\nMenuItem.displayName = \"MenuItem\"\nMenuItem.__ui__ = \"MenuItem\"\n\ninterface MenuOptionItemOptions {\n  /**\n   * The type of the menu option item.\n   */\n  type?: \"checkbox\" | \"radio\"\n  /**\n   * If `true`, the checkbox or radio will be checked.\n   *\n   * @default false\n   */\n  checked?: boolean\n  /**\n   * The menu option item icon to use.\n   */\n  icon?: null | ReactElement\n  /**\n   * If `true`, the checkbox or radio will be checked.\n   *\n   * @default false\n   *\n   * @deprecated Use `checked` instead.\n   */\n  isChecked?: boolean\n  /**\n   * The value of the menu option item.\n   */\n  value?: string\n}\n\nexport interface MenuOptionItemProps\n  extends Omit<MenuItemProps, \"command\" | \"icon\" | \"value\">,\n    MenuOptionItemOptions {}\n\nexport const MenuOptionItem = forwardRef<MenuOptionItemProps, \"button\">(\n  (\n    {\n      className,\n      isChecked,\n      checked = isChecked,\n      children,\n      closeOnSelect = false,\n      icon,\n      ...rest\n    },\n    ref,\n  ) => {\n    return (\n      <MenuItem\n        ref={ref}\n        className={cx(\"ui-menu__item--option\", className)}\n        aria-checked={checked}\n        closeOnSelect={closeOnSelect}\n        {...rest}\n      >\n        {icon !== null ? (\n          <MenuIcon opacity={checked ? 1 : 0}>{icon || <CheckIcon />}</MenuIcon>\n        ) : null}\n        {children}\n      </MenuItem>\n    )\n  },\n)\n\nMenuOptionItem.displayName = \"MenuOptionItem\"\nMenuOptionItem.__ui__ = \"MenuOptionItem\"\n\nexport interface MenuIconProps extends HTMLUIProps<\"span\"> {}\n\nexport const MenuIcon = forwardRef<MenuIconProps, \"span\">(\n  ({ className, ...rest }, ref) => {\n    const { styles } = useMenu()\n\n    const css: CSSUIObject = {\n      alignItems: \"center\",\n      display: \"inline-flex\",\n      flexShrink: 0,\n      fontSize: \"0.85em\",\n      justifyContent: \"center\",\n      ...styles.icon,\n    }\n\n    return (\n      <ui.span\n        ref={ref}\n        className={cx(\"ui-menu__item__icon\", className)}\n        aria-hidden\n        __css={css}\n        {...rest}\n      />\n    )\n  },\n)\n\nMenuIcon.displayName = \"MenuIcon\"\nMenuIcon.__ui__ = \"MenuIcon\"\n\nexport interface MenuCommandProps extends HTMLUIProps<\"span\"> {}\n\nexport const MenuCommand = forwardRef<MenuCommandProps, \"span\">(\n  ({ className, ...rest }, ref) => {\n    const { styles } = useMenu()\n\n    const css: CSSUIObject = { ...styles.command }\n\n    return (\n      <ui.span\n        ref={ref}\n        className={cx(\"ui-menu__item__command\", className)}\n        __css={css}\n        {...rest}\n      />\n    )\n  },\n)\n\nMenuCommand.displayName = \"MenuCommand\"\nMenuCommand.__ui__ = \"MenuCommand\"\n\nconst CheckIcon: FC = () => (\n  <svg height=\"1em\" viewBox=\"0 0 14 14\" width=\"1em\">\n    <polygon\n      fill=\"currentColor\"\n      points=\"5.5 11.9993304 14 3.49933039 12.5 2 5.5 8.99933039 1.5 4.9968652 0 6.49933039\"\n    />\n  </svg>\n)\n"],"mappings":"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","names":["_a","id"]}