/* Define the web component for settable list https://stackoverflow.com/questions/50404970/web-components-pass-data-to-and-from https://www.w3schools.com/howto/howto_js_treeview.asp */ class ListComponent extends HTMLElement { #shadow; #data; #iconKinds; //array from kind integer to codicon name constructor() { super(); this.#shadow = this.attachShadow({ mode: "open", delegatesFocus: true }); this.#data = []; this.#iconKinds = []; this.render(); } setData(newData, icons, append = false) { if (!Array.isArray(newData)) { console.warn("Invalid format, expected an array."); return; } this.#iconKinds = icons; this.#data = append ? this.#data.concat(newData) : structuredClone(newData); this.render(); } set data(value) { this.setData(value, false); } get data() { return this.#data; } /* Render the list items #data */ render() { const list = document.createElement('ul'); list.style = "max-height:45cqh;overflow: auto;"; const select = e => { if(e.type ==="keyup" && !(e.key==="Enter" )) return; this.#shadow.querySelectorAll('li.selected').forEach(item => { item.className = ''; }); e.currentTarget.className = 'selected'; const i=e.currentTarget.getAttribute("data-index") console.log('Item index clicked:', i,this.#data[i]); // You can dispatch a custom event here if needed. this.dispatchEvent(new CustomEvent('itemSelected', { detail: this.#data[i], bubbles: true, composed: true })); }; this.#data.forEach((item, index) => { const listItem = document.createElement('li'); listItem.setAttribute("tabindex", "0") listItem.setAttribute("data-index", index) listItem.innerHTML = ` ${item.name} - ${item.detail}`; listItem.addEventListener('click', select); listItem.addEventListener('keyup', select); list.appendChild(listItem); }); this.#shadow.innerHTML = ''; const style = document.createElement('style'); style.textContent = ` @import url("../codicon@0.0.40/codicon.css"); ul { list-style-type: none; padding:0;margin:0;overflow: auto; background-color: #f8f9fa;font-size: 80%;} li { padding: 0 0 0 2px; border-bottom: 1px solid #ccc; cursor: pointer; width:100%; } li:not(.selected) :hover { background-color: #ccc; } .selected { background-color: #0d6efd;color: #ffff;} i {vertical-align: middle;} `; this.#shadow.appendChild(style); this.#shadow.appendChild(list); } /* Render an error message if JSON fetching fails */ renderError(error) { this.#shadow.innerHTML = `
Error loading data: ${error.message}
`; } } /* Define the new custom element */ customElements.define('qd-list', ListComponent); class PanelComponent extends HTMLElement { #shadow; #data; #iconKinds; //array from kind integer to codicon name constructor() { super(); this.#shadow = this.attachShadow({ mode: "open", delegatesFocus: true }); this.#data = []; this.#iconKinds = []; this.render(); } setData(newData, icons, append = false) { if (!Array.isArray(newData)) { console.warn("Invalid format, expected an array."); return; } this.#iconKinds = icons; this.#data = append ? this.#data.concat(newData) : structuredClone(newData); this.render(); } set data(value) { this.setData(value, false); } get data() { return this.#data; } /* Render the list items #data */ render() { const list = document.createElement('ul'); list.style = "max-height:45cqh;overflow: auto;"; const select = e => { if(e.type ==="keyup" && !(e.key==="Enter" )) return; this.#shadow.querySelectorAll('li.selected').forEach(item => { item.className = ''; }); e.currentTarget.className = 'selected'; const i=e.currentTarget.getAttribute("data-index") console.log('Item index clicked:', i,this.#data[i]); // You can dispatch a custom event here if needed. this.dispatchEvent(new CustomEvent('itemSelected', { detail: this.#data[i], bubbles: true, composed: true })); }; this.#data.forEach((item, index) => { const listItem = document.createElement('li'); listItem.setAttribute("tabindex", "0") listItem.setAttribute("data-index", index) listItem.innerHTML = ` ${item.name} - ${item.detail}`; listItem.addEventListener('click', select); listItem.addEventListener('keyup', select); list.appendChild(listItem); }); this.#shadow.innerHTML = ''; const style = document.createElement('style'); style.textContent = ` @import url("../codicon@0.0.40/codicon.css"); ul { list-style-type: none; padding:0;margin:0;overflow: auto; background-color: #f8f9fa;font-size: 80%;} li { padding: 0 0 0 2px; border-bottom: 1px solid #ccc; cursor: pointer; width:100%; } li:not(.selected) :hover { background-color: #ccc; } .selected { background-color: #0d6efd;color: #ffff;} i {vertical-align: middle;} `; this.#shadow.appendChild(style); this.#shadow.appendChild(list); } /* Render an error message if JSON fetching fails */ renderError(error) { this.#shadow.innerHTML = `Error loading data: ${error.message}
`; } } /* Define the new custom element */ customElements.define('qd-panel', PanelComponent);