PluginProbe
Gutenberg / 17.8.1
Gutenberg v17.8.1
24.1.0 24.0.0 23.9.1 23.9.0 23.8.0 23.7.2 23.7.1 23.7.0 23.6.1 23.6.2 23.6.0 23.5.3 23.5.2 23.5.1 23.5.0 23.4.0 23.3.2 23.3.1 23.3.0 23.2.0 23.2.1 23.2.2 23.1.1 23.1.0 23.0.1 All 404 releases
gutenberg / build / interactivity / navigation.js

navigation.js in Gutenberg 17.8.1, at build/interactivity/navigation.js

208 lines 7.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
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 ;// CONCATENATED MODULE: external "@wordpress/interactivity"
27 var x = y => { var x = {}; __webpack_require__.d(x, y); return x; }
28 var y = x => () => x
29 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 });
30 ;// CONCATENATED MODULE: ./packages/block-library/src/navigation/view.js
31 /**
32 * WordPress dependencies
33 */
34
35 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^="-"])'];
36
37 // This is a fix for Safari in iOS/iPadOS. Without it, Safari doesn't focus out
38 // when the user taps in the body. It can be removed once we add an overlay to
39 // capture the clicks, instead of relying on the focusout event.
40 document.addEventListener('click', () => {});
41 const {
42 state,
43 actions
44 } = (0,interactivity_namespaceObject.store)('core/navigation', {
45 state: {
46 get roleAttribute() {
47 const ctx = (0,interactivity_namespaceObject.getContext)();
48 return ctx.type === 'overlay' && state.isMenuOpen ? 'dialog' : null;
49 },
50 get ariaModal() {
51 const ctx = (0,interactivity_namespaceObject.getContext)();
52 return ctx.type === 'overlay' && state.isMenuOpen ? 'true' : null;
53 },
54 get ariaLabel() {
55 const ctx = (0,interactivity_namespaceObject.getContext)();
56 return ctx.type === 'overlay' && state.isMenuOpen ? ctx.ariaLabel : null;
57 },
58 get isMenuOpen() {
59 // The menu is opened if either `click`, `hover` or `focus` is true.
60 return Object.values(state.menuOpenedBy).filter(Boolean).length > 0;
61 },
62 get menuOpenedBy() {
63 const ctx = (0,interactivity_namespaceObject.getContext)();
64 return ctx.type === 'overlay' ? ctx.overlayOpenedBy : ctx.submenuOpenedBy;
65 }
66 },
67 actions: {
68 openMenuOnHover() {
69 const {
70 type,
71 overlayOpenedBy
72 } = (0,interactivity_namespaceObject.getContext)();
73 if (type === 'submenu' &&
74 // Only open on hover if the overlay is closed.
75 Object.values(overlayOpenedBy || {}).filter(Boolean).length === 0) actions.openMenu('hover');
76 },
77 closeMenuOnHover() {
78 actions.closeMenu('hover');
79 },
80 openMenuOnClick() {
81 const ctx = (0,interactivity_namespaceObject.getContext)();
82 const {
83 ref
84 } = (0,interactivity_namespaceObject.getElement)();
85 ctx.previousFocus = ref;
86 actions.openMenu('click');
87 },
88 closeMenuOnClick() {
89 actions.closeMenu('click');
90 actions.closeMenu('focus');
91 },
92 openMenuOnFocus() {
93 actions.openMenu('focus');
94 },
95 toggleMenuOnClick() {
96 const ctx = (0,interactivity_namespaceObject.getContext)();
97 const {
98 ref
99 } = (0,interactivity_namespaceObject.getElement)();
100 // 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
101 if (window.document.activeElement !== ref) ref.focus();
102 const {
103 menuOpenedBy
104 } = state;
105 if (menuOpenedBy.click || menuOpenedBy.focus) {
106 actions.closeMenu('click');
107 actions.closeMenu('focus');
108 } else {
109 ctx.previousFocus = ref;
110 actions.openMenu('click');
111 }
112 },
113 handleMenuKeydown(event) {
114 const {
115 type,
116 firstFocusableElement,
117 lastFocusableElement
118 } = (0,interactivity_namespaceObject.getContext)();
119 if (state.menuOpenedBy.click) {
120 // If Escape close the menu.
121 if (event?.key === 'Escape') {
122 actions.closeMenu('click');
123 actions.closeMenu('focus');
124 return;
125 }
126
127 // Trap focus if it is an overlay (main menu).
128 if (type === 'overlay' && event.key === 'Tab') {
129 // If shift + tab it change the direction.
130 if (event.shiftKey && window.document.activeElement === firstFocusableElement) {
131 event.preventDefault();
132 lastFocusableElement.focus();
133 } else if (!event.shiftKey && window.document.activeElement === lastFocusableElement) {
134 event.preventDefault();
135 firstFocusableElement.focus();
136 }
137 }
138 }
139 },
140 handleMenuFocusout(event) {
141 const {
142 modal
143 } = (0,interactivity_namespaceObject.getContext)();
144 // If focus is outside modal, and in the document, close menu
145 // event.target === The element losing focus
146 // event.relatedTarget === The element receiving focus (if any)
147 // When focusout is outsite the document,
148 // `window.document.activeElement` doesn't change.
149
150 // The event.relatedTarget is null when something outside the navigation menu is clicked. This is only necessary for Safari.
151 if (event.relatedTarget === null || !modal?.contains(event.relatedTarget) && event.target !== window.document.activeElement) {
152 actions.closeMenu('click');
153 actions.closeMenu('focus');
154 }
155 },
156 openMenu(menuOpenedOn = 'click') {
157 const {
158 type
159 } = (0,interactivity_namespaceObject.getContext)();
160 state.menuOpenedBy[menuOpenedOn] = true;
161 if (type === 'overlay') {
162 // Add a `has-modal-open` class to the <html> root.
163 document.documentElement.classList.add('has-modal-open');
164 }
165 },
166 closeMenu(menuClosedOn = 'click') {
167 const ctx = (0,interactivity_namespaceObject.getContext)();
168 state.menuOpenedBy[menuClosedOn] = false;
169 // Check if the menu is still open or not.
170 if (!state.isMenuOpen) {
171 if (ctx.modal?.contains(window.document.activeElement)) {
172 ctx.previousFocus?.focus();
173 }
174 ctx.modal = null;
175 ctx.previousFocus = null;
176 if (ctx.type === 'overlay') {
177 document.documentElement.classList.remove('has-modal-open');
178 }
179 }
180 }
181 },
182 callbacks: {
183 initMenu() {
184 const ctx = (0,interactivity_namespaceObject.getContext)();
185 const {
186 ref
187 } = (0,interactivity_namespaceObject.getElement)();
188 if (state.isMenuOpen) {
189 const focusableElements = ref.querySelectorAll(focusableSelectors);
190 ctx.modal = ref;
191 ctx.firstFocusableElement = focusableElements[0];
192 ctx.lastFocusableElement = focusableElements[focusableElements.length - 1];
193 }
194 },
195 focusFirstElement() {
196 const {
197 ref
198 } = (0,interactivity_namespaceObject.getElement)();
199 if (state.isMenuOpen) {
200 const focusableElements = ref.querySelectorAll(focusableSelectors);
201 focusableElements?.[0]?.focus();
202 }
203 }
204 }
205 }, {
206 lock: true
207 });
208