Bugfix/fix carousel component (#3709)
* Fix carousel component * Update changelog
This commit is contained in:
parent
d6dbc0d9e3
commit
8018236942
@ -29,6 +29,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
- Fixed an issue in the view mode toggle of the holdings tab on the home page (experimental)
|
- Fixed an issue in the view mode toggle of the holdings tab on the home page (experimental)
|
||||||
- Fixed an issue on the portfolio activities page by loading the data only once
|
- Fixed an issue on the portfolio activities page by loading the data only once
|
||||||
|
- Fixed an issue in the carousel component for the testimonial section on the landing page
|
||||||
|
|
||||||
## 2.105.0 - 2024-08-21
|
## 2.105.0 - 2024-08-21
|
||||||
|
|
||||||
|
@ -331,7 +331,7 @@
|
|||||||
<div class="col-md-8 offset-md-2">
|
<div class="col-md-8 offset-md-2">
|
||||||
<gf-carousel [aria-label]="'Testimonials'">
|
<gf-carousel [aria-label]="'Testimonials'">
|
||||||
@for (testimonial of testimonials; track testimonial) {
|
@for (testimonial of testimonials; track testimonial) {
|
||||||
<div gf-carousel-item>
|
<div #carouselItem gf-carousel-item>
|
||||||
<div class="d-flex px-4">
|
<div class="d-flex px-4">
|
||||||
<gf-logo
|
<gf-logo
|
||||||
class="mr-3 mt-2 pt-1"
|
class="mr-3 mt-2 pt-1"
|
||||||
|
@ -1,16 +1,8 @@
|
|||||||
import { FocusableOption } from '@angular/cdk/a11y';
|
import { Directive, ElementRef } from '@angular/core';
|
||||||
import { Directive, ElementRef, HostBinding } from '@angular/core';
|
|
||||||
|
|
||||||
@Directive({
|
@Directive({
|
||||||
selector: '[gf-carousel-item]'
|
selector: '[gf-carousel-item]'
|
||||||
})
|
})
|
||||||
export class CarouselItem implements FocusableOption {
|
export class CarouselItem {
|
||||||
@HostBinding('attr.role') readonly role = 'listitem';
|
|
||||||
@HostBinding('tabindex') tabindex = '-1';
|
|
||||||
|
|
||||||
public constructor(readonly element: ElementRef<HTMLElement>) {}
|
public constructor(readonly element: ElementRef<HTMLElement>) {}
|
||||||
|
|
||||||
public focus() {
|
|
||||||
this.element.nativeElement.focus({ preventScroll: true });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -11,12 +11,7 @@
|
|||||||
</button>
|
</button>
|
||||||
}
|
}
|
||||||
|
|
||||||
<div
|
<div #contentWrapper class="overflow-hidden" role="region">
|
||||||
#contentWrapper
|
|
||||||
class="overflow-hidden"
|
|
||||||
role="region"
|
|
||||||
(keyup)="onKeydown($event)"
|
|
||||||
>
|
|
||||||
<div #list class="d-flex carousel-content" role="list" tabindex="0">
|
<div #list class="d-flex carousel-content" role="list" tabindex="0">
|
||||||
<ng-content></ng-content>
|
<ng-content></ng-content>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,24 +1,18 @@
|
|||||||
import { FocusKeyManager } from '@angular/cdk/a11y';
|
|
||||||
import { LEFT_ARROW, RIGHT_ARROW, TAB } from '@angular/cdk/keycodes';
|
|
||||||
import {
|
import {
|
||||||
AfterContentInit,
|
|
||||||
CUSTOM_ELEMENTS_SCHEMA,
|
CUSTOM_ELEMENTS_SCHEMA,
|
||||||
ChangeDetectionStrategy,
|
ChangeDetectionStrategy,
|
||||||
Component,
|
Component,
|
||||||
ContentChildren,
|
contentChildren,
|
||||||
ElementRef,
|
ElementRef,
|
||||||
HostBinding,
|
HostBinding,
|
||||||
Inject,
|
Inject,
|
||||||
Input,
|
Input,
|
||||||
Optional,
|
Optional,
|
||||||
QueryList,
|
|
||||||
ViewChild
|
ViewChild
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import { MatButtonModule } from '@angular/material/button';
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
import { ANIMATION_MODULE_TYPE } from '@angular/platform-browser/animations';
|
import { ANIMATION_MODULE_TYPE } from '@angular/platform-browser/animations';
|
||||||
|
|
||||||
import { CarouselItem } from './carousel-item.directive';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
imports: [MatButtonModule],
|
imports: [MatButtonModule],
|
||||||
@ -28,9 +22,7 @@ import { CarouselItem } from './carousel-item.directive';
|
|||||||
styleUrls: ['./carousel.component.scss'],
|
styleUrls: ['./carousel.component.scss'],
|
||||||
templateUrl: './carousel.component.html'
|
templateUrl: './carousel.component.html'
|
||||||
})
|
})
|
||||||
export class GfCarouselComponent implements AfterContentInit {
|
export class GfCarouselComponent {
|
||||||
@ContentChildren(CarouselItem) public items!: QueryList<CarouselItem>;
|
|
||||||
|
|
||||||
@HostBinding('class.animations-disabled')
|
@HostBinding('class.animations-disabled')
|
||||||
public readonly animationsDisabled: boolean;
|
public readonly animationsDisabled: boolean;
|
||||||
|
|
||||||
@ -38,11 +30,11 @@ export class GfCarouselComponent implements AfterContentInit {
|
|||||||
|
|
||||||
@ViewChild('list') public list!: ElementRef<HTMLElement>;
|
@ViewChild('list') public list!: ElementRef<HTMLElement>;
|
||||||
|
|
||||||
|
public items = contentChildren('carouselItem', { read: ElementRef });
|
||||||
public showPrevArrow = false;
|
public showPrevArrow = false;
|
||||||
public showNextArrow = true;
|
public showNextArrow = true;
|
||||||
|
|
||||||
private index = 0;
|
private index = 0;
|
||||||
private keyManager!: FocusKeyManager<CarouselItem>;
|
|
||||||
private position = 0;
|
private position = 0;
|
||||||
|
|
||||||
public constructor(
|
public constructor(
|
||||||
@ -51,12 +43,8 @@ export class GfCarouselComponent implements AfterContentInit {
|
|||||||
this.animationsDisabled = animationsModule === 'NoopAnimations';
|
this.animationsDisabled = animationsModule === 'NoopAnimations';
|
||||||
}
|
}
|
||||||
|
|
||||||
public ngAfterContentInit() {
|
|
||||||
this.keyManager = new FocusKeyManager<CarouselItem>(this.items);
|
|
||||||
}
|
|
||||||
|
|
||||||
public next() {
|
public next() {
|
||||||
for (let i = this.index; i < this.items.length; i++) {
|
for (let i = this.index; i < this.items().length; i++) {
|
||||||
if (this.isOutOfView(i)) {
|
if (this.isOutOfView(i)) {
|
||||||
this.index = i;
|
this.index = i;
|
||||||
this.scrollToActiveItem();
|
this.scrollToActiveItem();
|
||||||
@ -65,31 +53,6 @@ export class GfCarouselComponent implements AfterContentInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public onKeydown({ keyCode }: KeyboardEvent) {
|
|
||||||
const manager = this.keyManager;
|
|
||||||
const previousActiveIndex = manager.activeItemIndex;
|
|
||||||
|
|
||||||
if (keyCode === LEFT_ARROW) {
|
|
||||||
manager.setPreviousItemActive();
|
|
||||||
} else if (keyCode === RIGHT_ARROW) {
|
|
||||||
manager.setNextItemActive();
|
|
||||||
} else if (keyCode === TAB && !manager.activeItem) {
|
|
||||||
manager.setFirstItemActive();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
manager.activeItemIndex != null &&
|
|
||||||
manager.activeItemIndex !== previousActiveIndex
|
|
||||||
) {
|
|
||||||
this.index = manager.activeItemIndex;
|
|
||||||
this.updateItemTabIndices();
|
|
||||||
|
|
||||||
if (this.isOutOfView(this.index)) {
|
|
||||||
this.scrollToActiveItem();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public previous() {
|
public previous() {
|
||||||
for (let i = this.index; i > -1; i--) {
|
for (let i = this.index; i > -1; i--) {
|
||||||
if (this.isOutOfView(i)) {
|
if (this.isOutOfView(i)) {
|
||||||
@ -101,8 +64,7 @@ export class GfCarouselComponent implements AfterContentInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private isOutOfView(index: number, side?: 'start' | 'end') {
|
private isOutOfView(index: number, side?: 'start' | 'end') {
|
||||||
const { offsetWidth, offsetLeft } =
|
const { offsetWidth, offsetLeft } = this.items()[index].nativeElement;
|
||||||
this.items.toArray()[index].element.nativeElement;
|
|
||||||
|
|
||||||
if ((!side || side === 'start') && offsetLeft - this.position < 0) {
|
if ((!side || side === 'start') && offsetLeft - this.position < 0) {
|
||||||
return true;
|
return true;
|
||||||
@ -120,33 +82,23 @@ export class GfCarouselComponent implements AfterContentInit {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const itemsArray = this.items.toArray();
|
|
||||||
let targetItemIndex = this.index;
|
let targetItemIndex = this.index;
|
||||||
|
|
||||||
if (this.index > 0 && !this.isOutOfView(this.index - 1)) {
|
if (this.index > 0 && !this.isOutOfView(this.index - 1)) {
|
||||||
targetItemIndex =
|
targetItemIndex =
|
||||||
itemsArray.findIndex((_, i) => !this.isOutOfView(i)) + 1;
|
this.items().findIndex((_, i) => !this.isOutOfView(i)) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.position =
|
this.position = this.items()[targetItemIndex].nativeElement.offsetLeft;
|
||||||
itemsArray[targetItemIndex].element.nativeElement.offsetLeft;
|
|
||||||
this.list.nativeElement.style.transform = `translateX(-${this.position}px)`;
|
this.list.nativeElement.style.transform = `translateX(-${this.position}px)`;
|
||||||
this.showPrevArrow = this.index > 0;
|
this.showPrevArrow = this.index > 0;
|
||||||
this.showNextArrow = false;
|
this.showNextArrow = false;
|
||||||
|
|
||||||
for (let i = itemsArray.length - 1; i > -1; i--) {
|
for (let i = this.items().length - 1; i > -1; i--) {
|
||||||
if (this.isOutOfView(i, 'end')) {
|
if (this.isOutOfView(i, 'end')) {
|
||||||
this.showNextArrow = true;
|
this.showNextArrow = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private updateItemTabIndices() {
|
|
||||||
this.items.forEach((item: CarouselItem) => {
|
|
||||||
if (this.keyManager != null) {
|
|
||||||
item.tabindex = item === this.keyManager.activeItem ? '0' : '-1';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user