Files
draw-tools/static/components/side-menu/side-menu.js

103 lines
3.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 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" });
const tmpl = document.getElementById("side-menu-template");
if (!tmpl) {
console.error("SideMenu: template not found");
return;
}
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 kebabcase convention used elsewhere
customElements.define("side-menu-component", SideMenu);