[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

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

   1  // packages/block-library/build-module/tabs/view.mjs
   2  import {
   3    store,
   4    getContext,
   5    getElement,
   6    withSyncEvent
   7  } from "@wordpress/interactivity";
   8  var { actions, state } = store(
   9    "core/tabs",
  10    {
  11      state: {
  12        /**
  13         * Gets a contextually aware list of tabs for the current tabs block.
  14         *
  15         * @type {Array}
  16         */
  17        get tabsList() {
  18          const context = getContext();
  19          const tabsId = context?.tabsId;
  20          const tabsList = state[tabsId];
  21          return tabsList;
  22        },
  23        /**
  24         * Gets the index of the active tab element whether it
  25         * is a tab label or tab panel.
  26         *
  27         * @type {number|null}
  28         */
  29        get tabIndex() {
  30          const { attributes } = getElement();
  31          const tabId = attributes?.id?.replace("tab__", "") || null;
  32          if (!tabId) {
  33            return null;
  34          }
  35          const { tabsList } = state;
  36          const tabIndex = tabsList.findIndex((t) => t === tabId);
  37          return tabIndex;
  38        },
  39        /**
  40         * Whether the tab panel or tab label is the active tab.
  41         *
  42         * @type {boolean}
  43         */
  44        get isActiveTab() {
  45          const { activeTabIndex } = getContext();
  46          const { tabIndex } = state;
  47          return activeTabIndex === tabIndex;
  48        },
  49        /**
  50         * The value of the tabindex attribute for tab buttons.
  51         * Only the active tab should be in the tab sequence.
  52         *
  53         * @type {number}
  54         */
  55        get tabIndexAttribute() {
  56          return state.isActiveTab ? 0 : -1;
  57        }
  58      },
  59      actions: {
  60        /**
  61         * Handles the keydown events for the tab label and tabs controller.
  62         *
  63         * @param {KeyboardEvent} event The keydown event.
  64         */
  65        handleTabKeyDown: withSyncEvent((event) => {
  66          const { tabIndex, tabsList } = state;
  67          if (tabIndex === null) {
  68            return;
  69          }
  70          if (event.key === "ArrowRight") {
  71            event.preventDefault();
  72            actions.moveFocus(tabIndex + 1);
  73          } else if (event.key === "ArrowLeft") {
  74            event.preventDefault();
  75            actions.moveFocus(tabIndex - 1);
  76          } else if (event.key === "Home") {
  77            event.preventDefault();
  78            actions.moveFocus(0);
  79          } else if (event.key === "End") {
  80            event.preventDefault();
  81            actions.moveFocus(tabsList.length - 1);
  82          }
  83        }),
  84        /**
  85         * Handles the click event for the tab label.
  86         *
  87         * @param {MouseEvent} event The click event.
  88         */
  89        handleTabClick: withSyncEvent((event) => {
  90          event.preventDefault();
  91          const { tabIndex } = state;
  92          if (tabIndex !== null) {
  93            actions.setActiveTab(tabIndex);
  94          }
  95        }),
  96        /**
  97         * Moves focus to a specific tab without activating it.
  98         *
  99         * @param {number} tabIndex The index to move focus to.
 100         */
 101        moveFocus: (tabIndex) => {
 102          const { tabsList } = state;
 103          if (!tabsList || tabsList.length === 0) {
 104            return;
 105          }
 106          let newIndex = tabIndex;
 107          if (newIndex < 0) {
 108            newIndex = tabsList.length - 1;
 109          } else if (newIndex >= tabsList.length) {
 110            newIndex = 0;
 111          }
 112          const tabId = tabsList[newIndex];
 113          const tabElement = document.getElementById("tab__" + tabId);
 114          if (tabElement) {
 115            tabElement.focus();
 116          }
 117        },
 118        /**
 119         * Sets the active tab index.
 120         *
 121         * @param {number}  tabIndex    The index of the active tab.
 122         * @param {boolean} scrollToTab Whether to scroll to the tab element.
 123         */
 124        setActiveTab: (tabIndex, scrollToTab = false) => {
 125          const { tabsList } = state;
 126          if (!tabsList || tabsList.length === 0) {
 127            return;
 128          }
 129          let newIndex = tabIndex;
 130          if (newIndex < 0) {
 131            newIndex = 0;
 132          } else if (newIndex >= tabsList.length) {
 133            newIndex = tabsList.length - 1;
 134          }
 135          const context = getContext();
 136          context.activeTabIndex = newIndex;
 137          if (scrollToTab) {
 138            const tabId = tabsList[newIndex];
 139            const tabElement = document.getElementById(tabId);
 140            if (tabElement) {
 141              setTimeout(() => {
 142                tabElement.scrollIntoView({ behavior: "smooth" });
 143              }, 100);
 144            }
 145          }
 146        }
 147      },
 148      callbacks: {
 149        /**
 150         * 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.
 151         *
 152         */
 153        onTabsInit: () => {
 154          const { tabsList } = state;
 155          if (tabsList.length === 0) {
 156            return;
 157          }
 158          const { hash } = window.location;
 159          const tabId = hash.replace("#", "");
 160          const tabIndex = tabsList.findIndex((t) => t === tabId);
 161          if (tabIndex >= 0) {
 162            actions.setActiveTab(tabIndex, true);
 163          }
 164        }
 165      }
 166    },
 167    {
 168      lock: true
 169    }
 170  );


Generated : Fri Aug 14 08:20:23 2026 Cross-referenced by PHPXref