wp/wp-includes/js/dist/script-modules/block-library/navigation/view.js
changeset 22 8c2e4d02f4ef
equal deleted inserted replaced
21:48c4eec2b7e6 22:8c2e4d02f4ef
       
     1 import * as __WEBPACK_EXTERNAL_MODULE__wordpress_interactivity_8e89b257__ from "@wordpress/interactivity";
       
     2 /******/ // The require scope
       
     3 /******/ var __webpack_require__ = {};
       
     4 /******/ 
       
     5 /************************************************************************/
       
     6 /******/ /* webpack/runtime/define property getters */
       
     7 /******/ (() => {
       
     8 /******/ 	// define getter functions for harmony exports
       
     9 /******/ 	__webpack_require__.d = (exports, definition) => {
       
    10 /******/ 		for(var key in definition) {
       
    11 /******/ 			if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
       
    12 /******/ 				Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
       
    13 /******/ 			}
       
    14 /******/ 		}
       
    15 /******/ 	};
       
    16 /******/ })();
       
    17 /******/ 
       
    18 /******/ /* webpack/runtime/hasOwnProperty shorthand */
       
    19 /******/ (() => {
       
    20 /******/ 	__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
       
    21 /******/ })();
       
    22 /******/ 
       
    23 /************************************************************************/
       
    24 var __webpack_exports__ = {};
       
    25 
       
    26 ;// external "@wordpress/interactivity"
       
    27 var x = (y) => {
       
    28 	var x = {}; __webpack_require__.d(x, y); return x
       
    29 } 
       
    30 var y = (x) => (() => (x))
       
    31 const interactivity_namespaceObject = x({ ["getContext"]: () => (__WEBPACK_EXTERNAL_MODULE__wordpress_interactivity_8e89b257__.getContext), ["getElement"]: () => (__WEBPACK_EXTERNAL_MODULE__wordpress_interactivity_8e89b257__.getElement), ["store"]: () => (__WEBPACK_EXTERNAL_MODULE__wordpress_interactivity_8e89b257__.store), ["withSyncEvent"]: () => (__WEBPACK_EXTERNAL_MODULE__wordpress_interactivity_8e89b257__.withSyncEvent) });
       
    32 ;// ./node_modules/@wordpress/block-library/build-module/navigation/view.js
       
    33 /**
       
    34  * WordPress dependencies
       
    35  */
       
    36 
       
    37 const focusableSelectors = ['a[href]', 'input:not([disabled]):not([type="hidden"]):not([aria-hidden])', 'select:not([disabled]):not([aria-hidden])', 'textarea:not([disabled]):not([aria-hidden])', 'button:not([disabled]):not([aria-hidden])', '[contenteditable]', '[tabindex]:not([tabindex^="-"])'];
       
    38 
       
    39 // This is a fix for Safari in iOS/iPadOS. Without it, Safari doesn't focus out
       
    40 // when the user taps in the body. It can be removed once we add an overlay to
       
    41 // capture the clicks, instead of relying on the focusout event.
       
    42 document.addEventListener('click', () => {});
       
    43 const {
       
    44   state,
       
    45   actions
       
    46 } = (0,interactivity_namespaceObject.store)('core/navigation', {
       
    47   state: {
       
    48     get roleAttribute() {
       
    49       const ctx = (0,interactivity_namespaceObject.getContext)();
       
    50       return ctx.type === 'overlay' && state.isMenuOpen ? 'dialog' : null;
       
    51     },
       
    52     get ariaModal() {
       
    53       const ctx = (0,interactivity_namespaceObject.getContext)();
       
    54       return ctx.type === 'overlay' && state.isMenuOpen ? 'true' : null;
       
    55     },
       
    56     get ariaLabel() {
       
    57       const ctx = (0,interactivity_namespaceObject.getContext)();
       
    58       return ctx.type === 'overlay' && state.isMenuOpen ? ctx.ariaLabel : null;
       
    59     },
       
    60     get isMenuOpen() {
       
    61       // The menu is opened if either `click`, `hover` or `focus` is true.
       
    62       return Object.values(state.menuOpenedBy).filter(Boolean).length > 0;
       
    63     },
       
    64     get menuOpenedBy() {
       
    65       const ctx = (0,interactivity_namespaceObject.getContext)();
       
    66       return ctx.type === 'overlay' ? ctx.overlayOpenedBy : ctx.submenuOpenedBy;
       
    67     }
       
    68   },
       
    69   actions: {
       
    70     openMenuOnHover() {
       
    71       const {
       
    72         type,
       
    73         overlayOpenedBy
       
    74       } = (0,interactivity_namespaceObject.getContext)();
       
    75       if (type === 'submenu' &&
       
    76       // Only open on hover if the overlay is closed.
       
    77       Object.values(overlayOpenedBy || {}).filter(Boolean).length === 0) {
       
    78         actions.openMenu('hover');
       
    79       }
       
    80     },
       
    81     closeMenuOnHover() {
       
    82       const {
       
    83         type,
       
    84         overlayOpenedBy
       
    85       } = (0,interactivity_namespaceObject.getContext)();
       
    86       if (type === 'submenu' &&
       
    87       // Only close on hover if the overlay is closed.
       
    88       Object.values(overlayOpenedBy || {}).filter(Boolean).length === 0) {
       
    89         actions.closeMenu('hover');
       
    90       }
       
    91     },
       
    92     openMenuOnClick() {
       
    93       const ctx = (0,interactivity_namespaceObject.getContext)();
       
    94       const {
       
    95         ref
       
    96       } = (0,interactivity_namespaceObject.getElement)();
       
    97       ctx.previousFocus = ref;
       
    98       actions.openMenu('click');
       
    99     },
       
   100     closeMenuOnClick() {
       
   101       actions.closeMenu('click');
       
   102       actions.closeMenu('focus');
       
   103     },
       
   104     openMenuOnFocus() {
       
   105       actions.openMenu('focus');
       
   106     },
       
   107     toggleMenuOnClick() {
       
   108       const ctx = (0,interactivity_namespaceObject.getContext)();
       
   109       const {
       
   110         ref
       
   111       } = (0,interactivity_namespaceObject.getElement)();
       
   112       // Safari won't send focus to the clicked element, so we need to manually place it: https://bugs.webkit.org/show_bug.cgi?id=22261
       
   113       if (window.document.activeElement !== ref) {
       
   114         ref.focus();
       
   115       }
       
   116       const {
       
   117         menuOpenedBy
       
   118       } = state;
       
   119       if (menuOpenedBy.click || menuOpenedBy.focus) {
       
   120         actions.closeMenu('click');
       
   121         actions.closeMenu('focus');
       
   122       } else {
       
   123         ctx.previousFocus = ref;
       
   124         actions.openMenu('click');
       
   125       }
       
   126     },
       
   127     handleMenuKeydown: (0,interactivity_namespaceObject.withSyncEvent)(event => {
       
   128       const {
       
   129         type,
       
   130         firstFocusableElement,
       
   131         lastFocusableElement
       
   132       } = (0,interactivity_namespaceObject.getContext)();
       
   133       if (state.menuOpenedBy.click) {
       
   134         // If Escape close the menu.
       
   135         if (event?.key === 'Escape') {
       
   136           actions.closeMenu('click');
       
   137           actions.closeMenu('focus');
       
   138           return;
       
   139         }
       
   140 
       
   141         // Trap focus if it is an overlay (main menu).
       
   142         if (type === 'overlay' && event.key === 'Tab') {
       
   143           // If shift + tab it change the direction.
       
   144           if (event.shiftKey && window.document.activeElement === firstFocusableElement) {
       
   145             event.preventDefault();
       
   146             lastFocusableElement.focus();
       
   147           } else if (!event.shiftKey && window.document.activeElement === lastFocusableElement) {
       
   148             event.preventDefault();
       
   149             firstFocusableElement.focus();
       
   150           }
       
   151         }
       
   152       }
       
   153     }),
       
   154     handleMenuFocusout(event) {
       
   155       const {
       
   156         modal,
       
   157         type
       
   158       } = (0,interactivity_namespaceObject.getContext)();
       
   159       // If focus is outside modal, and in the document, close menu
       
   160       // event.target === The element losing focus
       
   161       // event.relatedTarget === The element receiving focus (if any)
       
   162       // When focusout is outside the document,
       
   163       // `window.document.activeElement` doesn't change.
       
   164 
       
   165       // The event.relatedTarget is null when something outside the navigation menu is clicked. This is only necessary for Safari.
       
   166       if (event.relatedTarget === null || !modal?.contains(event.relatedTarget) && event.target !== window.document.activeElement && type === 'submenu') {
       
   167         actions.closeMenu('click');
       
   168         actions.closeMenu('focus');
       
   169       }
       
   170     },
       
   171     openMenu(menuOpenedOn = 'click') {
       
   172       const {
       
   173         type
       
   174       } = (0,interactivity_namespaceObject.getContext)();
       
   175       state.menuOpenedBy[menuOpenedOn] = true;
       
   176       if (type === 'overlay') {
       
   177         // Add a `has-modal-open` class to the <html> root.
       
   178         document.documentElement.classList.add('has-modal-open');
       
   179       }
       
   180     },
       
   181     closeMenu(menuClosedOn = 'click') {
       
   182       const ctx = (0,interactivity_namespaceObject.getContext)();
       
   183       state.menuOpenedBy[menuClosedOn] = false;
       
   184       // Check if the menu is still open or not.
       
   185       if (!state.isMenuOpen) {
       
   186         if (ctx.modal?.contains(window.document.activeElement)) {
       
   187           ctx.previousFocus?.focus();
       
   188         }
       
   189         ctx.modal = null;
       
   190         ctx.previousFocus = null;
       
   191         if (ctx.type === 'overlay') {
       
   192           document.documentElement.classList.remove('has-modal-open');
       
   193         }
       
   194       }
       
   195     }
       
   196   },
       
   197   callbacks: {
       
   198     initMenu() {
       
   199       const ctx = (0,interactivity_namespaceObject.getContext)();
       
   200       const {
       
   201         ref
       
   202       } = (0,interactivity_namespaceObject.getElement)();
       
   203       if (state.isMenuOpen) {
       
   204         const focusableElements = ref.querySelectorAll(focusableSelectors);
       
   205         ctx.modal = ref;
       
   206         ctx.firstFocusableElement = focusableElements[0];
       
   207         ctx.lastFocusableElement = focusableElements[focusableElements.length - 1];
       
   208       }
       
   209     },
       
   210     focusFirstElement() {
       
   211       const {
       
   212         ref
       
   213       } = (0,interactivity_namespaceObject.getElement)();
       
   214       if (state.isMenuOpen) {
       
   215         const focusableElements = ref.querySelectorAll(focusableSelectors);
       
   216         focusableElements?.[0]?.focus();
       
   217       }
       
   218     }
       
   219   }
       
   220 }, {
       
   221   lock: true
       
   222 });
       
   223