// Side menu component logic class SideMenu extends HTMLElement { constructor() { super(); // Attach a shadow root and clone the template defined in side-menu.html this.attachShadow({ mode: "open" }); // Create a template element with the side‑menu markup directly in JS const tmpl = document.createElement("template"); tmpl.innerHTML = `
`; this.shadowRoot.appendChild(tmpl.content.cloneNode(true)); // Reference the toggle button and the menu container this._toggleBtn = this.shadowRoot.querySelector(".toggle"); this._menu = this.shadowRoot.querySelector(".menu"); this._colorPicker = this.shadowRoot.querySelector("color-picker"); this._gridToggle = this.shadowRoot.querySelector("#grid-toggle"); // Bind event handlers this._onToggle = this._onToggle.bind(this); this._onColorChange = this._onColorChange.bind(this); this._onGridToggle = this._onGridToggle.bind(this); } static get observedAttributes() { return ["collapsed"]; } connectedCallback() { // Register click listener for the toggle button this._toggleBtn?.addEventListener("click", this._onToggle); this._colorPicker?.addEventListener("colorchange", this._onColorChange); this._gridToggle?.addEventListener("change", this._onGridToggle); // Initialise collapsed state from the attribute (if present) if (this.hasAttribute("collapsed")) { this._applyCollapsed(true); } } disconnectedCallback() { // Clean up listeners when the element is removed this._toggleBtn?.removeEventListener("click", this._onToggle); this._colorPicker?.removeEventListener("colorchange", this._onColorChange); this._gridToggle?.removeEventListener("change", this._onGridToggle); } attributeChangedCallback(name, oldVal, newVal) { if (name === "collapsed") { const isCollapsed = this.hasAttribute("collapsed"); this._applyCollapsed(isCollapsed); } } // Apply or remove the CSS class that slides the menu _applyCollapsed(collapsed) { const host = this.shadowRoot.host; if (collapsed) { host.classList.add("collapsed"); } else { host.classList.remove("collapsed"); } } // Forward color picker change as bgcolorchange event _onColorChange(e) { const { color } = e.detail; this.dispatchEvent( new CustomEvent("bgcolorchange", { detail: { color }, bubbles: true, composed: true, }), ); } // Forward grid toggle change as gridtoggle event _onGridToggle(e) { const enabled = e.target.checked; this.dispatchEvent( new CustomEvent("gridtoggle", { detail: { enabled }, bubbles: true, composed: true, }), ); } // Toggle the collapsed attribute when the button is clicked _onToggle() { if (this.hasAttribute("collapsed")) { this.removeAttribute("collapsed"); } else { this.setAttribute("collapsed", ""); } } } // Register the custom element; we follow the kebab‑case convention used elsewhere customElements.define("side-menu-component", SideMenu);