> For the complete documentation index, see [llms.txt](https://design-with-cracka.gitbook.io/etchmegamenupro/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://design-with-cracka.gitbook.io/etchmegamenupro/javascript-api.md).

# JavaScript API

The script exposes two globals: `window.dwcMegaMenu` (the live instance) and `window.DwcConfig` (configuration). Advanced users can call instance methods to control the menu programmatically, watch CSS class changes to react to menu state, and listen to the custom events the script dispatches.

> **Important:** `window.DwcConfig` must be defined *before* the mega menu script loads. Methods on `window.dwcMegaMenu` are available after `DOMContentLoaded`.

Lite has the same API, except the parts marked **Full only**.

***

## Global Configuration

### `window.DwcConfig.MegaMenu`

Define this object before the script loads to override any default:

```js
window.DwcConfig = window.DwcConfig || {};
window.DwcConfig.MegaMenu = {
  minWidth: 1025,
  closeNavOnClick: 1,
  // ... other overrides
};
```

| Key                       | Type                 | Default                     | Description                                                                                                                                                                                                                                                                                                        |
| ------------------------- | -------------------- | --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `minWidth`                | `number`             | `1201`                      | Viewport width (px) at which desktop mode begins. Below this value is mobile. Overridden per-nav by `data-mobile-breakpoint`. Changing `minWidth` after page load has no effect on the stylesheet's media queries — use `data-mobile-breakpoint` and reset the stylesheet guard instead (see `destroy()` example). |
| `headerSelector`          | `string`             | `'#dwc-header'`             | CSS selector for the header element.                                                                                                                                                                                                                                                                               |
| `nestMenuSelector`        | `string`             | `'.dwc-nest-menu'`          | CSS selector for the nav wrapper.                                                                                                                                                                                                                                                                                  |
| `menuAutoExpansion`       | `boolean`            | `true`                      | **Full only.** Auto-expand the first level on mobile open.                                                                                                                                                                                                                                                         |
| `swipeToClose`            | `boolean`            | `true`                      | **Full only.** Enable swipe-left gesture to close mobile menu.                                                                                                                                                                                                                                                     |
| `toolTip`                 | `boolean`            | `true`                      | **Full only.** Show drill-down tooltips on mobile.                                                                                                                                                                                                                                                                 |
| `adaptiveHeight`          | `0\|1`               | `0`                         | **Full only.** Animate dropdown height when content changes. Overridden per-nav by `data-adaptive-height`.                                                                                                                                                                                                         |
| `stripeStyle`             | `0\|1`               | `0`                         | **Full only.** Apply stripe styling across header rows. Overridden per-nav by `data-stripe-style`.                                                                                                                                                                                                                 |
| `toggleLabelWidth`        | `0\|1`               | `1`                         | Equalise open/close toggle label widths to prevent layout shift.                                                                                                                                                                                                                                                   |
| `closeNavOnClick`         | `0\|1`               | `1`                         | Close the menu when a nav link is clicked.                                                                                                                                                                                                                                                                         |
| `closeOnHashClickOnly`    | `0\|1`               | `0`                         | Only close the menu when a hash (`#`) link is clicked.                                                                                                                                                                                                                                                             |
| `closeOnMobileOnly`       | `0\|1`               | `0`                         | Restrict click-to-close behaviour to mobile viewports.                                                                                                                                                                                                                                                             |
| `closeNavOnClickExclude`  | `string`             | `'.js-wpml-ls-item-toggle'` | Selector for links that should not trigger close-on-click.                                                                                                                                                                                                                                                         |
| `breakinToNavList`        | `0\|1`               | `0`                         | **Full only.** Place `data-breakin` items inside the nav `<ul>` instead of the nav wrapper.                                                                                                                                                                                                                        |
| `shiftFactor`             | `number`             | `1.05`                      | Multiplier used when shifting dropdowns to avoid viewport overflow.                                                                                                                                                                                                                                                |
| `minOverflow`             | `number`             | `20`                        | Minimum pixel overflow before a dropdown is repositioned.                                                                                                                                                                                                                                                          |
| `viewportGutter`          | `number`             | `25`                        | Minimum gap (px) between a dropdown edge and the viewport edge.                                                                                                                                                                                                                                                    |
| `reinitializeOnURLchange` | `boolean`            | `false`                     | Re-initialise automatically on SPA URL changes via the History API.                                                                                                                                                                                                                                                |
| `overlayInsideHeader`     | `0\|1`               | `0`                         | Render the dropdown overlay inside the header element instead of `<body>`.                                                                                                                                                                                                                                         |
| `resetNavOnBreakpoint`    | `boolean`            | `true`                      | Reset open/active states when crossing the desktop/mobile breakpoint.                                                                                                                                                                                                                                              |
| `backButtonStyle`         | `'title'\|'back-to'` | `'back-to'`                 | Mobile drill-down back button label. `'title'` shows the parent name; `'back-to'` shows "Back to \[Parent]".                                                                                                                                                                                                       |
| `propagateVariables`      | `array`              | *(see source)*              | CSS variables to copy from scoped elements to `:root`. Useful for elements outside the nav that need nav-scoped variables.                                                                                                                                                                                         |

### `window.DwcConfig.CenteredLogo`

**Full only.**

| Key                 | Type                | Default   | Description                                                                                                    |
| ------------------- | ------------------- | --------- | -------------------------------------------------------------------------------------------------------------- |
| `enable`            | `0\|1`              | `0`       | Enable the centered logo feature. Overridden per-nav by `data-centered-logo`.                                  |
| `centerGuide`       | `0\|1`              | `1`       | Show a visual center guide line (visible to logged-in admins only). Overridden per-nav by `data-center-guide`. |
| `forceCenteredLogo` | `0\|1`              | `1`       | Compensate margins to achieve pixel-perfect centering.                                                         |
| `centerNudge`       | `number`            | `0`       | Nudge the logo left (negative) or right (positive) by this many pixels.                                        |
| `allowOddItems`     | `0\|1`              | `1`       | Allow centering when the menu has an odd number of items.                                                      |
| `roundOffFactor`    | `'before'\|'after'` | `'after'` | For odd item counts, place the extra item before or after the logo.                                            |

### `window.DwcConfig.TabbedNav`

**Full only.** Options for [Tabbed Navigation](/etchmegamenupro/tabbed-navigation.md).

```js
window.DwcConfig = window.DwcConfig || {};
window.DwcConfig.TabbedNav = {
  prewarmTimeout: 3000,
};
```

| Key              | Type     | Default | Description                                                                                                         |
| ---------------- | -------- | ------- | ------------------------------------------------------------------------------------------------------------------- |
| `debounceDelay`  | `number` | `250`   | How long to wait after the window is resized before tabbed navs switch between desktop and mobile, in milliseconds. |
| `prewarmTimeout` | `number` | `1500`  | The longest wait for fonts and images before the tab area is sized to fit the tallest tab, in milliseconds.         |

***

## Public Instance Methods

All methods are on the `window.dwcMegaMenu` singleton.

### Lifecycle

#### `reinitialize()`

Tears down event listeners and re-runs setup without a page reload. Use this after dynamically injecting or removing nav elements.

```js
// After injecting new nav items via JS
document.querySelector('.dwc-nav-nested-items').appendChild(newItem);
window.dwcMegaMenu.reinitialize();
```

> **Note:** `reinitialize()` does not reset the stylesheet guard. If you are changing `data-mobile-breakpoint` at runtime and need the stylesheet's media queries updated, use the full `destroy()` pattern below instead of `reinitialize()`.

#### `destroy()`

Removes all event listeners and observers. Use this before replacing the instance with a new configuration.

```js
window.dwcMegaMenu.destroy();

// Set the new breakpoint on the nav.
// data-mobile-breakpoint takes priority over minWidth; the value is the last
// mobile px (desktop starts at value + 1). _resolveDataAttributes() derives
// minWidth from this automatically on reinitialise.
document.querySelector('.dwc-nest-menu').setAttribute('data-mobile-breakpoint', '1024');

// Reset the stylesheet guard so the media queries are rewritten on reinitialise.
// Without this, the one-time guard in _updateMobileStylesBreakpoint() prevents
// the stylesheet from being updated again.
const styleTag = document.querySelector('style[id^="etch-dwc-mega-menu"]');
if (styleTag) delete styleTag.dataset.breakpointModified;

window.dwcMegaMenu = new window.DWCMegaMenuPro().initialize();
```

***

### Viewport Detection

These return `boolean` and can be called at any time.

| Method                 | Returns `true` when…                              |
| ---------------------- | ------------------------------------------------- |
| `isDesktop()`          | Viewport ≥ `minWidth`                             |
| `isMobile()`           | Viewport < `minWidth`                             |
| `isEffectiveDesktop()` | Desktop viewport AND offcanvas mode is not active |
| `isEffectiveMobile()`  | Mobile viewport OR offcanvas mode is active       |
| `isRTL()`              | `<html dir="rtl">` is set                         |

```js
if (window.dwcMegaMenu.isEffectiveMobile()) {
  // Runs on mobile AND when offcanvas mode forces mobile behaviour on desktop
}

if (window.dwcMegaMenu.isRTL()) {
  // Flip custom icons, adjust third-party tooltips, etc.
}
```

***

### Dropdown Control

The `dropdown` argument is the nav `<li>` element that wraps both the toggle and its dropdown panel (i.e. a `<li.dwce-dropdown>` inside `.dwc-nav-nested-items`).

#### `openDropdown(dropdown, manual?)`

```js
const item = document.querySelector('.dwc-nav-nested-items > .dwce-dropdown:first-child');
window.dwcMegaMenu.openDropdown(item);
```

Pass `true` as the second argument to flag the open as a manual/programmatic trigger (bypasses hover-intent logic).

#### `closeDropdown(dropdown)`

```js
window.dwcMegaMenu.closeDropdown(item);
```

#### `toggleDropdown(dropdown, manual?)`

```js
// Wire a custom button to toggle a specific nav item.
// Target the <li.dwce-dropdown> by the text on its toggle button's data-text attribute.
document.querySelector('#my-trigger').addEventListener('click', () => {
  const item = document.querySelector('.dwce-dropdown:has(button[data-text="Products"])');
  window.dwcMegaMenu.toggleDropdown(item);
});
```

#### `closeAllDropdowns()`

```js
// Close everything — useful when opening a custom overlay or modal
document.querySelector('#open-modal-btn').addEventListener('click', () => {
  window.dwcMegaMenu.closeAllDropdowns();
  openMyModal();
});
```

#### `openInMenu(path)`

Opens a dropdown, or a tab inside one, by its name. Scrolls the header into view first if needed, and opens the mobile menu on mobile and in offcanvas mode. The name is the dropdown's **Text** in lowercase with dashes; add a tab or nested dropdown after a slash. See [Open in Menu](/etchmegamenupro/open-in-menu.md).

```js
window.dwcMegaMenu.openInMenu('features/mobile-menu').then((opened) => {
  if (!opened) console.log('No menu item has that name');
});
```

Returns a promise that resolves to `true` when the menu opened, or `false` when nothing matched.

***

### Mobile Menu Control

#### `openMobileMenu()` / `closeMobileMenu()` / `toggleMobileMenu()`

```js
// Custom hamburger button outside the nav
document.querySelector('#custom-hamburger').addEventListener('click', () => {
  window.dwcMegaMenu.toggleMobileMenu();
});
```

#### `isMobileMenuOpen()`

```js
if (window.dwcMegaMenu.isMobileMenuOpen()) {
  console.log('Mobile menu is currently open');
}
```

***

### Layout

#### `recalculatePositions()`

Forces all open dropdowns to recalculate their position. Useful after layout shifts caused by banners, cookie bars, or dynamic content.

```js
// After a cookie banner dismissal changes the page layout
document.querySelector('#cookie-bar .accept').addEventListener('click', () => {
  cookieBar.remove();
  window.dwcMegaMenu.recalculatePositions();
});
```

#### `updateDropdownPosition(contentEl)`

Recalculates position for a single dropdown panel. `contentEl` is the dropdown content container (`.dwc-dropdown-content`), not the `<li>`.

```js
const panel = document.querySelector('.dwc-dropdown-content');
window.dwcMegaMenu.updateDropdownPosition(panel);
```

### Tabbed Navigation

**Full only.**

#### `TabbedNavSystem.recalculateHeights()`

Resizes the tab area of every tabbed nav to fit its tallest tab. Call it after you add or change tab content with JavaScript, for example content that loads later.

```js
// After loading extra content into a tab
window.DWCMegaMenuUtils.TabbedNavSystem.recalculateHeights();
```

***

## Custom Events

These events are dispatched on `document` by the script itself. Listen to them to react to menu-level changes.

| Event           | `detail` payload     | When fired                                                                                            |
| --------------- | -------------------- | ----------------------------------------------------------------------------------------------------- |
| `dwc:rtlchange` | `{ isRTL: boolean }` | `<html dir>` attribute changes                                                                        |
| `dwc:resize`    | *(none)*             | Window resize fires                                                                                   |
| `dwc:navigate`  | *(none)*             | SPA URL change detected (also *listened* for — see [SPA Integration](#spa--third-party-integrations)) |

### Listening examples

```js
// React to RTL direction toggle (e.g. language switcher changes dir)
document.addEventListener('dwc:rtlchange', (e) => {
  document.querySelector('#my-icon').style.transform = e.detail.isRTL
    ? 'scaleX(-1)'
    : 'scaleX(1)';
});

// Debounce your own logic on resize
document.addEventListener('dwc:resize', () => {
  clearTimeout(myResizeTimer);
  myResizeTimer = setTimeout(() => {
    console.log('Menu resize fired — recalculate my layout');
  }, 150);
});
```

***

## CSS State Classes

No custom events are dispatched for dropdown open/close. The menu communicates state exclusively through CSS classes. Use a `MutationObserver` or CSS to react to these.

### Body classes

| Class                  | Present when…                                         |
| ---------------------- | ----------------------------------------------------- |
| `dwc-mobile`           | Viewport is in mobile range                           |
| `dwc-offcanvas-active` | **Full only.** Offcanvas sidebar mode is active       |
| `show-nav`             | Mobile/offcanvas menu panel is open                   |
| `no-scroll`            | Body scroll is locked (mobile menu open)              |
| `desktop-centered`     | **Full only.** Centered logo desktop layout is active |

### Element classes

| Class         | Element            | Present when…                                              |
| ------------- | ------------------ | ---------------------------------------------------------- |
| `dwc-open`    | `.dwc-nest-menu`   | Mobile menu is open                                        |
| `open`        | Nav `<li>`         | Dropdown is currently open/visible                         |
| `active`      | Nav `<li>`         | Dropdown is active/expanded                                |
| `dwc-closing` | Nav `<li>` or menu | Closing animation is in progress                           |
| `is-active`   | Toggle `<button>`  | Toggle button is in active state                           |
| `is-breakout` | `<li>`             | **Full only.** Item has been relocated via `data-breakout` |

***

### Reacting to dropdown open/close

Watch for the `open` class on `.dwce-dropdown` elements inside the nav:

```js
const nav = document.querySelector('.dwc-nest-menu');

const observer = new MutationObserver(() => {
  const openItems = nav.querySelectorAll('.dwce-dropdown.open');

  if (openItems.length > 0) {
    console.log('Dropdown opened:', openItems[0]);
    // e.g. fire analytics, lazy-load panel content, pause a video
  } else {
    console.log('All dropdowns closed');
  }
});

observer.observe(nav, {
  subtree: true,
  attributes: true,
  attributeFilter: ['class']
});
```

React to a specific dropdown only:

```js
const productsItem = document.querySelector('.dwce-dropdown:has(button[data-text="Products"])');

new MutationObserver(() => {
  if (productsItem.classList.contains('open')) {
    console.log('Products dropdown opened — load product thumbnails');
    lazyLoadProductImages();
  }
}).observe(productsItem, { attributes: true, attributeFilter: ['class'] });
```

***

### Reacting to mobile menu open/close

```js
new MutationObserver(() => {
  const isOpen = document.body.classList.contains('show-nav');
  document.querySelector('#my-overlay').hidden = !isOpen;
}).observe(document.body, {
  attributes: true,
  attributeFilter: ['class']
});
```

Watch for the closing animation to fully complete before acting:

```js
const nestMenu = document.querySelector('.dwc-nest-menu');

new MutationObserver(() => {
  const isOpen  = nestMenu.classList.contains('dwc-open');
  const closing = nestMenu.classList.contains('dwc-closing');

  if (!isOpen && !closing) {
    console.log('Menu fully closed (animation done)');
  }
}).observe(nestMenu, { attributes: true, attributeFilter: ['class'] });
```

***

### Reacting to viewport mode changes

```js
new MutationObserver(() => {
  if (document.body.classList.contains('dwc-mobile')) {
    console.log('Switched to mobile layout');
  } else {
    console.log('Switched to desktop layout');
  }
}).observe(document.body, {
  attributes: true,
  attributeFilter: ['class']
});
```

***

### Reacting to offcanvas mode activating

**Full only.**

```js
new MutationObserver(() => {
  const active = document.body.classList.contains('dwc-offcanvas-active');
  console.log('Offcanvas mode:', active ? 'ON' : 'OFF');
}).observe(document.body, {
  attributes: true,
  attributeFilter: ['class']
});
```

***

### Close all dropdowns when a modal or overlay opens

```js
document.querySelector('#open-modal').addEventListener('click', () => {
  window.dwcMegaMenu.closeAllDropdowns();
  window.dwcMegaMenu.closeMobileMenu();
  openMyModal();
});
```

***

### Pause / resume a video when a mega menu panel opens

```js
const nav = document.querySelector('.dwc-nest-menu');

new MutationObserver(() => {
  const anyOpen = !!nav.querySelector('.dwce-dropdown.open');
  const video = document.querySelector('#hero-video');

  if (anyOpen) {
    video.pause();
  } else {
    video.play();
  }
}).observe(nav, { subtree: true, attributes: true, attributeFilter: ['class'] });
```

***

### Run code once a specific dropdown finishes closing

```js
const item = document.querySelector('.dwce-dropdown:has(button[data-text="Services"])');

new MutationObserver(() => {
  // dwc-closing is added during exit animation, removed when done
  if (!item.classList.contains('open') && !item.classList.contains('dwc-closing')) {
    console.log('Services dropdown fully closed');
  }
}).observe(item, { attributes: true, attributeFilter: ['class'] });
```

***

### Track which dropdown is open for analytics

```js
const nav = document.querySelector('.dwc-nest-menu');
let lastOpenLabel = null;

new MutationObserver(() => {
  const openItem = nav.querySelector('.dwce-dropdown.open');
  const label = openItem?.querySelector('button[data-text]')?.getAttribute('data-text') ?? null;

  if (label && label !== lastOpenLabel) {
    lastOpenLabel = label;
    console.log('Analytics: dropdown opened —', label);
    // myAnalytics.track('mega_menu_open', { label });
  }

  if (!openItem) lastOpenLabel = null;
}).observe(nav, { subtree: true, attributes: true, attributeFilter: ['class'] });
```

***

## Data Attributes

These attributes are read from HTML elements at runtime. Place them directly on the relevant component in Etch Builder via the **Custom Attributes** field, or in raw HTML.

### Breakpoint & Mode

| Attribute                | Element | Value                | Description                                                                                                                                                                                                      |
| ------------------------ | ------- | -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `data-mobile-breakpoint` | DWC Nav | `number` e.g. `1024` | Override the global `minWidth` for this nav. Desktop starts at value + 1. Also rewrites the stylesheet media queries to match on first initialisation (one-time; see `destroy()` example for how to re-trigger). |
| `data-offcanvas`         | DWC Nav | `"true"`             | **Full only.** Enable offcanvas/sidebar mode.                                                                                                                                                                    |
| `data-offcanvas-hover`   | DWC Nav | `"true"`             | **Full only.** Enable hover interaction in offcanvas mode (desktop only).                                                                                                                                        |

### Dropdown Behaviour

| Attribute                      | Element               | Value                                  | Description                                                                                |
| ------------------------------ | --------------------- | -------------------------------------- | ------------------------------------------------------------------------------------------ |
| `data-megamenu`                | DWC Dropdown          | `"true"`                               | Mark this dropdown as a mega menu panel (instead of a standard dropdown).                  |
| `data-content-width`           | DWC Dropdown          | `"500px"`                              | Override the width of this dropdown's content panel.                                       |
| `data-dropdown-width`          | DWC Dropdown          | `"300px"`                              | Override the width of a standard dropdown.                                                 |
| `data-content-align`           | DWC Dropdown          | `"left"` \| `"right"` \| `"center"`    | Horizontal alignment of the dropdown panel.                                                |
| `data-content-reference`       | DWC Dropdown          | CSS selector                           | Element to use as the positioning reference instead of the nav item.                       |
| `data-global-content-width`    | DWC Nav               | CSS selector                           | Constraining element for all dropdown widths in this nav.                                  |
| `data-global-content-vertical` | DWC Nav               | `"top"` \| `"bottom"`                  | Vertical positioning reference for all dropdowns.                                          |
| `data-equal-dropdown-height`   | DWC Nav               | `"true"`                               | Equalise the heights of all sibling dropdowns.                                             |
| `data-toggle`                  | DWC Dropdown          | `"click"` \| `"hover"` \| `"both"`     | Override the interaction mode for this specific dropdown.                                  |
| `data-open-in-menu`            | Any element           | `"features"`, `"features/mobile-menu"` | Opens that dropdown or tab on click. See [Open in Menu](/etchmegamenupro/open-in-menu.md). |
| `data-menu-id`                 | DWC Dropdown, DWC Tab | `"features"`                           | A fixed name for Open in Menu. Set it with the **Menu ID** prop.                           |

### Mobile Drill-Down

| Attribute              | Element          | Value                 | Description                                                              |
| ---------------------- | ---------------- | --------------------- | ------------------------------------------------------------------------ |
| `data-back-text`       | DWC Dropdown     | `"Go back"`           | Custom label for the back button in this drill-down level.               |
| `data-target-selector` | DWC Dropdown     | CSS selector          | Custom target element for drill-down toggle (advanced layout overrides). |
| `data-open-new-tab`    | DWC Nav or `<a>` | `"true"` \| `"false"` | Force all nav links to open in a new tab. Set `"false"` to reverse.      |

### Responsive Relocation

**Full only.** These move elements between DOM positions at specific breakpoints.

| Attribute        | Element           | Value                             | Description                                                                                      |
| ---------------- | ----------------- | --------------------------------- | ------------------------------------------------------------------------------------------------ |
| `data-breakout`  | `<li>` or element | *(present)* or `"1024"`           | Remove from nav and place it outside at mobile. Optionally scope to a max breakpoint.            |
| `data-breakin`   | `<li>` or element | *(present)* or `"768"`            | Move a mobile-only element into the nav header at desktop. Optionally scope to a min breakpoint. |
| `data-breakinto` | `<li>` or element | `"selector"` or `"selector\|768"` | Move element into a target container, optionally at a breakpoint.                                |

### Logo & Header Rows

| Attribute            | Element    | Value                   | Description                                                                           |
| -------------------- | ---------- | ----------------------- | ------------------------------------------------------------------------------------- |
| `data-centered-logo` | DWC Nav    | `"true"`                | **Full only.** Enable centered logo layout for this nav.                              |
| `data-center-guide`  | DWC Nav    | `"true"`                | **Full only.** Show the visual center guide line (admin only).                        |
| `data-header-row`    | Nav `<li>` | `"1"` \| `"2"` \| `"3"` | Assign this item to a specific header row (used with stripe style and centered logo). |

### Accessibility & Skip Links

| Attribute         | Element            | Value                                    | Description                                        |
| ----------------- | ------------------ | ---------------------------------------- | -------------------------------------------------- |
| `data-skip-link`  | DWC Nav or wrapper | `"#content"`                             | Add a skip link to the given target.               |
| `data-skip-link`  | DWC Nav or wrapper | `"#content \| Skip to main content"`     | Skip link with custom label.                       |
| `data-skip-link`  | DWC Nav or wrapper | `"#content \| Label, #footer \| Footer"` | Multiple skip links, comma-separated.              |
| `data-no-overlay` | Page wrapper       | *(present)*                              | Exclude this page from the overlay header feature. |
| `data-no-sticky`  | Page wrapper       | *(present)*                              | Exclude this page from the sticky header feature.  |

### Effects & Toggle Labels

| Attribute               | Element       | Value          | Description                                                                       |
| ----------------------- | ------------- | -------------- | --------------------------------------------------------------------------------- |
| `data-flyout-offcanvas` | DWC Nav       | `"true"`       | **Full only.** Use a flyout animation instead of slide-in for the offcanvas menu. |
| `data-adaptive-height`  | DWC Nav       | `"true"`       | **Full only.** Animate dropdown height as content changes.                        |
| `data-stripe-style`     | DWC Nav       | `"true"`       | **Full only.** Enable stripe styling across header rows.                          |
| `data-hover-effect`     | DWC Menu Item | `"roll"`       | **Full only.** Enable a text-roll hover effect on this item (desktop only).       |
| `data-label`            | Toggle button | `"Open/Close"` | Mark this toggle for label-width equalisation. The value is the open label text.  |
| `data-close-text`       | Toggle button | `"Close"`      | Custom close label text (paired with `data-label`).                               |
| `data-roll-text`        | Nav item      | `"text"`       | **Full only.** Text used for the roll/flip hover animation.                       |

***

## SPA & Third-Party Integrations

### Swup

If `window.swup` is detected, the menu hooks into `content:replace` and `page:view` automatically. No configuration needed.

### History API (manual SPA)

Set `reinitializeOnURLchange: true` in `window.DwcConfig.MegaMenu` to wrap `pushState` / `replaceState` and re-initialise on every URL change.

```js
window.DwcConfig = window.DwcConfig || {};
window.DwcConfig.MegaMenu = { reinitializeOnURLchange: true };
```

### Manual SPA trigger

If you control your own router, dispatch `dwc:navigate` on `document` after each page transition:

```js
// After your router swaps page content
router.on('after-navigate', () => {
  document.dispatchEvent(new CustomEvent('dwc:navigate'));
});
```

Or call `reinitialize()` directly:

```js
router.on('after-navigate', () => {
  window.dwcMegaMenu.reinitialize();
});
```

### DWCHeadroom

If `window.DWCHeadroom` is present, the menu automatically pauses it when the mobile menu opens and resumes it when the menu closes. No configuration needed.

***

## Exported Utilities (`window.DWCMegaMenuUtils`)

`window.DWCMegaMenuUtils` exposes the script's internal building blocks for three purposes: calling standalone utility functions for edge cases not covered by the main API, reading viewport/RTL/dropdown state before or outside of a menu instance, and subclassing or replacing individual subsystems without forking the script. The utility functions and detection helpers listed below are safe to call directly. The system classes expose only what is listed here — their internal methods are not part of the public API and may change between versions.

### Utility functions & detection helpers

Safe to call directly without knowledge of the internals.

| Export                                           | Description                                                                                                                                                                                                              |
| ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `updateMobileClass(minWidth?)`                   | Adds/removes `dwc-mobile` on `<html>` and, in Full, manages `dwc-offcanvas-mobile`. `minWidth` is optional — defaults to the current `MegaMenuCONFIG.minWidth`. Call after manual breakpoint or offcanvas state changes. |
| `getPositioningReferenceElement(headerSelector)` | Resolves the positioning reference element for a dropdown. Pass the header CSS selector (e.g. `'#dwc-header'`). Returns `.dwc-nest-header` when narrower than the header, otherwise the header itself.                   |
| `clearPositioningReferenceCache`                 | Clears the cached positioning reference. Call after DOM changes that alter the header structure.                                                                                                                         |
| `ViewportDetector`                               | Reads viewport dimensions and resolves the current breakpoint. Methods: `getWidth()`, `getHeight()`, `isDesktop()`, `isMobile()`, `isEffectiveDesktop()`, `isEffectiveMobile()`, `isEtch()`.                             |
| `RTLDetector`                                    | Watches `<html dir>` via MutationObserver and dispatches `dwc:rtlchange`. Static method: `RTLDetector.isRTL()` for a one-off check without instantiation.                                                                |
| `DropdownDetector`                               | Determines dropdown type from a `<li.dwce-dropdown>` element. Methods: `isMegaMenu(el)`, `isNestedDropdown(el)`, `isTopLevelDropdown(el)`, `getType(el)`.                                                                |

### System classes

For subclassing or replacing a specific subsystem. Internal methods on these objects are not supported and may change.

| Export                       | Description                                                                                                                                                                   |
| ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Utils`                      | General DOM utilities (`debounce`, `throttle`) used internally.                                                                                                               |
| `WidthSystem`                | Calculates and applies dropdown panel widths.                                                                                                                                 |
| `PositioningSystem`          | Handles viewport-aware dropdown positioning and overflow correction.                                                                                                          |
| `InteractionSystem`          | Manages click/hover/keyboard interaction. Accepts `onDropdownOpen`, `onDropdownClose`, `onMobileMenuOpen`, `onMobileMenuClose` callbacks via `initialize(nestMenu, options)`. |
| `AccessibilitySystem`        | Keyboard navigation, ARIA state management, focus trapping.                                                                                                                   |
| `ResponsiveRelocationSystem` | **Full only.** Implements `data-breakout`, `data-breakin`, and `data-breakinto` DOM relocation.                                                                               |
| `SwipeGestureHandler`        | **Full only.** Touch `touchstart`/`touchend` swipe detection.                                                                                                                 |
| `MobileMenuScrollReset`      | Resets the mobile panel scroll position on open/close.                                                                                                                        |
| `URLChangeDetector`          | Wraps History API or hooks Swup to detect SPA navigation.                                                                                                                     |
| `TooltipManager`             | **Full only.** Manages drill-down tooltips on mobile.                                                                                                                         |
| `MenuAnimationController`    | Controls open/close animation classes and CSS variable injection for transitions.                                                                                             |
| `CenteredLogoController`     | **Full only.** Implements the centered logo layout algorithm.                                                                                                                 |
| `OffcanvasMenuHandler`       | **Full only.** Manages offcanvas sidebar mode activation.                                                                                                                     |
| `OpenInMenu`                 | Opens dropdowns and tabs from `#menu=` links and `data-open-in-menu` elements. Use `dwcMegaMenu.openInMenu()` instead of calling it directly.                                 |
| `ToggleLabelController`      | Equalises open/close toggle label widths via MutationObserver.                                                                                                                |
| `PageExclusion`              | Reads `data-no-sticky` / `data-no-overlay` and conditionally disables features per page.                                                                                      |
| `SkipLinkController`         | Builds and injects skip link elements from `data-skip-link`.                                                                                                                  |
