@aqua-ds/web-components
Version:
AquaDS Web Components
298 lines (290 loc) • 12.4 kB
JavaScript
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 };