feat(carousel): enhance circular layout handling and optimize page creation logic

This commit is contained in:
2026-09-24 15:20:57 -03:00
parent ee1420801d
commit f4959e0250
2 changed files with 24 additions and 4 deletions

View File

@@ -59,6 +59,16 @@ describe('CarouselComponent', () => {
expect(articles[1].getAttribute('data-index')).toBe('1'); expect(articles[1].getAttribute('data-index')).toBe('1');
}); });
it('permite inspeccionar las páginas antes de medir el viewport sin generar listas enormes', () => {
const carousel = fixture.componentInstance.carousel();
fixture.componentInstance.circular.set(true);
carousel['itemsPerPage'].set(Number.MAX_SAFE_INTEGER);
expect(carousel['circularPages']()).toEqual([]);
expect(carousel['createPage']('current', 0).items.map((entry) => entry.item.id))
.toEqual([1, 2, 3]);
});
it('expone una región accesible y controles con etiquetas', () => { it('expone una región accesible y controles con etiquetas', () => {
const region = fixture.nativeElement.querySelector('[role="region"]'); const region = fixture.nativeElement.querySelector('[role="region"]');
const buttons = fixture.nativeElement.querySelectorAll('button'); const buttons = fixture.nativeElement.querySelectorAll('button');

View File

@@ -70,6 +70,10 @@ export class CarouselComponent<T> implements AfterViewInit {
); );
protected readonly isCircularLayout = computed(() => this.circular() && this.pageCount() > 1); protected readonly isCircularLayout = computed(() => this.circular() && this.pageCount() > 1);
protected readonly circularPages = computed<CarouselPage<T>[]>(() => { protected readonly circularPages = computed<CarouselPage<T>[]>(() => {
if (!this.isCircularLayout()) {
return [];
}
const pageCount = this.pageCount(); const pageCount = this.pageCount();
const currentPage = this.normalizePage(this.currentPage(), pageCount); const currentPage = this.normalizePage(this.currentPage(), pageCount);
@@ -270,14 +274,20 @@ export class CarouselComponent<T> implements AfterViewInit {
} }
private createPage(slot: CarouselPage<T>['slot'], page: number): CarouselPage<T> { private createPage(slot: CarouselPage<T>['slot'], page: number): CarouselPage<T> {
const sourceItems = this.items();
// Layout has not necessarily been measured when a computed value is inspected.
const pageSize = Math.min(this.itemsPerPage(), sourceItems.length);
if (pageSize === 0) {
return { slot, items: [] };
}
const pageCount = this.pageCount(); const pageCount = this.pageCount();
const normalizedPage = this.normalizePage(page, pageCount); const normalizedPage = this.normalizePage(page, pageCount);
const start = normalizedPage * this.itemsPerPage(); const start = normalizedPage * pageSize;
const items: CarouselPageItem<T>[] = []; const items: CarouselPageItem<T>[] = [];
for (let offset = 0; offset < this.itemsPerPage(); offset += 1) { for (let offset = 0; offset < pageSize; offset += 1) {
const index = (start + offset) % this.items().length; const index = (start + offset) % sourceItems.length;
items.push({ item: this.items()[index], index }); items.push({ item: sourceItems[index], index });
} }
return { slot, items }; return { slot, items };