1
1
import {
2
2
AfterContentInit ,
3
3
Component ,
4
+ DestroyRef ,
4
5
ElementRef ,
5
6
EventEmitter ,
6
7
HostBinding ,
8
+ inject ,
7
9
Inject ,
8
10
Input ,
9
11
OnDestroy ,
10
12
OnInit ,
11
13
Output
12
14
} from '@angular/core' ;
13
- import { fromEvent , Subscription , withLatestFrom , zipWith } from 'rxjs' ;
15
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop' ;
16
+ import { finalize , fromEvent , Subscription , withLatestFrom , zipWith } from 'rxjs' ;
14
17
15
18
import { IntersectionService } from '../../services/intersection.service' ;
16
19
import { IListenersConfig , ListenersService } from '../../services/listeners.service' ;
@@ -24,7 +27,7 @@ import { Triggers } from '../../coreui.types';
24
27
selector : 'c-carousel' ,
25
28
template : '<ng-content></ng-content>' ,
26
29
styleUrls : [ './carousel.component.scss' ] ,
27
- providers : [ CarouselService , CarouselState , CarouselConfig , IntersectionService , ListenersService ] ,
30
+ providers : [ CarouselService , CarouselState , CarouselConfig , ListenersService ] ,
28
31
standalone : true
29
32
} )
30
33
export class CarouselComponent implements OnInit , OnDestroy , AfterContentInit {
@@ -93,11 +96,10 @@ export class CarouselComponent implements OnInit, OnDestroy, AfterContentInit {
93
96
} ;
94
97
}
95
98
96
- private carouselIndexSubscription ?: Subscription ;
97
99
private timerId ! : any ;
98
- private intersectingSubscription ?: Subscription ;
99
100
private activeItemInterval = 0 ;
100
101
private swipeSubscription ?: Subscription ;
102
+ readonly #destroyRef = inject ( DestroyRef ) ;
101
103
102
104
constructor (
103
105
@Inject ( CarouselConfig ) private config : CarouselConfig ,
@@ -116,13 +118,10 @@ export class CarouselComponent implements OnInit, OnDestroy, AfterContentInit {
116
118
117
119
ngOnDestroy ( ) : void {
118
120
this . clearListeners ( ) ;
119
- this . carouselStateSubscribe ( false ) ;
120
- this . intersectionServiceSubscribe ( false ) ;
121
121
this . swipeSubscribe ( false ) ;
122
122
}
123
123
124
124
ngAfterContentInit ( ) : void {
125
- this . intersectionService . createIntersectionObserver ( this . hostElement ) ;
126
125
this . intersectionServiceSubscribe ( ) ;
127
126
this . carouselState . state = { activeItemIndex : this . activeIndex , animate : this . animate } ;
128
127
this . setListeners ( ) ;
@@ -172,30 +171,34 @@ export class CarouselComponent implements OnInit, OnDestroy, AfterContentInit {
172
171
clearTimeout ( this . timerId ) ;
173
172
}
174
173
175
- private carouselStateSubscribe ( subscribe : boolean = true ) : void {
176
- if ( subscribe ) {
177
- this . carouselIndexSubscription = this . carouselService . carouselIndex$ . subscribe ( ( nextItem ) => {
174
+ private carouselStateSubscribe ( ) : void {
175
+ this . carouselService . carouselIndex$
176
+ . pipe (
177
+ takeUntilDestroyed ( this . #destroyRef)
178
+ )
179
+ . subscribe ( ( nextItem ) => {
178
180
if ( 'active' in nextItem ) {
179
181
this . itemChange . emit ( nextItem . active ) ;
180
182
}
181
183
this . activeItemInterval = typeof nextItem . interval === 'number' && nextItem . interval > - 1 ? nextItem . interval : this . interval ;
182
184
const isLastItem = ( ( nextItem . active === nextItem . lastItemIndex ) && this . direction === 'next' ) || ( ( nextItem . active === 0 ) && this . direction === 'prev' ) ;
183
185
! this . wrap && isLastItem ? this . resetTimer ( ) : this . setTimer ( ) ;
184
186
} ) ;
185
- } else {
186
- this . carouselIndexSubscription ?. unsubscribe ( ) ;
187
- }
188
187
}
189
188
190
189
private intersectionServiceSubscribe ( subscribe : boolean = true ) : void {
191
- if ( subscribe ) {
192
- this . intersectingSubscription = this . intersectionService . intersecting$ . subscribe ( isIntersecting => {
190
+ this . intersectionService . createIntersectionObserver ( this . hostElement ) ;
191
+ this . intersectionService . intersecting$
192
+ . pipe (
193
+ finalize ( ( ) => {
194
+ this . intersectionService . unobserve ( this . hostElement ) ;
195
+ } ) ,
196
+ takeUntilDestroyed ( this . #destroyRef)
197
+ )
198
+ . subscribe ( isIntersecting => {
193
199
this . visible = isIntersecting ;
194
200
isIntersecting ? this . setTimer ( ) : this . resetTimer ( ) ;
195
201
} ) ;
196
- } else {
197
- this . intersectingSubscription ?. unsubscribe ( ) ;
198
- }
199
202
}
200
203
201
204
private swipeSubscribe ( subscribe : boolean = true ) : void {
@@ -204,7 +207,10 @@ export class CarouselComponent implements OnInit, OnDestroy, AfterContentInit {
204
207
const touchStart$ = fromEvent < TouchEvent > ( carouselElement , 'touchstart' ) ;
205
208
const touchEnd$ = fromEvent < TouchEvent > ( carouselElement , 'touchend' ) ;
206
209
const touchMove$ = fromEvent < TouchEvent > ( carouselElement , 'touchmove' ) ;
207
- this . swipeSubscription = touchStart$ . pipe ( zipWith ( touchEnd$ . pipe ( withLatestFrom ( touchMove$ ) ) ) )
210
+ this . swipeSubscription = touchStart$ . pipe (
211
+ zipWith ( touchEnd$ . pipe ( withLatestFrom ( touchMove$ ) ) ) ,
212
+ takeUntilDestroyed ( this . #destroyRef)
213
+ )
208
214
. subscribe ( ( [ touchstart , [ touchend , touchmove ] ] ) => {
209
215
touchstart . stopPropagation ( ) ;
210
216
touchmove . stopPropagation ( ) ;
0 commit comments