as-hamburger.js

import API from '../api/ecosystem-base.js';
import {Menu_A} from './as-menu.js';
import {Component_A} from './basic/as-component.js';
import {FP_Hamburger_A} from './fp-ext/fp-hamburger-ext.js';
import {ErrorCode} from './../exception/exceptionDesc.js';

/**
 * @description Properties accepted by the Hamburger component, defining its appearance, behavior, and lifecycle hooks.
 * This class focuses on the specific properties of the Hamburger component.
 * Since it inherits from Accessor_A, all basic properties (e.g., height, width) are available but documented in the Accessor_A part.
 * @typedef {object} TComponents.HamburgerProps
 * @prop {object} [options] Additional options for the hamburger component.
 * Items in this object include:
 * - **responsive** (boolean, default: false): Whether the hamburger should be responsive.
 * @prop {string} [tips] Tooltip text for the component.
 * @prop {Function} [onCreated] Lifecycle hook invoked after component instantiation.
 * @prop {Function} [onMounted] Lifecycle hook invoked after component is attached to the DOM.
 * @prop {string} [position] CSS `position` property.
 * @prop {number} [width] Width of the menu container.
 * @prop {number} [height] Height of the menu container.
 * @prop {number} [top] Top offset in pixels.
 * @prop {number} [left] Left offset in pixels.
 * @prop {number} [borderRadius] Border radius in pixels.
 * @prop {number} [rotation] Rotation in degrees.
 * @prop {number} [zIndex] CSS `z-index`.
 * @prop {string} [border] CSS border shorthand.
 * @prop {string} [color] CSS text color.
 * @prop {string} [backgroundColor] CSS background color.
 * @prop {object} [font] Font configuration.
 * This object controls text appearance:
 * - **fontSize** (number, default: 12): Font size in pixels.
 * - **fontFamily** (string, default: 'Segoe UI'): Font family name.
 * - **style** (object): Font style configuration, containing `fontStyle`, `fontWeight`, `textDecoration`.
 * @prop {string} [size] Preset size key for the component.
 * @prop {string} [styleTemplate] Key of a style template to apply.
 * @prop {boolean} [useTitle] Whether to reserve space for the title.
 * @prop {string} [title] Title displayed next to the hamburger icon when the menu is opened.
 * @prop {boolean} [alwaysVisible] Whether the hamburger menu stays visible even when closed.
 * @prop {number} [activeViewIndex] Zero-based index of the currently active view.
 * @prop {Function} [onChange] Callback triggered when the active view changes.
 * @prop {boolean} [useViewIcon] Whether to display an icon alongside each view label.
 * @prop {TComponents.ViewProps[]} [views] Array of view objects to populate the menu.
 * @prop {string} [defaultState] Default state of the component.
 * @prop {boolean} [expandHeightToParentBottom] Whether to expand the height to the parent's bottom.
 * @memberof TComponents
 */

/**
 * @ignore
 */
const logModule = 'as-hamburger';

/**
 * @description Represents a Hamburger menu component.
 * @class TComponents.Hamburger
 * @extends TComponents.Menu_A
 * @memberof TComponents
 * @param {HTMLElement} parent - The parent element to which the hamburger menu is attached..
 * @param {TComponents.HamburgerProps} props - The properties of the hamburger menu.
 * @example
 * const hamburgerInstance = new TComponents.Hamburger(document.body, {
 *   position: 'absolute',
 *   width: 200,
 *   height: 200,
 *   zIndex: 1000,
 *   views: [
 *     {
 *       name: 'View 1',
 *       icon: 'abb-icon abb-icon-home-house_32',
 *       content: `view_${API.generateUUID()}`,
 *       children: [],
 *     },
 *   ],
 *   activeViewIndex: 0,
 * });
 *
 * // Render the hamburger menu
 * await hamburgerInstance.render();
 */
export class Hamburger extends Menu_A {
  constructor(parent, props) {
    super(parent, props);

    /**
     * @instance
     * @private
     * @type {TComponents.HamburgerProps}
     */
    this._props;

    /**
     * Use this variable to determine the source of the onchange event.
     * @instance
     * @private
     * @type {string|null}
     */
    this._changeSource = null; // 'user' | 'api'
  }

  /**
   * @description An array of Hamburger's views, each containing properties
   * like `id`, `name`, `content`, `active`, and `child`.
   * @member {any[]} TComponents.Hamburger#views
   * @instance
   * @example
   * const hamburgerInstance = new TComponents.Hamburger(document.body, {
   *   position: 'absolute',
   *   width: 200,
   *   height: 200,
   *   zIndex: 1000,
   *   views: [
   *     {
   *       name: 'View 1',
   *       icon: 'abb-icon abb-icon-home-house_32',
   *       content: `view_${API.generateUUID()}`,
   *       children: [],
   *     },
   *     {
   *       name: 'View 2',
   *       icon: 'abb-icon abb-icon-folder-open_32',
   *       content: `view_${API.generateUUID()}`,
   *       children: [],
   *     },
   *   ],
   *   activeViewIndex: 0,
   * });
   *
   * // Render the hamburger menu
   * await hamburgerInstance.render();
   *
   * // Get the views
   * const views = hamburgerInstance.views;
   * console.log(views);
   */
  get views() {
    return this._views;
  }

  /**
   * @returns {boolean}
   */
  get alwaysVisible() {
    return this._props.alwaysVisible;
  }

  /**
   * @description The visibility state of the hamburger menu.
   * @member {boolean} TComponents.Hamburger#alwaysVisible
   * @instance
   * @example
   * const hamburgerInstance = new TComponents.Hamburger(document.body, {
   *   position: 'absolute',
   *   width: 200,
   *   height: 200,
   *   zIndex: 1000,
   *   views: [
   *     {
   *       name: 'View 1',
   *       icon: 'abb-icon abb-icon-home-house_32',
   *       content: `view_${API.generateUUID()}`,
   *       children: [],
   *     },
   *   ],
   *   activeViewIndex: 0,
   * });
   *
   * // Render the hamburger menu
   * await hamburgerInstance.render();
   *
   * // Get the current visibility state
   * const isAlwaysVisible = hamburgerInstance.alwaysVisible;
   * console.log(isAlwaysVisible); // true
   *
   * // Set the visibility state to false
   * hamburgerInstance.alwaysVisible = false;
   */
  set alwaysVisible(b) {
    this.setProps({alwaysVisible: b});
  }

  /**
   * @deprecated
   */
  get activeView() {
    return this.activeViewName;
  }

  /**
   * @deprecated Use `activeViewName` instead {@link TComponents.Hamburger#activeViewName}.
   * @description Gets the currently active view.
   * @member {string} TComponents.Hamburger#activeView
   * @instance
   * @throws Will throw an error if the hamburger menu is not initialized.
   * @example
   * const hamburgerInstance = new TComponents.Hamburger(document.body, {
   *   position: 'absolute',
   *   width: 200,
   *   height: 200,
   *   zIndex: 1000,
   *   views: [
   *     {
   *       name: 'View 1',
   *       icon: 'abb-icon abb-icon-home-house_32',
   *       content: `view_${API.generateUUID()}`,
   *       children: [],
   *     },
   *   ],
   *   activeViewIndex: 0,
   * });
   *
   * // Render the hamburger menu
   * await hamburgerInstance.render();
   *
   * // Get the current active view
   * const currentActiveView = hamburgerInstance.activeView;
   * console.log(currentActiveView); // 'View 1'
   */
  set activeView(name) {
    this.activeViewName = name;
  }

  /**
   * @returns {string}
   */
  get activeViewName() {
    const index = this._props.activeViewIndex;
    if (index >= 0) {
      const view = this.views[index];
      return view.name;
    } else {
      return '';
    }
  }

  /**
   * @description Sets the active view by its display name.
   * The comparison is performed against the resolved text from Component_A.tParse.
   * @member {string} TComponents.Hamburger#activeViewName
   * @instance
   * @param {string} name - The target view's display name.
   * @throws {Error} If the hamburger menu is not initialized (render not completed).
   * @example
   * const hamburgerInstance = new TComponents.Hamburger(document.body, {
   *   position: 'absolute',
   *   width: 200,
   *   height: 200,
   *   zIndex: 1000,
   *   views: [
   *     {
   *       name: 'View 1',
   *       icon: 'abb-icon abb-icon-home-house_32',
   *       content: `view_${API.generateUUID()}`,
   *       children: [],
   *     },
   *   ],
   *   activeViewIndex: 0,
   * });
   *
   * // Render the hamburger menu
   * await hamburgerInstance.render();
   *
   * // Get the current active view name
   * const currentActiveView = hamburgerInstance.activeViewName;
   * console.log(currentActiveView); // 'View 1'
   */
  set activeViewName(name) {
    if (!this.hamburgerMenu) throw new Error('hamburgerMenu not initialized yet. Please render the component first');
    const index = this.views.findIndex((item) => Component_A.tParse(item.name) === name);
    this.activeViewIndex = index;
  }

  /**
   * @returns {number}
   */
  get activeViewIndex() {
    return this._props.activeViewIndex;
  }

  /**
   * @description Sets the active view index and updates the active view in the Hamburger component.
   * @member {number} TComponents.Hamburger#activeViewIndex
   * @instance
   * @param {number} t - The new active view index.
   * @throws {Error} If the new index is invalid or if the active view content is invalid.
   * @example
   * const hamburgerInstance = new TComponents.Hamburger(document.body, {
   *   position: 'absolute',
   *   width: 200,
   *   height: 200,
   *   zIndex: 1000,
   *   views: [
   *     {
   *       name: 'View 1',
   *       icon: 'abb-icon abb-icon-home-house_32',
   *       content: `view_${API.generateUUID()}`,
   *       children: [],
   *     },
   *   ],
   *   activeViewIndex: 0,
   * });
   *
   * // Render the hamburger menu
   * await hamburgerInstance.render();
   *
   * // Get the current active view index
   * const currentActiveViewIndex = hamburgerInstance.activeViewIndex;
   * console.log(currentActiveViewIndex); // 0
   */
  set activeViewIndex(t) {
    const index = this.checkActiveViewIndex(t);
    if (index === null) return;

    // To ensure compatibility, this interface will trigger onchange previously.
    if (!this._changeSource) {
      this._changeSource = 'user';
    }

    // Set up the hamburger active view.
    this.setProps({activeViewIndex: index});
  }

  /**
   * @returns {number}
   */
  get activeViewIndexX() {
    return this._props.activeViewIndex;
  }

  /**
   * @description Sets the active view index and updates the active view in the Hamburger component.
   * This will update the hamburger menu but will NOT trigger the `onchange` event.
   * Recommended for internal or programmatic updates, where change notification is not desired.
   * @member {number} TComponents.Hamburger#activeViewIndex
   * @instance
   * @param {number} t - The new active view index.
   * @throws {Error} If the new index is invalid or if the active view content is invalid.
   * @example
   * const hamburgerInstance = new TComponents.Hamburger(document.body, {
   *   position: 'absolute',
   *   width: 200,
   *   height: 200,
   *   zIndex: 1000,
   *   views: [
   *     {
   *       name: 'View 0',
   *       icon: 'abb-icon abb-icon-home-house_32',
   *       content: `view_${API.generateUUID()}`,
   *       children: [],
   *     },
   *     {
   *       name: 'View 1',
   *       icon: 'abb-icon abb-icon-home-house_32',
   *       content: `view_${API.generateUUID()}`,
   *       children: [],
   *     },
   *   ],
   *   activeViewIndex: 1,
   * });
   *
   * // Render the hamburger menu
   * await hamburgerInstance.render();
   *
   * hamburgerInstance.activeViewIndexX = 0;
   */
  set activeViewIndexX(t) {
    const index = this.checkActiveViewIndex(t);
    if (index === null) return;

    // If it is not triggered by a user, it is considered an API.
    if (!this._changeSource) {
      this._changeSource = 'api';
    }

    // Set up the hamburger active view.
    this.setProps({activeViewIndex: index});
  }

  /**
   * @description Returns default properties for the hamburger menu.
   * @member TComponents.Hamburger#defaultProps
   * @method
   * @protected
   * @returns {TComponents.HamburgerProps} The default properties.
   */
  defaultProps() {
    return {
      options: {
        responsive: false,
      },
      tips: '',
      onCreated: '',
      onMounted: '',
      onDispose: '',
      position: 'static',
      width: 200,
      height: 200,
      top: 0,
      left: 0,
      borderRadius: 4,
      rotation: 0,
      zIndex: 0,
      border: '1px solid #dbdbdb',
      color: 'rgba(0,0,0,1)',
      backgroundColor: 'rgba(255,255,255,1)',
      font: {
        fontSize: 12,
        fontFamily: 'Segoe UI',
        style: {
          fontStyle: 'normal',
          fontWeight: 'normal',
          textDecoration: 'none',
        },
      },
      size: '',
      styleTemplate: '',
      useTitle: true,
      title: '',
      alwaysVisible: true,
      activeViewIndex: 0,
      onChange: '',
      useViewIcon: true,
      views: [
        {
          name: Component_A.tParse('Item 0'),
          content: `View_${API.generateUUID()}`,
          id: null,
          icon: 'abb-icon abb-icon-abb_robot-tool_32',
          children: [],
        },
      ],
      defaultState: 'show_enable',
      expandHeightToParentBottom: false,
    };
  }

  /**
   * @description Initializes the hamburger menu.
   * @member TComponents.Hamburger#onInit
   * @method
   * @returns {void}
   */
  onInit() {
    // Process the views prior to instantiating the new hamburger object.
    this._initViews();

    // Initialize the hamburger menu.
    this.hamburgerMenu = new FP_Hamburger_A();
    this.hamburgerMenu.onclickmenu = this._cbOnClickMenu.bind(this);

    this.viewId.clear();
    this.views.forEach((view) => {
      const dom = this._getDom(view.content, view.id, view.name);
      view.id = this.hamburgerMenu.addView(Component_A.tParse(view.name), dom, view.icon);
      this.viewId.set(view.id, view.name);
    });
  }

  /**
   * @description Generates the HTML markup for the hamburger menu.
   * @member TComponents.Hamburger#markup
   * @method
   * @returns {string} The HTML markup.
   */
  markup() {
    return /*html*/ `<div class="tc-hamburger"></div>`;
  }

  /**
   * @description Maps components to their identifiers.
   * @member TComponents.Hamburger#mapComponents
   * @method
   * @returns {object}
   */
  mapComponents() {
    if (!Array.isArray(this._children)) return {};

    for (let i = 0; i < this._children.length; i++) {
      if (i === this._props.activeViewIndex) {
        const instance = this._children[i];
        return {children: instance};
      }
    }

    return {};
  }

  /**
   * @description Renders the hamburger menu.
   * @member TComponents.Hamburger#onRender
   * @method
   * @returns {void}
   */
  onRender() {
    try {
      this.hamburgerMenu.attachToElement(this.find('.tc-hamburger'));
      this.hamburgerMenu.title = Component_A.tParse(this._props.title);
      this.hamburgerMenu.alwaysVisible = this._props.alwaysVisible;

      // Refine the style of the hamburger menu.
      this.find('.fp-components-hamburgermenu-a-menu__container').style.setProperty('z-index', '3');
      this.find('.fp-components-hamburgermenu-a-button-container').style.setProperty('z-index', '99');
      this.find('.fp-components-hamburgermenu-a-container').style.cssText = `
        align-items: normal;
        border: ${this._props.border};
        border-radius: ${this._props.borderRadius}px;
      `;

      this.find('.fp-components-hamburgermenu-a-menu__wrapper').style.cssText = `
        color: ${this._props.color};
        font-family: ${this._props.font.fontFamily};
        font-size: ${this._props.font.fontSize}px;
        font-style: ${this._props.font.style.fontStyle};
        font-weight: ${this._props.font.style.fontWeight};
        text-decoration: ${this._props.font.style.textDecoration};
      `;

      // fix: the delayed rendering of menu icon
      this.all('.fp-components-hamburgermenu-a-menu__button').forEach((btn) => {
        btn.style.color = this._props.color;
      });

      this.find('.fp-components-hamburgermenu-a-container__content').classList.add(
        'hamburger__container',
        'flex-row',
        'justify-stretch',
      );

      this.find('.fp-components-hamburgermenu-a-container__content').style.backgroundColor =
        this._props.backgroundColor;

      this.container.classList.add('tc-container');
      this.container.classList.add('is-container');

      this.container.classList.add('hamburger-base-style');

      // Set up the hamburger active view.
      this._setActiveView();

      // After setting the `activeView` in the component, assign the `onchange` handler.
      // Prevent it from being executed during initialization.
      this.hamburgerMenu.onchange = this._cbOnChange.bind(this);
      this._addTips();
    } catch (e) {
      // Runtime errors: write specific content to the log, throw error code
      Logger.e(
        logModule,
        `${ErrorCode.FailedToRunOnRender}`,
        `Error happens on onRender of hamburger component ${this.compId}.`,
        e,
      );
      throw new Error(ErrorCode.FailedToRunOnRender, {cause: e});
    }
  }

  /**
   * @description Adds a new menu item to the hamburger menu.
   * @member TComponents.Hamburger#addMenu
   * @method
   * @param {object} menu - The menu definition
   * @param {string} menu.name - Display name of the menu item
   * @param {string|HTMLElement} menu.content - Content of the menu view
   * @param {string} [id = null] - ID of the menu view
   * @returns {void}
   * @example
   * const hamburgerInstance = new TComponents.Hamburger(document.body, {
   *   position: 'absolute',
   *   width: 200,
   *   height: 200,
   *   zIndex: 1000,
   *   views: [
   *     {
   *       name: 'View 1',
   *       icon: 'abb-icon abb-icon-home-house_32',
   *       content: `view_${API.generateUUID()}`,
   *       children: [],
   *     },
   *   ],
   *   activeViewIndex: 0,
   * });
   *
   * // Render the hamburger menu
   * await hamburgerInstance.render();
   *
   * const v1 = {
   *   name: 'Menu 1',
   *   content: 'view-001',
   *   icon: 'abb-icon abb-icon-abb_tree-view_16',
   *   children: []
   * }
   *
   * hamburgerInstance.addMenu(v1);
   * @example
   * const div1 = document.createElement('div');
   * div1.textContent = 'Hello world';
   * div1.style.fontSize = '96px';
   * div1.style.fontWeight = 'bold';
   * div1.style.textAlign = 'center';
   *
   * const v2 = {name: 'Menu 2', content: div1};
   *
   * hamburgerInstance.addMenu(v2);
   */
  addMenu(itemOptions) {
    this.addView(itemOptions);

    const lastMenu = this._views[this._views.length - 1];
    const dom = this._getDom(lastMenu.content, lastMenu.id, lastMenu.name);

    lastMenu.id = this.hamburgerMenu.addView(Component_A.tParse(lastMenu.name), dom, lastMenu.icon);

    this.viewId.set(lastMenu.id, lastMenu.name);
  }

  /**
   * @description Removes a menu item by id, content, or name.
   * Lookup priority:
   * 1. `id`
   * 2. `content`
   * 3. `name`
   * @member TComponents.Hamburger#removeMenu
   * @method
   * @param {object} options
   * @param {string} [options.id] - Menu id
   * @param {string|HTMLElement} [options.content] - Menu content
   * @param {string} [options.name] - Menu display name
   * @returns {void}
   * @example
   * hamburgerInstance.removeMenu({ name: 'Menu 1' });
   */
  removeMenu({id = null, content, name} = {}) {
    const menu = this.findView({id, content, name});
    if (!menu) return;

    this._removeMenu(menu);
  }

  /**
   * @description Removes a hamburger menu by its index in the views array.
   * @member TComponents.Hamburger#removeMenuByIndex
   * @method
   * @param {number} index - Zero-based hamburger menu index.
   * @returns {void}
   * @example
   * hamburgerInstance.removeMenuByIndex(1);
   */
  removeMenuByIndex(index) {
    if (!this.isValidIndex(index)) return;

    const menu = this._views[index];
    this._removeMenu(menu);
  }

  /**
   * @description Hides a menu item and its associated view.
   * @member TComponents.Hamburger#hideMenu
   * @method
   * @param {object} options
   * @param {string} [options.id] - Menu id
   * @param {string|HTMLElement} [options.content] - Menu content
   * @param {string} [options.name] - Menu display name
   * @returns {void}
   * @example
   * hamburgerInstance.hideMenu({ name: 'Menu 2' });
   */
  hideMenu({id = null, content, name} = {}) {
    const menu = this.findView({id, content, name});
    this._hideMenu(menu);
  }

  /**
   * @description Hides a hamburger menu by its index.
   * @member TComponents.Hamburger#hideMenuByIndex
   * @method
   * @param {number} index - Zero-based menu index.
   * @returns {void}
   * @example
   * // Hide the menu 1.
   * hamburgerInstance.hideMenuByIndex(0);
   */
  hideMenuByIndex(index) {
    if (!this.isValidIndex(index)) return;

    const menu = this._views[index];
    this._hideMenu(menu);
  }

  /**
   * @description Shows a menu item and its associated view.
   *
   * @member TComponents.Hamburger#showMenu
   * @method
   * @param {object} options
   * @param {string} [options.id] - Menu id
   * @param {string|HTMLElement} [options.content] - Menu content
   * @param {string} [options.name] - Menu display name
   * @returns {void}
   * @example
   * hamburgerInstance.showMenu({ name: 'Menu 2' });
   */
  showMenu({id = null, content, name} = {}) {
    const menu = this.findView({id, content, name});
    this._showMenu(menu);
  }

  /**
   * @description Shows a hamburger menu by its index.
   * @member TComponents.Hamburger#showMenuByIndex
   * @method
   * @param {number} index - Zero-based menu index.
   * @returns {void}
   * @example
   * // Hide the menu 1;
   * hamburgerInstance.hideMenuByIndex(0);
   *
   * // Show the menu 1;
   * hamburgerInstance.showMenuByIndex(0);
   */
  showMenuByIndex(index) {
    if (!this.isValidIndex(index)) return;

    const menu = this._views[index];
    this._showMenu(menu);
  }

  /**
   * @description Internal method to remove a menu item and its view.
   * @member TComponents.Hamburger#_removeMenu
   * @method
   * @private
   * @param {object} menu - Menu view object
   * @returns {void}
   */
  _removeMenu(menu) {
    if (!menu || !menu.id) return;

    this.hamburgerMenu.removeView(menu.id);
    this.removeView(menu);
  }

  /**
   * @description Internal method to hide a menu item and its view.
   * @member TComponents.Hamburger#_hideMenu
   * @method
   * @private
   * @param {object} menu - Menu view object
   * @returns {void}
   */
  _hideMenu(menu) {
    if (!menu) return;

    // hide hamburger menu bar item
    const index = this._views.findIndex((v) => v.id === menu.id);
    if (!this.isValidIndex(index)) return;

    const node = this.getMenuBarItem('.fp-components-hamburgermenu-a-menu', index);
    if (node) {
      node.style.display = 'none';
    }

    // hide content view
    this.hideView(menu);
  }

  /**
   * @description Internal method to show a menu item and its view.
   * @member TComponents.Hamburger#_showMenu
   * @method
   * @private
   * @param {object} menu - Menu view object
   * @returns {void}
   */
  _showMenu(menu) {
    if (!menu) return;

    const index = this._views.findIndex((v) => v.id === menu.id);
    if (!this.isValidIndex(index)) return;

    const node = this.getMenuBarItem('.fp-components-hamburgermenu-a-menu', index);
    if (node) {
      node.style.display = '';
    }

    // show content view
    this.showView(menu);
  }

  /**
   * @description Handles clicks on the menu bar items, updating the active view.
   * @member TComponents.Hamburger~_cbOnClickMenu
   * @method
   * @private
   * @param {string} oldId - The previous id of the active view.
   * @param {string} id - The current id of the active view.
   * @returns {void}
   */
  _cbOnClickMenu(oldId, id) {
    if (!id || oldId === id) return;

    // Define the origin of the onchange event.
    this._changeSource = 'user';

    const index = this.views.findIndex((v) => v.id === id);
    if (index === -1) return;
    this.activeViewIndex = index;
  }

  /**
   * @description Callback invoked when the active view of the hamburger menu changes.
   * @member TComponents.Hamburger~_cbOnChange
   * @method
   * @private
   * @param {string} oldId - The previous id of the active view.
   * @param {string} id - The current id of the active view.
   * @returns {void}
   */
  _cbOnChange(oldId, id) {
    // If oldId is invalid, it means the hamburger container has just been initialized.
    if (!oldId) return;

    // Only trigger the change event on user interaction.
    const source = this._changeSource;
    this._changeSource = null;

    if (source !== 'user') return;

    try {
      var fn = Component_A.genFuncTemplate(this._props.onChange, this);
      if (typeof fn === 'function') fn(oldId, id);
    } catch (e) {
      Component_A.popupEventError(e, 'onChange', logModule);
    }
  }

  /**
   * @description Removes the “active” style from all hamburger menu buttons, then activates the view at the specified index.
   * @member TComponents.Hamburger#setActiveView
   * @method
   * @protected
   * @throws {Error} If the hamburger menu is not initialized or the target view cannot be found.
   * @return {void}
   */
  setActiveView() {
    this._setActiveView();
  }

  /**
   * @member TComponents.Hamburger~_setActiveView
   * @method
   * @private
   * @throws {Error}
   * @return {void}
   */
  _setActiveView() {
    if (!this.hamburgerMenu) {
      Logger.e(logModule, ErrorCode.FailedToInitComponent, 'The hamburger component is not initialized.');
      throw ErrorCode.FailedToInitComponent;
    }

    const idx = this._props.activeViewIndex || 0;
    const view = this.views[idx];

    if (!view || !view.id) {
      Logger.e(logModule, ErrorCode.NotfoundTargetView, 'The target view is not found or active index is invalid.');
      throw ErrorCode.NotfoundTargetView;
    }
    if (this.hamburgerMenu.activeView === view.id) return;

    this.all('.fp-components-hamburgermenu-a-menu__button--active').forEach((el) => {
      el.classList.remove('fp-components-hamburgermenu-a-menu__button--active');
    });

    this.hamburgerMenu.activeView = view.id;
  }
}

/**
 * @description Add css properties to the component
 * @alias loadCssClassFromString
 * @member TComponents.Hamburger.loadCssClassFromString
 * @method
 * @static
 * @param {string} css - The css string to be loaded into style tag
 * @example
 * TComponents.Hamburger.loadCssClassFromString(/*css* / `
 *   .tc-hamburger {
 *     height: 100%;
 *     width: 100%;
 *   }`
 * );
 */
Hamburger.loadCssClassFromString(/*css*/ `
.tc-hamburger {
  height: 100%;
  width: 100%;
  min-width: 0px;
  min-height: 0px;
  padding: 0px;
  margin: 0px;
}

.tc-hamburger .fp-components-hamburgermenu-a-container {
  height: 100%;
  width: 100%;
  min-width: 0px;
  min-height: 0px;
  padding: 0px;
  margin: 0px;
  overflow: hidden;
}

.tc-hamburger .hamburger-base-style {
  background-color: transparent !important;
  border: 1px solid var(--t-color-GRAY-30);
  border-top: none;
  border-buttom: none;
  border-right: none;
}

.tc-hamburger .hamburger__container {
  position: relative;
  max-width: inherit;
  overflow-y: auto;
}

.tc-hamburger .fp-components-hamburgermenu-a-menu__container {
  text-decoration: inherit;
}

.tc-hamburger .fp-components-hamburgermenu-a-menu__title-container {
  min-height: unset;
  padding-left: 48px;
}

.tc-hamburger .fp-components-hamburgermenu-a-menu {
  min-height: unset;
  padding-right: 0px;
}

.tc-hamburger .fp-components-hamburgermenu-a-button-container {
  position: absolute;
}

.tc-hamburger .fp-components-hamburgermenu-a-menu__button {
  min-height: 48px;
}

.tc-hamburger .fp-components-hamburgermenu-a-menu__wrapper {
  z-index: 2;
}

.tc-hamburger .fp-components-hamburgermenu-a-container__content {
  z-index: 1;
}

.tc-hamburger .fp-components-hamburgermenu-a-menu__button-icon {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 32px;
  width: 32px;
  min-height: unset;
}

.tc-hamburger .fp-components-hamburgermenu-a-button-wrap {
  width: 48px;
  height: 48px;
}
`);

/**
 * Add disabled css properties to hamburger-type components.
 */
Hamburger.loadCssClassFromString(`
.hamburgermenu-a-disabled {
  opacity: 0.7;
  cursor: not-allowed !important;
}

.hamburgermenu-a-disabled .fp-components-hamburgermenu-a-menu__wrapper,
.hamburgermenu-a-disabled .fp-components-hamburgermenu-a-container__content {
  pointer-events: none;
}
`);