Co-authored-by: Robbie Davis <robbie@therobbiedavis.com>
This commit is contained in:
Joe Milazzo 2024-08-24 19:23:57 -05:00 committed by GitHub
parent dbc4f35107
commit c93af3e56f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
126 changed files with 1989 additions and 2877 deletions

View file

@ -1 +0,0 @@
<ng-content></ng-content>

View file

@ -1,17 +0,0 @@
import {ChangeDetectionStrategy, Component, ContentChild, Input, TemplateRef} from '@angular/core';
import {TabId} from "../carousel-tabs/carousel-tabs.component";
@Component({
selector: 'app-carousel-tab',
standalone: true,
imports: [],
templateUrl: './carousel-tab.component.html',
styleUrl: './carousel-tab.component.scss',
changeDetection: ChangeDetectionStrategy.OnPush
})
export class CarouselTabComponent {
@Input({required: true}) id!: TabId;
@ContentChild(TemplateRef, {static: true}) implicitContent!: TemplateRef<any>;
}

View file

@ -1,27 +0,0 @@
<ng-container *transloco="let t;">
<div class="carousel-tabs-wrapper">
<button class="scroll-button left" (click)="scroll('left')" [class.visible]="showLeftArrow">
<i class="fas fa-chevron-left"></i>
</button>
<div class="carousel-tabs-container" #scrollContainer (scroll)="onScroll()">
<ul ngbNav #nav="ngbNav" [(activeId)]="activeTabId" class="nav nav-tabs mb-2" (navChange)="onNavChange($event)">
@for (tab of tabComponents; track tab) {
<li [ngbNavItem]="tab.id">
<a ngbNavLink>{{t('tabs.' + tab.id)}}</a>
<ng-template ngbNavContent>
<!-- <ng-container [ngTemplateOutlet]="tab.contentTemplate"></ng-container>-->
<ng-content select="app-carousel-tab[id='{{tab.id}}']"></ng-content>
</ng-template>
</li>
}
</ul>
</div>
<button class="scroll-button right" (click)="scroll('right')" [class.visible]="showRightArrow">
<i class="fas fa-chevron-right"></i>
</button>
</div>
<div [ngbNavOutlet]="nav" style="min-height: 300px"></div>
</ng-container>

View file

@ -1,45 +0,0 @@
.carousel-tabs-wrapper {
position: relative;
display: flex;
align-items: center;
}
.carousel-tabs-container {
overflow-x: auto;
white-space: nowrap;
-webkit-overflow-scrolling: touch;
-ms-overflow-style: -ms-autohiding-scrollbar;
scrollbar-width: none;
flex-grow: 1;
}
.carousel-tabs-container::-webkit-scrollbar {
display: none;
}
.nav-tabs {
flex-wrap: nowrap;
}
.scroll-button {
position: absolute;
top: 50%;
transform: translateY(-50%);
background-color: rgba(255, 255, 255, 0.7);
border: none;
border-radius: 50%;
width: 30px;
height: 30px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
opacity: 0;
transition: opacity 0.3s ease;
z-index: 1;
}
.scroll-button.left {
left: 0;
}
.scroll-button.right {
right: 0;
}
.scroll-button.visible {
opacity: 1;
}

View file

@ -1,127 +0,0 @@
import {
AfterViewInit,
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
ContentChild,
ContentChildren, ElementRef, EventEmitter, HostListener,
inject, Input, OnInit, Output, QueryList,
TemplateRef, ViewChild
} from '@angular/core';
import {
NgbNav,
NgbNavChangeEvent,
NgbNavContent,
NgbNavItem,
NgbNavLink,
NgbNavOutlet
} from "@ng-bootstrap/ng-bootstrap";
import {CarouselTabComponent} from "../carousel-tab/carousel-tab.component";
import {TranslocoDirective} from "@jsverse/transloco";
import {NgTemplateOutlet} from "@angular/common";
/**
* Any Tabs that use this Carousel should use these
*/
export enum TabId {
Related = 'related-tab',
Reviews = 'review-tab', // Only applicable for books
Details = 'details-tab',
Chapters = 'chapters-tab',
}
@Component({
selector: 'app-carousel-tabs',
standalone: true,
imports: [
NgbNav,
TranslocoDirective,
NgbNavItem,
NgbNavLink,
NgTemplateOutlet,
NgbNavOutlet,
NgbNavContent
],
templateUrl: './carousel-tabs.component.html',
styleUrl: './carousel-tabs.component.scss',
changeDetection: ChangeDetectionStrategy.OnPush
})
export class CarouselTabsComponent implements OnInit, AfterViewInit {
private readonly cdRef = inject(ChangeDetectorRef);
@ContentChildren(CarouselTabComponent) tabComponents!: QueryList<CarouselTabComponent>;
@Input({required: true}) activeTabId!: TabId;
@Output() activeTabIdChange = new EventEmitter<TabId>();
@Output() navChange = new EventEmitter<NgbNavChangeEvent>();
@ViewChild('scrollContainer') scrollContainer: ElementRef | undefined;
tabs: { id: TabId; contentTemplate: any }[] = [];
showLeftArrow = false;
showRightArrow = false;
ngOnInit() {
this.checkOverflow();
}
ngAfterViewInit() {
this.initializeTabs();
this.scrollToActiveTab();
this.checkOverflow();
}
initializeTabs() {
this.tabs = this.tabComponents.map(tabComponent => ({
id: tabComponent.id,
contentTemplate: tabComponent.implicitContent
}));
this.cdRef.markForCheck();
}
@HostListener('window:resize')
onResize() {
this.checkOverflow();
}
onNavChange(event: NgbNavChangeEvent) {
this.activeTabIdChange.emit(event.nextId);
this.navChange.emit(event);
this.scrollToActiveTab();
}
onScroll() {
this.checkOverflow();
}
scrollToActiveTab() {
setTimeout(() => {
const activeTab = this.scrollContainer?.nativeElement.querySelector('.active');
if (activeTab) {
activeTab.scrollIntoView({ behavior: 'smooth', inline: 'center', block: 'nearest' });
}
this.checkOverflow();
});
}
checkOverflow() {
const element = this.scrollContainer?.nativeElement;
if (!element) return;
this.showLeftArrow = element.scrollLeft > 0;
this.showRightArrow = element.scrollLeft < element.scrollWidth - element.clientWidth;
this.cdRef.markForCheck();
}
scroll(direction: 'left' | 'right') {
const element = this.scrollContainer?.nativeElement;
if (!element) return;
const scrollAmount = element.clientWidth / 2;
if (direction === 'left') {
element.scrollBy({ left: -scrollAmount, behavior: 'smooth' });
} else {
element.scrollBy({ left: scrollAmount, behavior: 'smooth' });
}
}
}