UNPKG

@aqua-ds/web-components

Version:
298 lines (290 loc) 12.4 kB
import { proxyCustomElement, HTMLElement, h, Host } from '@stencil/core/internal/client'; import { P as PopoverWidths } from './PopoverWidths.js'; import { U as UniqueIdGenerator } from './uidGenerator.js'; class DOMManager { filterChildToGetContent(el) { if (!!el === false) return; const content = el.childNodes; let child; content.forEach(item => { if (item.nodeName !== '#text' && item.nodeName !== 'SLOT-FB' && item.nodeName !== '#comment') { child = item; } }); return child; } filterValidChilds(content) { if (content.length <= 0) return; let childs = []; content.forEach(item => { if (item.nodeName !== '#text' && item.nodeName !== 'SLOT-FB' && item.nodeName !== '#comment') { childs.push(item); } }); return childs; } setElementWidth(width) { DOMManager.elementWidth = width; } get getElementWidth() { return DOMManager.elementWidth; } } class VirtualScroll { constructor({ renderRows, itemCount, viewportHeight, rowHeight, nodePadding, container, scrollTop, scrolledElement, id }) { this.activeIndex = -1; this.activeItem = null; this.id = ''; this.maxWidth = 0; this.currentScrollTop = -1; this.renderRows = renderRows; this.itemCount = itemCount; this.viewportHeight = viewportHeight; this.rowHeight = rowHeight; this.nodePadding = nodePadding; this.scrollTop = scrollTop; this.scrolledElement = scrolledElement; this.container = container; this.domManager = new DOMManager(); this.id = id; } render() { this.scrolledElement.scrollTo({ top: this.scrollTop }); const totalContentHeight = this.itemCount * this.rowHeight; let startNode = Math.floor(this.scrollTop / this.rowHeight) - this.nodePadding; startNode = Math.max(0, startNode); this.currentScrollTop = this.scrollTop; let visibleNodesCount = Math.ceil(this.viewportHeight / this.rowHeight) + 2 * this.nodePadding; visibleNodesCount = Math.min(this.itemCount - startNode, visibleNodesCount); const offsetY = startNode * this.rowHeight; this.visibleChildren = new Array(visibleNodesCount).fill(null).map((_, index) => this.renderRows[index + startNode]); return ` <div aria-role="listbox"> <div style=" height: ${totalContentHeight}px; overflow: hidden; position: relative; will-change: transform; " > <div class="result-list" id="${this.id}" tabindex="0" style=" transform: translateY(${offsetY}px); " > </div> </div> </div>`; } setScroll() { if (this.scrollListener) { return; } this.scrollListener = (e) => { if (this.animationFrame) { cancelAnimationFrame(this.animationFrame); } this.animationFrame = requestAnimationFrame(() => { this.scrollTop = e.target.scrollTop; this.renderWindow(); }); }; this.scrolledElement.addEventListener('scroll', this.scrollListener); } renderWindow() { /* if (Math.abs(this.scrollTop - this.currentScrollTop) < this.rowHeight / 2) { return; } */ this.currentScrollTop = this.scrollTop; const result = this.render(); this.scrolledElement.innerHTML = result; const resultList = this.scrolledElement.querySelector(`#${this.id}`); this.visibleChildren.forEach((item) => { resultList.appendChild(item); }); if (this.activeIndex >= 0) { this.activeItem = document.getElementById(getResultItemId(this.activeIndex)); if (this.activeItem) { this.activeItem.classList.add('focused'); this.activeItem.scrollIntoView(); } } this.setScroll(); } updateItems(newItems) { console.log('VL New Items: ', newItems); // this.renderRows = newItems; // this.itemCount = newItems.length; // this.scrollTop = 0; // Reiniciar el scroll para evitar errores con la nueva lista // this.scrolledElement.scrollTop = 0; // Asegurar que el scroll visual se resetee // this.renderWindow(); // Recalcular la ventana de elementos visibles } removeControllers() { this.animationFrame = null; } } const getResultItemId = idx => `result-item-${idx}`; const DEFAULT_WIDTH = 360; const aqVirtualListCss = ".aq-virtual-list__header{border-bottom:1px solid var(--color-paper-light);padding-bottom:var(--spacing-size-short);position:relative;z-index:5}.aq-virtual-list__content{max-height:360px;overflow-y:auto}.aq-virtual-list__footer{padding-top:var(--spacing-size-short);border-top:1px solid var(--color-paper-light);position:relative;z-index:5}"; const aqProgressBarCss = ".aq-scroll-bar::-webkit-scrollbar-track,.ag-body-horizontal-scroll-viewport::-webkit-scrollbar-track,.ag-body-vertical-scroll-viewport::-webkit-scrollbar-track{background-color:var(--color-paper-lighter);border-radius:10px}.aq-scroll-bar::-webkit-scrollbar,.ag-body-horizontal-scroll-viewport::-webkit-scrollbar,.ag-body-vertical-scroll-viewport::-webkit-scrollbar{width:14px;height:14px;background-color:var(--color-paper-lighter)}.aq-scroll-bar::-webkit-scrollbar-thumb,.ag-body-horizontal-scroll-viewport::-webkit-scrollbar-thumb,.ag-body-vertical-scroll-viewport::-webkit-scrollbar-thumb{background-color:var(--color-paper-base);border-radius:10px;border:3px var(--color-paper-lighter) solid}.aq-scroll-bar--wo-color::-webkit-scrollbar-track,.ag-body-horizontal-scroll-viewport--wo-color::-webkit-scrollbar-track,.ag-body-vertical-scroll-viewport--wo-color::-webkit-scrollbar-track{border-radius:10px}.aq-scroll-bar--wo-color::-webkit-scrollbar,.ag-body-horizontal-scroll-viewport--wo-color::-webkit-scrollbar,.ag-body-vertical-scroll-viewport--wo-color::-webkit-scrollbar{width:14px;height:14px}.aq-scroll-bar--wo-color::-webkit-scrollbar-thumb,.ag-body-horizontal-scroll-viewport--wo-color::-webkit-scrollbar-thumb,.ag-body-vertical-scroll-viewport--wo-color::-webkit-scrollbar-thumb{border-radius:10px}"; const AqVirtualList = /*@__PURE__*/ proxyCustomElement(class AqVirtualList extends HTMLElement { constructor(registerHost) { super(); if (registerHost !== false) { this.__registerHost(); } this.offset = 20; this.popoverWidth = PopoverWidths.DEFAULT; this.maxWidth = 50; this.rowMaxWidth = 50; this.virtualScroll = null; this.scrollListener = null; this.result = null; this.domManager = null; this.cid = ''; this.getMaxWidthByFull = () => { return this.activator.offsetWidth; }; this.getMaxWidthByAuto = () => { return this.rowMaxWidth + this.offset; }; } onActivatorChange() { this.setMaxWidth(); } onUpdate() { if (!!this.virtualScroll) this.virtualScroll.render(); else this.setInstance(); } onUpdateContent() { this.virtualScroll.renderWindow(); } async setInstance() { const el = this.el.querySelector('.aq-virtual-list'); const scrolledElement = this.el.querySelector('.aq-scroll-bar'); const content = el.querySelector('[slot="content"]'); if (!!content) { const domManager = new DOMManager(); const cloneElement = content; const rows = domManager.filterValidChilds(cloneElement.childNodes); this.calculateMaxWidth(rows); this.cid = new UniqueIdGenerator().generateId(); if (!!rows && !!rows.length) { this.virtualScroll = new VirtualScroll({ renderRows: rows, scrolledElement, container: this.container, itemCount: rows.length, viewportHeight: el.clientHeight, rowHeight: 28, nodePadding: 2, id: this.cid, scrollTop: scrolledElement.scrollTop, }); this.virtualScroll.renderWindow(); } } } calculateMaxWidth(rows) { if (!!rows === false || rows?.length <= 0) return; rows.forEach((row) => { const width = row.getBoundingClientRect().width; if (this.rowMaxWidth < width) this.rowMaxWidth = width; }); } setMaxWidth() { const value = Number(this.popoverWidth); if (!isNaN(value)) { this.maxWidth = value; return; } const widthTriggers = { [PopoverWidths.FULL]: this.getMaxWidthByFull, [PopoverWidths.AUTO]: this.getMaxWidthByAuto, [PopoverWidths.DEFAULT]: this.getMaxWidthByDefault, }; if (!!this.activator && this.domManager) { this.maxWidth = widthTriggers[this.popoverWidth](); } } setScrollListener() { if (this.scrollListener) return; const element = this.el.querySelector('.aq-virtual-list'); this.result = this.el.querySelector('.result-list'); if (!!this.result) { const content = this.domManager.filterValidChilds(this.result.childNodes); this.scrollListener = () => { if (!!content) { this.setMaxWidth(); } }; element.addEventListener('scroll', this.scrollListener); } } disconnectListeners() { const element = this.el.querySelector('.aq-virtual-list'); element.removeEventListener('scroll', this.scrollListener); } getMaxWidthByDefault() { return DEFAULT_WIDTH; } get getMaxWidth() { return this.maxWidth; } componentDidRender() { this.setScrollListener(); } disconnectedCallback() { if (!!this.virtualScroll) { this.virtualScroll.removeControllers(); } this.disconnectListeners(); } connectedCallback() { this.domManager = new DOMManager(); this.setMaxWidth(); } render() { return (h(Host, { key: 'fc194ad14f8960030ddbb93fc2c3b6f597a6200d' }, h("div", { key: 'b2e3ee59fb219193ba86395e73a1f6eceba787f4', class: "aq-virtual-list", style: this.popoverWidth === PopoverWidths.AUTO ? { minWidth: `${this.getMaxWidth}px`, maxWidth: `${DEFAULT_WIDTH}px` } : { width: `${this.getMaxWidth}px` } }, h("slot", { key: '0c1405b7eb6f935269f78bc2bcfba1d05b881c8c', name: "header" }), h("div", { key: '6c2b0a7528cf2c84ed19624f53bc481482f0f84e', class: "aq-virtual-list__content aq-scroll-bar" }, h("slot", { key: 'dd5f7f041a5ffa4d68028fedb3ceccef65f48a76', name: "content" })), h("slot", { key: '6033e1de846e8bba070d972a2b62b392f027c633', name: "footer" })))); } get el() { return this; } static get watchers() { return { "activator": ["onActivatorChange"] }; } static get style() { return aqVirtualListCss + aqProgressBarCss; } }, [260, "aq-virtual-list", { "additionalConfig": [16, "additional-config"], "offset": [2], "popoverWidth": [8, "popover-width"], "container": [16], "activator": [16], "isDynamic": [4, "is-dynamic"], "maxWidth": [32] }, [[0, "update", "onUpdate"], [0, "updateContent", "onUpdateContent"]], { "activator": ["onActivatorChange"] }]); function defineCustomElement() { if (typeof customElements === "undefined") { return; } const components = ["aq-virtual-list"]; components.forEach(tagName => { switch (tagName) { case "aq-virtual-list": if (!customElements.get(tagName)) { customElements.define(tagName, AqVirtualList); } break; } }); } export { AqVirtualList as A, defineCustomElement as d };