Add UI web components and adjust .gitignore
This commit is contained in:
102
static/components/side-menu/side-menu.js
Normal file
102
static/components/side-menu/side-menu.js
Normal file
@@ -0,0 +1,102 @@
|
||||
// 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 kebab‑case convention used elsewhere
|
||||
customElements.define("side-menu-component", SideMenu);
|
||||
Reference in New Issue
Block a user