[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

/wp-includes/js/dist/script-modules/block-library/navigation/ -> view.js (source)

   1  // packages/block-library/build-module/navigation/view.mjs
   2  import {
   3    store,
   4    getContext,
   5    getElement,
   6    withSyncEvent
   7  } from "@wordpress/interactivity";
   8  var focusableSelectors = [
   9    "a[href]",
  10    'input:not([disabled]):not([type="hidden"]):not([aria-hidden])',
  11    "select:not([disabled]):not([aria-hidden])",
  12    "textarea:not([disabled]):not([aria-hidden])",
  13    "button:not([disabled]):not([aria-hidden])",
  14    "[contenteditable]",
  15    '[tabindex]:not([tabindex^="-"])'
  16  ];
  17  function getFocusableElements(ref) {
  18    const focusableElements = ref.querySelectorAll(focusableSelectors);
  19    return Array.from(focusableElements).filter((element) => {
  20      if (typeof element.checkVisibility === "function") {
  21        return element.checkVisibility({
  22          checkOpacity: false,
  23          checkVisibilityCSS: true
  24        });
  25      }
  26      return element.offsetParent !== null;
  27    });
  28  }
  29  document.addEventListener("click", () => {
  30  });
  31  var { state, actions } = store(
  32    "core/navigation",
  33    {
  34      state: {
  35        get roleAttribute() {
  36          const ctx = getContext();
  37          return ctx.type === "overlay" && state.isMenuOpen ? "dialog" : null;
  38        },
  39        get ariaModal() {
  40          const ctx = getContext();
  41          return ctx.type === "overlay" && state.isMenuOpen ? "true" : null;
  42        },
  43        get ariaLabel() {
  44          const ctx = getContext();
  45          return ctx.type === "overlay" && state.isMenuOpen ? ctx.ariaLabel : null;
  46        },
  47        get isMenuOpen() {
  48          return Object.values(state.menuOpenedBy).filter(Boolean).length > 0;
  49        },
  50        get menuOpenedBy() {
  51          const ctx = getContext();
  52          return ctx.type === "overlay" ? ctx.overlayOpenedBy : ctx.submenuOpenedBy;
  53        }
  54      },
  55      actions: {
  56        openMenuOnHover(event) {
  57          if (event?.pointerType === "touch") {
  58            return;
  59          }
  60          const { type, overlayOpenedBy } = getContext();
  61          if (type === "submenu" && // Only open on hover if the overlay is closed.
  62          Object.values(overlayOpenedBy || {}).filter(Boolean).length === 0) {
  63            actions.openMenu("hover");
  64          }
  65        },
  66        closeMenuOnHover(event) {
  67          if (event?.pointerType === "touch") {
  68            return;
  69          }
  70          const { type, overlayOpenedBy } = getContext();
  71          if (type === "submenu" && // Only close on hover if the overlay is closed.
  72          Object.values(overlayOpenedBy || {}).filter(Boolean).length === 0) {
  73            actions.closeMenu("hover");
  74          }
  75        },
  76        openMenuOnClick() {
  77          const ctx = getContext();
  78          const { ref } = getElement();
  79          ctx.previousFocus = ref;
  80          actions.openMenu("click");
  81        },
  82        closeMenuOnClick() {
  83          actions.closeMenu("click");
  84          actions.closeMenu("focus");
  85        },
  86        openMenuOnFocus() {
  87          actions.openMenu("focus");
  88        },
  89        toggleMenuOnClick() {
  90          const ctx = getContext();
  91          const { ref } = getElement();
  92          if (window.document.activeElement !== ref) {
  93            ref.focus();
  94          }
  95          const { menuOpenedBy } = state;
  96          if (menuOpenedBy.click || menuOpenedBy.focus) {
  97            actions.closeMenu("click");
  98            actions.closeMenu("focus");
  99            actions.closeMenu("hover");
 100          } else {
 101            ctx.previousFocus = ref;
 102            actions.openMenu("click");
 103          }
 104        },
 105        handleMenuKeydown: withSyncEvent((event) => {
 106          const { type, firstFocusableElement, lastFocusableElement } = getContext();
 107          if (state.menuOpenedBy.click) {
 108            if (event.key === "Escape") {
 109              event.stopPropagation();
 110              actions.closeMenu("click");
 111              actions.closeMenu("focus");
 112              return;
 113            }
 114            if (type === "overlay" && event.key === "Tab") {
 115              if (event.shiftKey && window.document.activeElement === firstFocusableElement) {
 116                event.preventDefault();
 117                lastFocusableElement.focus();
 118              } else if (!event.shiftKey && window.document.activeElement === lastFocusableElement) {
 119                event.preventDefault();
 120                firstFocusableElement.focus();
 121              }
 122            }
 123          }
 124        }),
 125        handleMenuFocusout: withSyncEvent((event) => {
 126          const { modal, type } = getContext();
 127          if (event.relatedTarget === null || !modal?.contains(event.relatedTarget) && event.target !== window.document.activeElement && type === "submenu") {
 128            actions.closeMenu("click");
 129            actions.closeMenu("focus");
 130          }
 131        }),
 132        openMenu(menuOpenedOn = "click") {
 133          const { type } = getContext();
 134          state.menuOpenedBy[menuOpenedOn] = true;
 135          if (type === "overlay") {
 136            document.documentElement.classList.add("has-modal-open");
 137          }
 138        },
 139        closeMenu(menuClosedOn = "click") {
 140          const ctx = getContext();
 141          state.menuOpenedBy[menuClosedOn] = false;
 142          if (!state.isMenuOpen) {
 143            if (ctx.modal?.contains(window.document.activeElement)) {
 144              ctx.previousFocus?.focus();
 145            }
 146            ctx.modal = null;
 147            ctx.previousFocus = null;
 148            if (ctx.type === "overlay") {
 149              document.documentElement.classList.remove(
 150                "has-modal-open"
 151              );
 152            }
 153          }
 154        }
 155      },
 156      callbacks: {
 157        initMenu() {
 158          const ctx = getContext();
 159          const { ref } = getElement();
 160          if (state.isMenuOpen) {
 161            const focusableElements = getFocusableElements(ref);
 162            ctx.modal = ref;
 163            ctx.firstFocusableElement = focusableElements[0];
 164            ctx.lastFocusableElement = focusableElements[focusableElements.length - 1];
 165          }
 166        },
 167        focusFirstElement() {
 168          const { ref } = getElement();
 169          if (state.isMenuOpen) {
 170            const focusableElements = getFocusableElements(ref);
 171            focusableElements?.[0]?.focus();
 172          }
 173        }
 174      }
 175    },
 176    { lock: true }
 177  );


Generated : Sat Jun 20 08:20:11 2026 Cross-referenced by PHPXref