/home/vianto5/heredit.mx/wp-content/plugins/code-snippets/js/components/common
NameSizeModeActions
cloud/-0755rm
icons/-0755rm
ListTable/-0755rm
snippets/-0755rm
Badge.tsx8600644editdlrm
Button.tsx9290644editdlrm
ConfirmDialog.tsx10590644editdlrm
CopyToClipboardButton.tsx23400644editdlrm
KebabMenu.tsx61940644editdlrm
LoadingStatusNotices.tsx9430644editdlrm
Notice.tsx13540644editdlrm
ScreenMetaSlot.tsx12900644editdlrm
SnippetViewToggle.tsx14650644editdlrm
SubmitButton.tsx9820644editdlrm
SubnavTabs.tsx22540644editdlrm
Toolbar.tsx52110644editdlrm
Tooltip.tsx14280644editdlrm
TooltipButton.tsx8540644editdlrm
UpsellBanner.tsx13370644editdlrm
UpsellDialog.tsx24200644editdlrm
Edit: /home/vianto5/heredit.mx/wp-content/plugins/code-snippets/js/components/common/KebabMenu.tsx (6194B)
import classnames from 'classnames' import React, { createContext, useCallback, useContext, useEffect, useId, useLayoutEffect, useRef, useState } from 'react' import { KebabIcon } from './icons/KebabIcon' import type { Dispatch, PropsWithChildren, ReactNode, RefObject, SetStateAction } from 'react' const FOCUSABLE_SELECTOR = [ 'button:not(:disabled)', '[href]', 'input:not(:disabled)', 'select:not(:disabled)', 'textarea:not(:disabled)', '[tabindex]:not([tabindex="-1"])' ].join(', ') interface KebabMenuContextValue { closeMenu: VoidFunction } const KebabMenuContext = createContext({ closeMenu: () => undefined }) export const useKebabMenu = (): KebabMenuContextValue => useContext(KebabMenuContext) export interface KebabMenuItemProps { onSelect?: VoidFunction destructive?: boolean disabled?: boolean className?: string } export const KebabMenuItem: React.FC> = ({ onSelect, destructive, disabled, className, children }) => { const { closeMenu } = useKebabMenu() return (
  • ) } export const KebabMenuDivider: React.FC = () =>
  • {children}
  • interface PopoverBehaviourOptions { isOpen: boolean setIsOpen: Dispatch> closeMenu: VoidFunction containerRef: RefObject triggerRef: RefObject popoverRef: RefObject } const usePopoverPlacement = ({ isOpen, triggerRef, popoverRef }: PopoverBehaviourOptions): boolean => { const [isFlipped, setIsFlipped] = useState(false) useLayoutEffect(() => { if (isOpen && popoverRef.current) { const popover = popoverRef.current.getBoundingClientRect() const trigger = triggerRef.current?.getBoundingClientRect() setIsFlipped(popover.bottom > window.innerHeight && (trigger?.top ?? 0) > popover.height) const firstItem = popoverRef.current.querySelector('button:not(:disabled)') ;(firstItem ?? popoverRef.current).focus() } else { setIsFlipped(false) } }, [isOpen, triggerRef, popoverRef]) return isFlipped } const handlePopoverKeyDown = ( event: KeyboardEvent, { closeMenu, popoverRef }: Pick ) => { if ('Escape' === event.key) { event.preventDefault() closeMenu() return } if (!popoverRef.current) { return } const active = document.activeElement const isFormInput = active instanceof HTMLElement && (active.isContentEditable || active.matches('input, select, textarea')) if (isFormInput) { return } const focusable = Array.from(popoverRef.current.querySelectorAll(FOCUSABLE_SELECTOR)) const currentIndex = active instanceof HTMLElement ? focusable.indexOf(active) : -1 if (0 < focusable.length && ['ArrowDown', 'ArrowUp', 'Home', 'End'].includes(event.key)) { event.preventDefault() const getTarget = () => { switch (event.key) { case 'Home': return 0 case 'End': return focusable.length - 1 default: { const offset = currentIndex + ('ArrowDown' === event.key ? 1 : -1) return (offset + focusable.length) % focusable.length } } } focusable[getTarget()].focus() } } const usePopoverDismissal = ({ isOpen, setIsOpen, closeMenu, containerRef, popoverRef }: PopoverBehaviourOptions) => { useEffect(() => { if (!isOpen) { return } const handlePointerDown = (event: MouseEvent) => { if (event.target instanceof Node && !containerRef.current?.contains(event.target)) { setIsOpen(false) } } const handleFocusIn = (event: FocusEvent) => { if (event.target instanceof Node && !containerRef.current?.contains(event.target)) { setIsOpen(false) } } const handleKeyDown = (event: KeyboardEvent) => handlePopoverKeyDown(event, { closeMenu, popoverRef }) document.addEventListener('mousedown', handlePointerDown) document.addEventListener('focusin', handleFocusIn) document.addEventListener('keydown', handleKeyDown) return () => { document.removeEventListener('mousedown', handlePointerDown) document.removeEventListener('focusin', handleFocusIn) document.removeEventListener('keydown', handleKeyDown) } }, [isOpen, setIsOpen, closeMenu, containerRef, popoverRef]) } export interface KebabMenuProps { label: string className?: string children: ReactNode } export const KebabMenu: React.FC = ({ label, className, children }) => { const [isOpen, setIsOpen] = useState(false) const containerRef = useRef(null) const triggerRef = useRef(null) const popoverRef = useRef(null) const menuId = useId() const closeMenu = useCallback(() => { setIsOpen(false) triggerRef.current?.focus() }, []) const behaviourOptions = { isOpen, setIsOpen, closeMenu, containerRef, triggerRef, popoverRef } const isFlipped = usePopoverPlacement(behaviourOptions) usePopoverDismissal(behaviourOptions) return (
    {isOpen ?
      {children}
    : null}
    ) }