[ 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.js
   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.
  83         *
  84         * @type {false|string}
  85         */
  86        get tabIndexAttribute() {
  87          return privateState.isActiveTab ? -1 : 0;
  88        }
  89      },
  90      actions: {
  91        /**
  92         * Handles the keydown events for the tab label and tabs controller.
  93         *
  94         * @param {KeyboardEvent} event The keydown event.
  95         */
  96        handleTabKeyDown: withSyncEvent((event) => {
  97          const { isVertical } = getContext();
  98          if (event.key === "Enter") {
  99            const { tabIndex } = privateState;
 100            if (tabIndex !== null) {
 101              privateActions.setActiveTab(tabIndex);
 102            }
 103          } else if (event.key === "ArrowRight" && !isVertical) {
 104            const { tabIndex } = privateState;
 105            if (tabIndex !== null) {
 106              privateActions.setActiveTab(tabIndex + 1);
 107            }
 108          } else if (event.key === "ArrowLeft" && !isVertical) {
 109            const { tabIndex } = privateState;
 110            if (tabIndex !== null) {
 111              privateActions.setActiveTab(tabIndex - 1);
 112            }
 113          } else if (event.key === "ArrowDown" && isVertical) {
 114            const { tabIndex } = privateState;
 115            if (tabIndex !== null) {
 116              privateActions.setActiveTab(tabIndex + 1);
 117            }
 118          } else if (event.key === "ArrowUp" && isVertical) {
 119            const { tabIndex } = privateState;
 120            if (tabIndex !== null) {
 121              privateActions.setActiveTab(tabIndex - 1);
 122            }
 123          }
 124        }),
 125        /**
 126         * Handles the click event for the tab label.
 127         *
 128         * @param {MouseEvent} event The click event.
 129         */
 130        handleTabClick: withSyncEvent((event) => {
 131          event.preventDefault();
 132          const { tabIndex } = privateState;
 133          if (tabIndex !== null) {
 134            privateActions.setActiveTab(tabIndex);
 135          }
 136        }),
 137        /**
 138         * Sets the active tab index (internal implementation).
 139         *
 140         * @param {number}  tabIndex    The index of the active tab.
 141         * @param {boolean} scrollToTab Whether to scroll to the tab element.
 142         */
 143        setActiveTab: (tabIndex, scrollToTab = false) => {
 144          const context = getContext();
 145          context.activeTabIndex = tabIndex;
 146          if (scrollToTab) {
 147            const tabId = privateState.tabsList[tabIndex].id;
 148            const tabElement = document.getElementById(tabId);
 149            if (tabElement) {
 150              setTimeout(() => {
 151                tabElement.scrollIntoView({ behavior: "smooth" });
 152              }, 100);
 153            }
 154          }
 155        }
 156      },
 157      callbacks: {
 158        /**
 159         * 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.
 160         *
 161         */
 162        onTabsInit: () => {
 163          const { tabsList } = privateState;
 164          if (tabsList.length === 0) {
 165            return;
 166          }
 167          const { hash } = window.location;
 168          const tabId = hash.replace("#", "");
 169          const tabIndex = tabsList.findIndex((t) => t.id === tabId);
 170          if (tabIndex >= 0) {
 171            privateActions.setActiveTab(tabIndex, true);
 172          }
 173        }
 174      }
 175    },
 176    {
 177      lock: true
 178    }
 179  );
 180  store("core/tabs", {
 181    state: {
 182      /**
 183       * Gets a contextually aware list of tabs for the current tabs block.
 184       * Public API for third-party access.
 185       *
 186       * @type {Array}
 187       */
 188      get tabsList() {
 189        return createReadOnlyProxy(privateState.tabsList);
 190      },
 191      /**
 192       * Gets the index of the active tab element whether it
 193       * is a tab label or tab panel.
 194       *
 195       * @type {number|null}
 196       */
 197      get tabIndex() {
 198        return privateState.tabIndex;
 199      },
 200      /**
 201       * Whether the tab panel or tab label is the active tab.
 202       *
 203       * @type {boolean}
 204       */
 205      get isActiveTab() {
 206        return privateState.isActiveTab;
 207      }
 208    },
 209    actions: {
 210      /**
 211       * Sets the active tab index.
 212       * Public API for third-party programmatic tab activation.
 213       *
 214       * @param {number}  tabIndex    The index of the active tab.
 215       * @param {boolean} scrollToTab Whether to scroll to the tab element.
 216       */
 217      setActiveTab: (tabIndex, scrollToTab = false) => {
 218        privateActions.setActiveTab(tabIndex, scrollToTab);
 219      }
 220    }
 221  });


Generated : Tue May 5 08:20:14 2026 Cross-referenced by PHPXref