@wordpress/block-library
Version:
Block library for the WordPress editor.
8 lines (7 loc) • 11.7 kB
Source Map (JSON)
{
"version": 3,
"sources": ["../../src/navigation/view.js"],
"sourcesContent": ["/**\n * WordPress dependencies\n */\nimport {\n\tstore,\n\tgetContext,\n\tgetElement,\n\twithSyncEvent,\n} from '@wordpress/interactivity';\n\nconst focusableSelectors = [\n\t'a[href]',\n\t'input:not([disabled]):not([type=\"hidden\"]):not([aria-hidden])',\n\t'select:not([disabled]):not([aria-hidden])',\n\t'textarea:not([disabled]):not([aria-hidden])',\n\t'button:not([disabled]):not([aria-hidden])',\n\t'[contenteditable]',\n\t'[tabindex]:not([tabindex^=\"-\"])',\n];\n\n/**\n * Gets all visible focusable elements within a container.\n * Filters out elements that are hidden.\n *\n * @param {HTMLElement} ref - The container element to search within\n * @return {HTMLElement[]} Array of visible focusable elements\n */\nfunction getFocusableElements( ref ) {\n\tconst focusableElements = ref.querySelectorAll( focusableSelectors );\n\treturn Array.from( focusableElements ).filter( ( element ) => {\n\t\t// Use modern checkVisibility API if available (Chrome 105+, Firefox 106+, Safari 17.4+)\n\t\tif ( typeof element.checkVisibility === 'function' ) {\n\t\t\treturn element.checkVisibility( {\n\t\t\t\tcheckOpacity: false,\n\t\t\t\tcheckVisibilityCSS: true,\n\t\t\t} );\n\t\t}\n\t\t// Fallback for older browsers\n\t\treturn element.offsetParent !== null;\n\t} );\n}\n\n// This is a fix for Safari in iOS/iPadOS. Without it, Safari doesn't focus out\n// when the user taps in the body. It can be removed once we add an overlay to\n// capture the clicks, instead of relying on the focusout event.\ndocument.addEventListener( 'click', () => {} );\n\nconst { state, actions } = store(\n\t'core/navigation',\n\t{\n\t\tstate: {\n\t\t\tget roleAttribute() {\n\t\t\t\tconst ctx = getContext();\n\t\t\t\treturn ctx.type === 'overlay' && state.isMenuOpen\n\t\t\t\t\t? 'dialog'\n\t\t\t\t\t: null;\n\t\t\t},\n\t\t\tget ariaModal() {\n\t\t\t\tconst ctx = getContext();\n\t\t\t\treturn ctx.type === 'overlay' && state.isMenuOpen\n\t\t\t\t\t? 'true'\n\t\t\t\t\t: null;\n\t\t\t},\n\t\t\tget ariaLabel() {\n\t\t\t\tconst ctx = getContext();\n\t\t\t\treturn ctx.type === 'overlay' && state.isMenuOpen\n\t\t\t\t\t? ctx.ariaLabel\n\t\t\t\t\t: null;\n\t\t\t},\n\t\t\tget isMenuOpen() {\n\t\t\t\t// The menu is opened if either `click`, `hover` or `focus` is true.\n\t\t\t\treturn (\n\t\t\t\t\tObject.values( state.menuOpenedBy ).filter( Boolean )\n\t\t\t\t\t\t.length > 0\n\t\t\t\t);\n\t\t\t},\n\t\t\tget menuOpenedBy() {\n\t\t\t\tconst ctx = getContext();\n\t\t\t\treturn ctx.type === 'overlay'\n\t\t\t\t\t? ctx.overlayOpenedBy\n\t\t\t\t\t: ctx.submenuOpenedBy;\n\t\t\t},\n\t\t},\n\t\tactions: {\n\t\t\topenMenuOnHover() {\n\t\t\t\tconst { type, overlayOpenedBy } = getContext();\n\t\t\t\tif (\n\t\t\t\t\ttype === 'submenu' &&\n\t\t\t\t\t// Only open on hover if the overlay is closed.\n\t\t\t\t\tObject.values( overlayOpenedBy || {} ).filter( Boolean )\n\t\t\t\t\t\t.length === 0\n\t\t\t\t) {\n\t\t\t\t\tactions.openMenu( 'hover' );\n\t\t\t\t}\n\t\t\t},\n\t\t\tcloseMenuOnHover() {\n\t\t\t\tconst { type, overlayOpenedBy } = getContext();\n\t\t\t\tif (\n\t\t\t\t\ttype === 'submenu' &&\n\t\t\t\t\t// Only close on hover if the overlay is closed.\n\t\t\t\t\tObject.values( overlayOpenedBy || {} ).filter( Boolean )\n\t\t\t\t\t\t.length === 0\n\t\t\t\t) {\n\t\t\t\t\tactions.closeMenu( 'hover' );\n\t\t\t\t}\n\t\t\t},\n\t\t\topenMenuOnClick() {\n\t\t\t\tconst ctx = getContext();\n\t\t\t\tconst { ref } = getElement();\n\t\t\t\tctx.previousFocus = ref;\n\t\t\t\tactions.openMenu( 'click' );\n\t\t\t},\n\t\t\tcloseMenuOnClick() {\n\t\t\t\tactions.closeMenu( 'click' );\n\t\t\t\tactions.closeMenu( 'focus' );\n\t\t\t},\n\t\t\topenMenuOnFocus() {\n\t\t\t\tactions.openMenu( 'focus' );\n\t\t\t},\n\t\t\ttoggleMenuOnClick() {\n\t\t\t\tconst ctx = getContext();\n\t\t\t\tconst { ref } = getElement();\n\t\t\t\t// 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\n\t\t\t\tif ( window.document.activeElement !== ref ) {\n\t\t\t\t\tref.focus();\n\t\t\t\t}\n\t\t\t\tconst { menuOpenedBy } = state;\n\t\t\t\tif ( menuOpenedBy.click || menuOpenedBy.focus ) {\n\t\t\t\t\tactions.closeMenu( 'click' );\n\t\t\t\t\tactions.closeMenu( 'focus' );\n\t\t\t\t} else {\n\t\t\t\t\tctx.previousFocus = ref;\n\t\t\t\t\tactions.openMenu( 'click' );\n\t\t\t\t}\n\t\t\t},\n\t\t\thandleMenuKeydown: withSyncEvent( ( event ) => {\n\t\t\t\tconst { type, firstFocusableElement, lastFocusableElement } =\n\t\t\t\t\tgetContext();\n\t\t\t\tif ( state.menuOpenedBy.click ) {\n\t\t\t\t\t// If Escape close the menu.\n\t\t\t\t\tif ( event.key === 'Escape' ) {\n\t\t\t\t\t\tevent.stopPropagation(); // Keeps ancestor menus open.\n\t\t\t\t\t\tactions.closeMenu( 'click' );\n\t\t\t\t\t\tactions.closeMenu( 'focus' );\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Trap focus if it is an overlay (main menu).\n\t\t\t\t\tif ( type === 'overlay' && event.key === 'Tab' ) {\n\t\t\t\t\t\t// If shift + tab it change the direction.\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tevent.shiftKey &&\n\t\t\t\t\t\t\twindow.document.activeElement ===\n\t\t\t\t\t\t\t\tfirstFocusableElement\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\tlastFocusableElement.focus();\n\t\t\t\t\t\t} else if (\n\t\t\t\t\t\t\t! event.shiftKey &&\n\t\t\t\t\t\t\twindow.document.activeElement ===\n\t\t\t\t\t\t\t\tlastFocusableElement\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\tfirstFocusableElement.focus();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} ),\n\t\t\thandleMenuFocusout: withSyncEvent( ( event ) => {\n\t\t\t\tconst { modal, type } = getContext();\n\t\t\t\t// If focus is outside modal, and in the document, close menu\n\t\t\t\t// event.target === The element losing focus\n\t\t\t\t// event.relatedTarget === The element receiving focus (if any)\n\t\t\t\t// When focusout is outside the document,\n\t\t\t\t// `window.document.activeElement` doesn't change.\n\n\t\t\t\t// The event.relatedTarget is null when something outside the navigation menu is clicked. This is only necessary for Safari.\n\t\t\t\tif (\n\t\t\t\t\tevent.relatedTarget === null ||\n\t\t\t\t\t( ! modal?.contains( event.relatedTarget ) &&\n\t\t\t\t\t\tevent.target !== window.document.activeElement &&\n\t\t\t\t\t\ttype === 'submenu' )\n\t\t\t\t) {\n\t\t\t\t\tactions.closeMenu( 'click' );\n\t\t\t\t\tactions.closeMenu( 'focus' );\n\t\t\t\t}\n\t\t\t} ),\n\n\t\t\topenMenu( menuOpenedOn = 'click' ) {\n\t\t\t\tconst { type } = getContext();\n\t\t\t\tstate.menuOpenedBy[ menuOpenedOn ] = true;\n\t\t\t\tif ( type === 'overlay' ) {\n\t\t\t\t\t// Add a `has-modal-open` class to the <html> root.\n\t\t\t\t\tdocument.documentElement.classList.add( 'has-modal-open' );\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tcloseMenu( menuClosedOn = 'click' ) {\n\t\t\t\tconst ctx = getContext();\n\t\t\t\tstate.menuOpenedBy[ menuClosedOn ] = false;\n\t\t\t\t// Check if the menu is still open or not.\n\t\t\t\tif ( ! state.isMenuOpen ) {\n\t\t\t\t\tif (\n\t\t\t\t\t\tctx.modal?.contains( window.document.activeElement )\n\t\t\t\t\t) {\n\t\t\t\t\t\tctx.previousFocus?.focus();\n\t\t\t\t\t}\n\t\t\t\t\tctx.modal = null;\n\t\t\t\t\tctx.previousFocus = null;\n\t\t\t\t\tif ( ctx.type === 'overlay' ) {\n\t\t\t\t\t\tdocument.documentElement.classList.remove(\n\t\t\t\t\t\t\t'has-modal-open'\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t\tcallbacks: {\n\t\t\tinitMenu() {\n\t\t\t\tconst ctx = getContext();\n\t\t\t\tconst { ref } = getElement();\n\t\t\t\tif ( state.isMenuOpen ) {\n\t\t\t\t\tconst focusableElements = getFocusableElements( ref );\n\t\t\t\t\tctx.modal = ref;\n\t\t\t\t\tctx.firstFocusableElement = focusableElements[ 0 ];\n\t\t\t\t\tctx.lastFocusableElement =\n\t\t\t\t\t\tfocusableElements[ focusableElements.length - 1 ];\n\t\t\t\t}\n\t\t\t},\n\t\t\tfocusFirstElement() {\n\t\t\t\tconst { ref } = getElement();\n\t\t\t\tif ( state.isMenuOpen ) {\n\t\t\t\t\tconst focusableElements = getFocusableElements( ref );\n\t\t\t\t\tfocusableElements?.[ 0 ]?.focus();\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t},\n\t{ lock: true }\n);\n"],
"mappings": "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",
"names": []
}