| [ Index ] |
PHP Cross Reference of WordPress Trunk (Updated Daily) |
[Summary view] [Print] [Text view]
1 // packages/block-library/build-module/tabs/view.mjs 2 import { 3 store, 4 getContext, 5 getElement, 6 withSyncEvent 7 } from "@wordpress/interactivity"; 8 function createReadOnlyProxy(obj) { 9 const arrayMutationMethods = /* @__PURE__ */ new Set([ 10 "push", 11 "pop", 12 "shift", 13 "unshift", 14 "splice", 15 "sort", 16 "reverse", 17 "copyWithin", 18 "fill" 19 ]); 20 return new Proxy(obj, { 21 get(target, prop) { 22 if (Array.isArray(target) && arrayMutationMethods.has(prop)) { 23 return () => { 24 }; 25 } 26 const value = target[prop]; 27 if (typeof value === "object" && value !== null) { 28 return createReadOnlyProxy(value); 29 } 30 return value; 31 }, 32 set() { 33 return false; 34 }, 35 deleteProperty() { 36 return false; 37 } 38 }); 39 } 40 var { actions: privateActions, state: privateState } = store( 41 "core/tabs/private", 42 { 43 state: { 44 /** 45 * Gets a contextually aware list of tabs for the current tabs block. 46 * 47 * @type {Array} 48 */ 49 get tabsList() { 50 const context = getContext(); 51 const tabsId = context?.tabsId; 52 const tabsList = privateState[tabsId]; 53 return tabsList; 54 }, 55 /** 56 * Gets the index of the active tab element whether it 57 * is a tab label or tab panel. 58 * 59 * @type {number|null} 60 */ 61 get tabIndex() { 62 const { attributes } = getElement(); 63 const tabId = attributes?.id?.replace("tab__", "") || null; 64 if (!tabId) { 65 return null; 66 } 67 const { tabsList } = privateState; 68 const tabIndex = tabsList.findIndex((t) => t.id === tabId); 69 return tabIndex; 70 }, 71 /** 72 * Whether the tab panel or tab label is the active tab. 73 * 74 * @type {boolean} 75 */ 76 get isActiveTab() { 77 const { activeTabIndex } = getContext(); 78 const { tabIndex } = privateState; 79 return activeTabIndex === tabIndex; 80 }, 81 /** 82 * The value of the tabindex attribute for tab buttons. 83 * Only the active tab should be in the tab sequence. 84 * 85 * @type {number} 86 */ 87 get tabIndexAttribute() { 88 return privateState.isActiveTab ? 0 : -1; 89 } 90 }, 91 actions: { 92 /** 93 * Handles the keydown events for the tab label and tabs controller. 94 * 95 * @param {KeyboardEvent} event The keydown event. 96 */ 97 handleTabKeyDown: withSyncEvent((event) => { 98 const context = getContext(); 99 const { isVertical } = context; 100 const { tabIndex } = privateState; 101 if (tabIndex === null) { 102 return; 103 } 104 if (event.key === "ArrowRight" && !isVertical) { 105 event.preventDefault(); 106 privateActions.moveFocus(tabIndex + 1); 107 } else if (event.key === "ArrowLeft" && !isVertical) { 108 event.preventDefault(); 109 privateActions.moveFocus(tabIndex - 1); 110 } else if (event.key === "ArrowDown" && isVertical) { 111 event.preventDefault(); 112 privateActions.moveFocus(tabIndex + 1); 113 } else if (event.key === "ArrowUp" && isVertical) { 114 event.preventDefault(); 115 privateActions.moveFocus(tabIndex - 1); 116 } 117 }), 118 /** 119 * Handles the click event for the tab label. 120 * 121 * @param {MouseEvent} event The click event. 122 */ 123 handleTabClick: withSyncEvent((event) => { 124 event.preventDefault(); 125 const { tabIndex } = privateState; 126 if (tabIndex !== null) { 127 privateActions.setActiveTab(tabIndex); 128 } 129 }), 130 /** 131 * Moves focus to a specific tab without activating it. 132 * 133 * @param {number} tabIndex The index to move focus to. 134 */ 135 moveFocus: (tabIndex) => { 136 const { tabsList } = privateState; 137 if (!tabsList || tabsList.length === 0) { 138 return; 139 } 140 let newIndex = tabIndex; 141 if (newIndex < 0) { 142 newIndex = tabsList.length - 1; 143 } else if (newIndex >= tabsList.length) { 144 newIndex = 0; 145 } 146 const tabId = tabsList[newIndex].id; 147 const tabElement = document.getElementById("tab__" + tabId); 148 if (tabElement) { 149 tabElement.focus(); 150 } 151 }, 152 /** 153 * Sets the active tab index (internal implementation). 154 * 155 * @param {number} tabIndex The index of the active tab. 156 * @param {boolean} scrollToTab Whether to scroll to the tab element. 157 */ 158 setActiveTab: (tabIndex, scrollToTab = false) => { 159 const { tabsList } = privateState; 160 if (!tabsList || tabsList.length === 0) { 161 return; 162 } 163 let newIndex = tabIndex; 164 if (newIndex < 0) { 165 newIndex = 0; 166 } else if (newIndex >= tabsList.length) { 167 newIndex = tabsList.length - 1; 168 } 169 const context = getContext(); 170 context.activeTabIndex = newIndex; 171 if (scrollToTab) { 172 const tabId = tabsList[newIndex].id; 173 const tabElement = document.getElementById(tabId); 174 if (tabElement) { 175 setTimeout(() => { 176 tabElement.scrollIntoView({ behavior: "smooth" }); 177 }, 100); 178 } 179 } 180 } 181 }, 182 callbacks: { 183 /** 184 * When the tabs are initialized, we need to check if there is a hash in the url and if so if it exists in the current tabsList, set the active tab to that index. 185 * 186 */ 187 onTabsInit: () => { 188 const { tabsList } = privateState; 189 if (tabsList.length === 0) { 190 return; 191 } 192 const { hash } = window.location; 193 const tabId = hash.replace("#", ""); 194 const tabIndex = tabsList.findIndex((t) => t.id === tabId); 195 if (tabIndex >= 0) { 196 privateActions.setActiveTab(tabIndex, true); 197 } 198 } 199 } 200 }, 201 { 202 lock: true 203 } 204 ); 205 store("core/tabs", { 206 state: { 207 /** 208 * Gets a contextually aware list of tabs for the current tabs block. 209 * Public API for third-party access. 210 * 211 * @type {Array} 212 */ 213 get tabsList() { 214 return createReadOnlyProxy(privateState.tabsList); 215 }, 216 /** 217 * Gets the index of the active tab element whether it 218 * is a tab label or tab panel. 219 * 220 * @type {number|null} 221 */ 222 get tabIndex() { 223 return privateState.tabIndex; 224 }, 225 /** 226 * Whether the tab panel or tab label is the active tab. 227 * 228 * @type {boolean} 229 */ 230 get isActiveTab() { 231 return privateState.isActiveTab; 232 } 233 }, 234 actions: { 235 /** 236 * Sets the active tab index. 237 * Public API for third-party programmatic tab activation. 238 * 239 * @param {number} tabIndex The index of the active tab. 240 * @param {boolean} scrollToTab Whether to scroll to the tab element. 241 */ 242 setActiveTab: (tabIndex, scrollToTab = false) => { 243 privateActions.setActiveTab(tabIndex, scrollToTab); 244 } 245 } 246 });
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated : Mon Jun 15 08:20:09 2026 | Cross-referenced by PHPXref |