@ngfly/carousel
Version:
A smooth, customizable carousel component for Angular 17+ applications
1 lines • 41.3 kB
JavaScript
import*as t from"@angular/core";import{Injectable as e,inject as i,ChangeDetectorRef as n,NgZone as s,Component as o,Input as r,ContentChild as a,ViewChild as l,Directive as c,NgModule as d}from"@angular/core";import{__rest as h}from"tslib";import*as u from"@angular/common";import{CommonModule as m}from"@angular/common";import{BehaviorSubject as g,Subject as p,fromEvent as v}from"rxjs";import{debounceTime as f,takeUntil as y}from"rxjs/operators";const x={NAVIGATION_SIZE:"32px",CONTENT_PADDING:"10px",ANIMATION_DURATION:"300ms",ANIMATION_TIMING:"ease",EMPTY_STATE_HEIGHT:"200px",NAVIGATION_PREV_ICON:"❮",NAVIGATION_NEXT_ICON:"❯",INDICATOR_SIZE:"10px",INDICATOR_SPACING:"5px",INDICATOR_ACTIVE_COLOR:"#333",INDICATOR_INACTIVE_COLOR:"#ccc",INDICATOR_ACTIVE_OPACITY:"1",INDICATOR_INACTIVE_OPACITY:"0.5",INDICATOR_ANIMATION_DURATION:"250ms",INDICATOR_ANIMATION_TIMING:"ease",INDICATOR_TRANSITION:"all 0.3s ease-in-out"};class I{constructor(){this.isVisibleSubject=new g(!0),this.isVisible$=this.isVisibleSubject.asObservable()}setVisibility(t){this.isVisibleSubject.next(t)}getButtonShapeStyles(t){const e={};switch(t){case"circle":e.borderRadius="50%";break;case"rounded":e.borderRadius="8px";break;default:e.borderRadius="0"}return e}getIndicatorStyles(t,e=!1){var i,n,s,o;const r={width:x.INDICATOR_SIZE,height:x.INDICATOR_SIZE,display:"inline-block",transition:(null==t?void 0:t.transition)||((null===(i=null==t?void 0:t.animation)||void 0===i?void 0:i.timing)?`all ${t.animation.duration||x.INDICATOR_ANIMATION_DURATION} ${t.animation.timing}`:x.INDICATOR_TRANSITION),cursor:"pointer",margin:`0 ${(null==t?void 0:t.spacing)||x.INDICATOR_SPACING}`,borderRadius:"50%"};if(e){r.backgroundColor=x.INDICATOR_ACTIVE_COLOR,r.opacity=x.INDICATOR_ACTIVE_OPACITY,r.transform="scale(1.2)";const e=!1!==(null===(n=null==t?void 0:t.animation)||void 0===n?void 0:n.enabled),i=(null===(s=null==t?void 0:t.animation)||void 0===s?void 0:s.type)||"pulse";e&&"none"!==i&&("custom"===i&&(null===(o=null==t?void 0:t.animation)||void 0===o?void 0:o.custom)?r.animation=t.animation.custom:"pulse"===i&&(r.animation="indicator-pulse 1s infinite alternate")),(null==t?void 0:t.active)&&Object.assign(r,t.active)}else r.backgroundColor=x.INDICATOR_INACTIVE_COLOR,r.opacity=x.INDICATOR_INACTIVE_OPACITY,r.transform="scale(1)",(null==t?void 0:t.inactive)&&Object.assign(r,t.inactive);return r}getIndicatorContainerStyles(t){var e,i;const n={position:"absolute",display:"flex",justifyContent:"center",alignItems:"center",zIndex:"100",padding:"10px",pointerEvents:"auto"};return n.bottom=(null===(e=null==t?void 0:t.position)||void 0===e?void 0:e.bottom)||"4px",n.left=(null===(i=null==t?void 0:t.position)||void 0===i?void 0:i.left)||"50%",n.transform="translateX(-50%)",(null==t?void 0:t.position)&&(Object.keys(t.position).forEach((e=>{const i=t.position;i[e]&&(n[e]=i[e])})),"50%"!==t.position.left||n.transform?"50%"!==t.position.top||n.transform||(n.transform="translateY(-50%)"):n.transform="translateX(-50%)"),(null==t?void 0:t.container)&&Object.assign(n,t.container),n}getNavigationIcons(t,e){const i={horizontal:{prev:x.NAVIGATION_PREV_ICON,next:x.NAVIGATION_NEXT_ICON},vertical:{prev:x.NAVIGATION_PREV_ICON,next:x.NAVIGATION_NEXT_ICON}},n=e||{},s=n.vertical||{};return{prev:t?s.prev||i.vertical.prev:n.prev||i.horizontal.prev,next:t?s.next||i.vertical.next:n.next||i.horizontal.next}}parseTimeToMs(t){return t?t.endsWith("ms")?parseInt(t.slice(0,-2),10):t.endsWith("s")?1e3*parseFloat(t.slice(0,-1)):parseInt(t,10):300}}I.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"14.3.0",ngImport:t,type:I,deps:[],target:t.ɵɵFactoryTarget.Injectable}),I.ɵprov=t.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"14.3.0",ngImport:t,type:I,providedIn:"root"}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"14.3.0",ngImport:t,type:I,decorators:[{type:e,args:[{providedIn:"root"}]}]});const b={linear:t=>t,ease:t=>t,easeInQuad:t=>t*t,easeOutQuad:t=>t*(2-t),easeInOutQuad:t=>t<.5?2*t*t:(4-2*t)*t-1,easeInCubic:t=>t*t*t,easeOutCubic:t=>--t*t*t+1,easeInOutCubic:t=>t<.5?4*t*t*t:(t-1)*(2*t-2)*(2*t-2)+1};function _(t){switch(t){case"linear":return b.linear;case"ease-in":return b.easeInQuad;case"ease-out":return b.easeOutQuad;case"ease-in-out":default:return b.easeInOutQuad;case"ease":return b.ease}}function w(t,e){return e?`translateY(-${t}px)`:`translateX(-${t}px)`}function S(t,e=300){return t?t.endsWith("ms")?parseInt(t,10):t.endsWith("s")?1e3*parseFloat(t):parseInt(t,10)||e:e}function T(t,e,i,n=.8){if(!t)return e*n;if(t.endsWith("%")){return e*(parseFloat(t)/100)}return i[t]?i[t]:t.endsWith("px")?parseFloat(t):e*n}function O(t,e,i=300,n=b.easeInOutQuad){return new Promise((s=>{const o=t.scrollLeft,r=e-o,a=performance.now();requestAnimationFrame((function l(c){const d=c-a;if(d>=i)return t.scrollLeft=e,void s();const h=n(d/i);t.scrollLeft=o+r*h,requestAnimationFrame(l)}))}))}function C(t,e,i=300,n=b.easeInOutQuad){return new Promise((s=>{const o=t.scrollTop,r=e-o,a=performance.now();requestAnimationFrame((function l(c){const d=c-a;if(d>=i)return t.scrollTop=e,void s();const h=n(d/i);t.scrollTop=o+r*h,requestAnimationFrame(l)}))}))}class N{constructor(){this.cdr=i(n),this.ngZone=i(s),this.carouselService=i(I),this.slides=[],this.configs={},this.currentTranslate=0,this.currentIndex=0,this.destroy$=new p,this.itemWidths=[],this.itemHeights=[],this.containerWidth=0,this.containerHeight=0,this.intersectionObserver=null,this.resizeObserver=null,this.visibilityChangeTimeout=null,this.initialized=!1,this.scrollSizeMap={xs:50,sm:100,md:150,lg:200,xl:250,"2xl":300,"3xl":350,"4xl":400,"5xl":450,"6xl":500,"7xl":550,"8xl":600,"9xl":650,"10xl":700,full:1},this.showPrevButton=!1,this.showNextButton=!1,this.filteredItems=[],this.emptyStateText="No items found",this.emptyStateIcon="📭",this.emptyStateTextColor="#666",this.showEmptyStateIcon=!0}ngOnInit(){this.filteredItems=this.slides||[];this.filteredItems.length>1&&(this.showPrevButton=!0,this.showNextButton=!0),this.configs.emptyState&&(this.emptyStateText=this.configs.emptyState.text||this.emptyStateText,this.emptyStateIcon=this.configs.emptyState.icon||this.emptyStateIcon,this.emptyStateTextColor=this.configs.emptyState.textColor||this.emptyStateTextColor,this.showEmptyStateIcon=!this.configs.emptyState.hideIcon)}ngOnChanges(t){t.slides&&(this.filteredItems=this.slides||[],this.initialized&&setTimeout((()=>{this.updateContainerDimensions(),this.calculateItemDimensions(),this.checkOverflow(),this.cdr.detectChanges()}))),t.configs&&this.initialized&&setTimeout((()=>{this.updateContainerDimensions(),this.calculateItemDimensions(),this.checkOverflow(),this.setupAutoplay(),this.cdr.detectChanges()}))}setupAutoplay(){if(this.clearAutoplayInterval(),!this.configs.autoplay)return;const t=this.carouselService.parseTimeToMs(this.configs.autoplayDelay||"3000ms");this.autoplayInterval=setInterval((()=>{var t,e;const i=null===(t=this.trackElement)||void 0===t?void 0:t.nativeElement,n=null===(e=this.wrapperElement)||void 0===e?void 0:e.nativeElement;if(!i||!n)return;const s=this.isVertical?i.offsetHeight-n.offsetHeight:i.offsetWidth-n.offsetWidth;if(this.currentTranslate>=s){if(!this.configs.loop)return void this.clearAutoplayInterval();this.currentTranslate=0,this.currentIndex=0}else this.next();this.cdr.detectChanges()}),t)}clearAutoplayInterval(){this.autoplayInterval&&(clearInterval(this.autoplayInterval),this.autoplayInterval=void 0)}ngAfterViewInit(){this.ngZone.runOutsideAngular((()=>{setTimeout((()=>{this.ngZone.run((()=>{this.initializeCarousel(),this.setupResizeListener(),this.setupIntersectionObserver(),this.setupResizeObserver(),this.updateContainerDimensions(),this.calculateItemDimensions(),this.checkOverflow(),this.initialized=!0,this.cdr.detectChanges(),setTimeout((()=>{this.setupAutoplay()})),setTimeout((()=>{this.updateContainerDimensions(),this.calculateItemDimensions(),this.checkOverflow(),this.cdr.detectChanges()}),100)}))}))}))}ngOnDestroy(){this.autoplayInterval&&(clearInterval(this.autoplayInterval),this.autoplayInterval=void 0),this.intersectionObserver&&(this.intersectionObserver.disconnect(),this.intersectionObserver=null),this.resizeObserver&&(this.resizeObserver.disconnect(),this.resizeObserver=null),this.visibilityChangeTimeout&&(clearTimeout(this.visibilityChangeTimeout),this.visibilityChangeTimeout=null),this.destroy$.next(),this.destroy$.complete(),this.itemWidths=[],this.itemHeights=[],this.filteredItems=[]}get isVertical(){return"vertical"===this.configs.orientation}get containerStyles(){const t=this.configs.containerStyle||{};return"width"in t||(t.width=this.configs.containerWidth||"100%"),"height"in t||(t.height=this.configs.containerHeight||"auto"),t}get trackStyles(){const t={transform:w(this.currentTranslate,this.isVertical)};return this.isVertical?Object.assign(Object.assign({},t),{flexDirection:"column"}):t}initializeCarousel(){this.trackElement&&this.wrapperElement&&(this.currentTranslate=0,this.currentIndex=0,this.checkOverflow())}setupResizeListener(){v(window,"resize").pipe(f(200),y(this.destroy$)).subscribe((()=>{this.updateContainerDimensions(),this.calculateItemDimensions(),this.checkOverflow()}))}setupIntersectionObserver(){"IntersectionObserver"in window&&this.ngZone.runOutsideAngular((()=>{var t;this.intersectionObserver=new IntersectionObserver((t=>{var e;(null===(e=t[0])||void 0===e?void 0:e.isIntersecting)&&this.initialized&&this.ngZone.run((()=>{this.visibilityChangeTimeout=setTimeout((()=>{this.updateContainerDimensions(),this.calculateItemDimensions(),this.checkOverflow()}),50)}))}),{threshold:.1}),(null===(t=this.wrapperElement)||void 0===t?void 0:t.nativeElement)&&this.intersectionObserver.observe(this.wrapperElement.nativeElement)}))}setupResizeObserver(){"ResizeObserver"in window&&this.ngZone.runOutsideAngular((()=>{var t;this.resizeObserver=new ResizeObserver((()=>{this.initialized&&this.ngZone.run((()=>{this.updateContainerDimensions(),this.calculateItemDimensions(),this.checkOverflow()}))})),(null===(t=this.wrapperElement)||void 0===t?void 0:t.nativeElement)&&this.resizeObserver.observe(this.wrapperElement.nativeElement)}))}updateContainerDimensions(){this.wrapperElement&&(this.containerWidth=this.wrapperElement.nativeElement.offsetWidth,this.containerHeight=this.wrapperElement.nativeElement.offsetHeight)}checkOverflow(){var t,e,i;if(!this.initialized&&!(null===(t=this.trackElement)||void 0===t?void 0:t.nativeElement))return;if(this.filteredItems.length>1&&this.configs.singleItemMode)return this.configs.loop?(this.showPrevButton=!0,void(this.showNextButton=!0)):(this.showPrevButton=this.currentIndex>0,void(this.showNextButton=this.currentIndex<this.filteredItems.length-1));if(!this.showNavigation||this.filteredItems.length<=1)return this.showPrevButton=!1,void(this.showNextButton=!1);const n=null===(e=this.trackElement)||void 0===e?void 0:e.nativeElement,s=null===(i=this.wrapperElement)||void 0===i?void 0:i.nativeElement;if(n&&s&&0!==s.offsetWidth&&0!==s.offsetHeight){if(this.configs.loop&&this.filteredItems.length>1)this.showPrevButton=!0,this.showNextButton=!0;else if(this.showPrevButton=this.currentTranslate>0,this.isVertical){const t=n.offsetHeight,e=s.offsetHeight;this.showNextButton=t-this.currentTranslate>e+1}else{const t=n.offsetWidth,e=s.offsetWidth;this.showNextButton=t-this.currentTranslate>e+1}this.cdr.detectChanges()}}calculateItemDimensions(){if(!this.trackElement||!this.wrapperElement)return;const t=this.wrapperElement.nativeElement,e=t.offsetHeight,i=t.offsetWidth;this.containerWidth=i,this.containerHeight=e;const n=Array.from(this.trackElement.nativeElement.children);0!==n.length&&setTimeout((()=>{if(this.configs.singleItemMode)return this.isVertical?(this.itemHeights=n.map((()=>e)),this.itemWidths=n.map((t=>{const e=window.getComputedStyle(t);return t.offsetWidth+parseInt(e.marginLeft||"0",10)+parseInt(e.marginRight||"0",10)}))):(this.itemWidths=n.map((()=>i)),this.itemHeights=n.map((t=>{const e=window.getComputedStyle(t);return t.offsetHeight+parseInt(e.marginTop||"0",10)+parseInt(e.marginBottom||"0",10)}))),this.updateTranslatePosition(),void this.cdr.detectChanges();this.itemWidths=n.map((t=>{const e=window.getComputedStyle(t);return t.offsetWidth+parseInt(e.marginLeft||"0",10)+parseInt(e.marginRight||"0",10)})),this.itemHeights=n.map((t=>{const e=window.getComputedStyle(t);return t.offsetHeight+parseInt(e.marginTop||"0",10)+parseInt(e.marginBottom||"0",10)})),this.cdr.detectChanges()}),50)}getScrollAmount(){var t;const e=null===(t=this.wrapperElement)||void 0===t?void 0:t.nativeElement;if(!e)return 0;if(this.configs.singleItemMode){if(this.isVertical&&this.itemHeights.length>0)return this.currentIndex<this.itemHeights.length?this.itemHeights[this.currentIndex]:this.itemHeights[0]||e.offsetHeight;if(this.itemWidths.length>0)return this.currentIndex<this.itemWidths.length?this.itemWidths[this.currentIndex]:this.itemWidths[0]||e.offsetWidth}const i=this.configs.scrollSize||"sm";if("full"===i)return this.isVertical?e.offsetHeight:e.offsetWidth;if("string"==typeof i&&i.endsWith("%")){const t=parseInt(i,10)/100;return this.isVertical?e.offsetHeight*t:e.offsetWidth*t}return this.scrollSizeMap[i]||this.scrollSizeMap.sm}previous(){if(this.showPrevButton){if(this.configs.singleItemMode)this.currentIndex>0?(this.currentIndex--,this.updateTranslatePosition()):this.configs.loop&&this.filteredItems.length>0&&(this.currentIndex=this.filteredItems.length-1,this.updateTranslatePosition());else{const t=this.getScrollAmount();this.currentTranslate=Math.max(0,this.currentTranslate-t)}this.checkOverflow()}}next(){var t,e;if(!this.showNextButton)return;const i=null===(t=this.trackElement)||void 0===t?void 0:t.nativeElement,n=null===(e=this.wrapperElement)||void 0===e?void 0:e.nativeElement;if(i&&n){if(this.configs.singleItemMode)this.currentIndex<this.filteredItems.length-1?(this.currentIndex++,this.updateTranslatePosition()):this.configs.loop&&this.filteredItems.length>0&&(this.currentIndex=0,this.currentTranslate=0);else{const t=this.getScrollAmount(),e=this.isVertical?i.offsetHeight-n.offsetHeight:i.offsetWidth-n.offsetWidth;this.currentTranslate=Math.min(e,this.currentTranslate+t)}this.checkOverflow()}}updateTranslatePosition(){if(0===this.currentIndex)return void(this.currentTranslate=0);const t=this.configs.itemGap?parseInt(this.configs.itemGap.replace("px",""),10):0;let e=0;for(let i=0;i<this.currentIndex;i++)this.isVertical?e+=(this.itemHeights[i]||0)+t:e+=(this.itemWidths[i]||0)+t;this.currentTranslate=e}getItemStyle(t){const e={flexShrink:"0",flexGrow:"0",boxSizing:"border-box",overflow:"hidden",borderRadius:"inherit"};if(this.configs.itemWidth&&("100%"===this.configs.itemWidth&&this.containerWidth>0?(e.width=this.containerWidth+"px",e.maxWidth="100%"):e.width=this.configs.itemWidth),this.configs.itemHeight?("100%"===this.configs.itemHeight||parseInt(this.configs.itemHeight,10)===this.containerHeight)&&this.containerHeight>0?(e.height=this.containerHeight+"px",e.minHeight=this.containerHeight+"px",e.maxHeight="100%",e.display="flex",e.flexDirection="column",e.alignItems="stretch",e.justifyContent="stretch"):e.height=this.configs.itemHeight:this.isVertical&&this.configs.containerHeight&&(e.height=this.containerHeight+"px",e.minHeight=this.containerHeight+"px"),!this.configs.itemGap)return e;return e[this.isVertical?"marginTop":"marginLeft"]=0===t?"0":this.configs.itemGap,e}get contentPadding(){return this.configs.contentPadding||x.CONTENT_PADDING}get animationDuration(){return this.configs.animationDuration||x.ANIMATION_DURATION}get animationTiming(){return this.configs.animationTiming||x.ANIMATION_TIMING}get showNavigation(){var t;return null===(t=this.configs.showNavigation)||void 0===t||t}getEmptyStateContainerStyle(){var t;return{width:"100%",boxSizing:"border-box",borderRadius:"inherit",backgroundColor:(null===(t=this.configs.emptyState)||void 0===t?void 0:t.backgroundColor)||"transparent"}}hasItems(){var t;return(null===(t=this.filteredItems)||void 0===t?void 0:t.length)>0}getNavControlsClass(){return"carousel__nav-controls"}getNavControlsStyle(){var t;const e={position:"absolute",top:"0",left:"0",width:"100%",height:"100%",pointerEvents:"none"};return(null===(t=this.configs.navigationStyle)||void 0===t?void 0:t.zIndex)&&(e["--carousel-z-index"]=this.configs.navigationStyle.zIndex),e}get prevIcon(){var t;return this.carouselService.getNavigationIcons(this.isVertical,null===(t=this.configs.navigationStyle)||void 0===t?void 0:t.icons).prev}get nextIcon(){var t;return this.carouselService.getNavigationIcons(this.isVertical,null===(t=this.configs.navigationStyle)||void 0===t?void 0:t.icons).next}getIconStyles(t){var e,i,n,s;return{color:t?(null===(i=null===(e=this.configs.navigationStyle)||void 0===e?void 0:e.nextButton)||void 0===i?void 0:i.color)||"#666":(null===(s=null===(n=this.configs.navigationStyle)||void 0===n?void 0:n.prevButton)||void 0===s?void 0:s.color)||"#666"}}getButtonPositionStyle(t){const e=this.configs.navigationStyle,i="prev"===t?(null==e?void 0:e.prevButton)||{}:(null==e?void 0:e.nextButton)||{},n={position:"absolute",pointerEvents:"auto"};["top","bottom","left","right"].forEach((t=>{const e=i[t];void 0!==e&&(n[t]=0===e||"0"===e?"0px":e)}));const s={"left=50%":"translateX(-50%)","right=50%":"translateX(50%)","top=50%":"translateY(-50%)","bottom=50%":"translateY(50%)"};for(const[t,e]of Object.entries(s)){const[s,o]=t.split("=");if(i[s]===o){n.transform=i.transform?`${i.transform} ${e}`:e;break}}!n.transform&&i.transform&&(n.transform=i.transform);return["top","bottom","left","right"].some((t=>void 0!==i[t]))||(this.isVertical?(n.left="50%",n.transform="translateX(-50%)",n["prev"===t?"top":"bottom"]="0px"):(n.top="50%",n.transform="translateY(-50%)",n["prev"===t?"left":"right"]="0px")),n}getButtonFullStyles(t){var e,i,n,s;const o=Object.assign({},this.carouselService.getButtonShapeStyles(null===(e=this.configs.navigationStyle)||void 0===e?void 0:e.buttonShape)),r=null===(i=this.configs.navigationStyle)||void 0===i?void 0:i[`${t}Button`];if(r){const e=this.getButtonPositionStyle(t);Object.assign(o,e);if(null===(n=this.configs.navigationStyle)||void 0===n?void 0:n.buttonShape){const{borderRadius:t}=r,e=h(r,["borderRadius"]);Object.assign(o,e)}else Object.assign(o,r);r.zIndex?o["--carousel-z-index"]=r.zIndex:(null===(s=this.configs.navigationStyle)||void 0===s?void 0:s.zIndex)&&(o["--carousel-z-index"]=this.configs.navigationStyle.zIndex)}return o}getPrevButtonFullStyles(){return this.getButtonFullStyles("prev")}getNextButtonFullStyles(){return this.getButtonFullStyles("next")}getPrevIndex(t){var e;const i=(null===(e=this.filteredItems)||void 0===e?void 0:e.length)||0;return 0===i?t:t>0?t-1:this.configs.loop?i-1:t}goToPrevSlide(){const t=this.getPrevIndex(this.currentIndex);t!==this.currentIndex&&(this.currentIndex=t,this.updateTranslatePosition(),this.checkOverflow())}getIndicatorContainerStyles(){return this.carouselService.getIndicatorContainerStyles(this.configs.indicatorStyle)}getIndicatorItemStyles(t){const e=t===this.currentIndex;return this.carouselService.getIndicatorStyles(this.configs.indicatorStyle,e)}goToSlide(t){var e,i,n;if(t===this.currentIndex||t<0||t>=this.filteredItems.length)return;if(this.currentIndex=t,this.configs.singleItemMode)return this.updateTranslatePosition(),void this.checkOverflow();const s=null===(e=this.trackElement)||void 0===e?void 0:e.nativeElement,o=null===(i=this.wrapperElement)||void 0===i?void 0:i.nativeElement;if(!s||!o)return;const r=parseInt((null===(n=this.configs.itemGap)||void 0===n?void 0:n.replace("px",""))||"0",10),a=(this.isVertical?this.itemHeights:this.itemWidths).slice(0,t).reduce(((t,e)=>t+(e||0)+r),0),l=this.isVertical?s.offsetHeight-o.offsetHeight:s.offsetWidth-o.offsetWidth;this.currentTranslate=Math.min(l,Math.max(0,a)),this.checkOverflow()}get showIndicators(){var t;return null!==(t=this.configs.showIndicators)&&void 0!==t&&t}}N.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"14.3.0",ngImport:t,type:N,deps:[],target:t.ɵɵFactoryTarget.Component}),N.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"14.3.0",type:N,isStandalone:!0,selector:"carousel",inputs:{slides:"slides",configs:"configs"},providers:[I],queries:[{propertyName:"itemTemplate",first:!0,predicate:["carouselItem"],descendants:!0},{propertyName:"emptyStateTemplate",first:!0,predicate:["emptyState"],descendants:!0}],viewQueries:[{propertyName:"trackElement",first:!0,predicate:["track"],descendants:!0},{propertyName:"wrapperElement",first:!0,predicate:["wrapper"],descendants:!0}],usesOnChanges:!0,ngImport:t,template:'<div class="carousel" \n [class.carousel--vertical]="isVertical" \n [ngClass]="configs.containerClass" \n [ngStyle]="containerStyles"\n [style.height]="configs.containerHeight || \'auto\'"\n [style.width]="configs.containerWidth || \'auto\'">\n <div\n #wrapper\n [style.--content-padding]="contentPadding"\n class="carousel__wrapper">\n <div\n #track\n [ngStyle]="trackStyles"\n [class.carousel__track--vertical]="isVertical"\n [style.--animation-duration]="animationDuration"\n [style.--animation-timing]="animationTiming"\n class="carousel__track">\n <ng-container *ngIf="hasItems(); else emptyState">\n <ng-container *ngFor="let slide of filteredItems; let i = index">\n <div class="carousel__item" \n [ngClass]="configs.itemClass" \n [ngStyle]="getItemStyle(i)" \n [style.--item-width]="configs.itemWidth || \'auto\'"\n [style.--item-height]="configs.itemHeight || \'auto\'">\n <ng-container *ngIf="itemTemplate; else defaultTemplate">\n <ng-container *ngTemplateOutlet="itemTemplate; context: { $implicit: slide, index: i }"></ng-container>\n </ng-container>\n <ng-template #defaultTemplate>\n <div class="carousel__item-default">\n {{ slide }}\n </div>\n </ng-template>\n </div>\n </ng-container>\n </ng-container>\n \n <ng-template #emptyState>\n <div class="carousel__empty-container" [ngStyle]="getEmptyStateContainerStyle()">\n <ng-container *ngIf="emptyStateTemplate; else defaultEmptyState">\n <ng-container *ngTemplateOutlet="emptyStateTemplate; context: { $implicit: emptyStateText }"></ng-container>\n </ng-container>\n <ng-template #defaultEmptyState>\n <div class="carousel__empty-state" [style.color]="emptyStateTextColor">\n <div *ngIf="showEmptyStateIcon" class="carousel__empty-icon">{{emptyStateIcon}}</div>\n <div class="carousel__empty-text">{{emptyStateText}}</div>\n </div>\n </ng-template>\n </div>\n </ng-template>\n </div>\n </div>\n\n <div *ngIf="showNavigation && hasItems()" [ngClass]="getNavControlsClass()" [ngStyle]="getNavControlsStyle()"> \n <button \n [class.carousel__nav-button--disabled]="!showPrevButton" \n [disabled]="!showPrevButton" \n [ngStyle]="getPrevButtonFullStyles()" \n (click)="previous()" \n style="pointer-events:auto;"\n class="carousel__nav-button">\n <span class="carousel__nav-icon" [ngStyle]="getIconStyles(false)">{{ prevIcon }}</span>\n </button>\n \n <button\n [class.carousel__nav-button--disabled]="!showNextButton"\n [disabled]="!showNextButton"\n [ngStyle]="getNextButtonFullStyles()"\n (click)="next()"\n style="pointer-events:auto;"\n class="carousel__nav-button">\n <span class="carousel__nav-icon" [ngStyle]="getIconStyles(true)">{{ nextIcon }}</span>\n </button>\n </div>\n\n \x3c!-- Carousel indicators --\x3e\n <div\n *ngIf="showIndicators && hasItems() && filteredItems.length > 1" \n class="carousel__indicators" \n [ngStyle]="getIndicatorContainerStyles()">\n <div\n *ngFor="let slide of filteredItems; let i = index"\n class="carousel__indicator"\n [class.carousel__indicator--active]="i === currentIndex"\n [ngStyle]="getIndicatorItemStyles(i)"\n (click)="goToSlide(i)">\n </div>\n </div>\n</div>\n',styles:[".carousel{--carousel-item-bg: #fff;--carousel-item-border-color: #e0e0e0;--carousel-empty-bg: #fff;--carousel-empty-color: #666;--carousel-nav-bg: #fff;--carousel-nav-border-color: #e0e0e0;--carousel-nav-disabled-bg: #f5f5f5;--carousel-nav-disabled-border: #ddd;--carousel-nav-disabled-opacity: .4;--carousel-empty-icon-size: 32px;--carousel-empty-text-size: 16px;--carousel-nav-icon-size: 16px;--carousel-nav-item-gap: 24px;--carousel-indicator-active-color: #333;--carousel-indicator-inactive-color: #ccc;--carousel-z-index: 100;position:relative;overflow:hidden;display:flex;flex-direction:column;border-radius:inherit;height:100%;min-height:inherit;box-sizing:border-box;width:fit-content}.carousel--vertical{flex-direction:column}.carousel__wrapper{flex:1;overflow:hidden;position:relative;width:100%;border-radius:inherit;height:100%;min-height:inherit;display:flex;flex-direction:column;box-sizing:border-box}.carousel__track{display:flex;flex-wrap:nowrap;transition:transform var(--animation-duration, .3s) var(--animation-timing, ease);width:fit-content;min-width:100%;height:fit-content!important;min-height:fit-content!important;border-radius:inherit;align-items:stretch;flex:1;box-sizing:border-box}.carousel__track--vertical{flex-direction:column;width:100%;height:fit-content!important;min-height:100%;align-items:stretch}.carousel__item{flex:0 0 auto;box-sizing:border-box;border-radius:inherit;min-height:100px;height:100%;display:flex;flex-direction:column;position:relative;overflow:hidden}.carousel__item[style*=--item-width]{flex:0 0 var(--item-width)!important;width:var(--item-width)!important;max-width:var(--item-width)!important;min-width:var(--item-width)!important}.carousel__item[style*=--item-height]{height:var(--item-height)!important;min-height:var(--item-height)!important;max-height:var(--item-height)!important}.carousel__item>*{height:100%!important;min-height:inherit!important;flex:1 1 auto!important;display:flex!important;flex-direction:column!important;box-sizing:border-box!important;overflow:hidden}.carousel--vertical .carousel__item{width:100%}.carousel__item-default{background:var(--carousel-item-bg);height:100%;width:100%;display:flex;align-items:center;justify-content:center;border:1px solid var(--carousel-item-border-color);border-radius:inherit;padding:20px;box-sizing:border-box;flex:1}.carousel__empty-container{width:100%;box-sizing:border-box;border-radius:inherit;flex:1;display:flex;align-items:center;justify-content:center;min-height:inherit;height:100%}.carousel__empty-state{background:var(--carousel-empty-bg);display:flex;flex-direction:column;align-items:center;justify-content:center;padding:30px;text-align:center;color:var(--carousel-empty-color);border-radius:inherit;min-height:200px;width:100%;height:100%;flex:1}.carousel__nav-controls{position:absolute;display:flex;gap:0;z-index:var(--carousel-z-index);pointer-events:none;padding:0;margin:0;width:100%;height:100%;top:0;left:0}.carousel__nav-button{background:var(--carousel-nav-bg);border:1px solid var(--carousel-nav-border-color);width:32px;height:32px;padding:0;margin:0;display:flex;align-items:center;justify-content:center;cursor:pointer;z-index:var(--carousel-z-index);position:absolute;outline:none;box-shadow:0 2px 4px #0000001a}.carousel__nav-button:hover:not(.carousel__nav-button--disabled){opacity:.9;box-shadow:0 3px 6px #00000026}.carousel__nav-button--disabled{opacity:var(--carousel-nav-disabled-opacity);cursor:not-allowed;background-color:var(--carousel-nav-disabled-bg);border-color:var(--carousel-nav-disabled-border);pointer-events:none}.carousel__nav-icon{display:flex;align-items:center;justify-content:center;width:100%;height:100%;font-size:var(--carousel-nav-icon-size);line-height:1}.carousel--vertical .carousel__nav-icon{transform:rotate(90deg)}.carousel__empty-icon{font-size:var(--carousel-empty-icon-size);margin-bottom:12px}.carousel__empty-text{font-size:var(--carousel-empty-text-size);margin-bottom:12px}.carousel__indicators{display:flex;flex-direction:row;justify-content:center;align-items:center;gap:5px;position:absolute;bottom:4px;left:50%;transform:translate(-50%);z-index:100;pointer-events:auto}.carousel--vertical .carousel__indicators{flex-direction:row;bottom:10px;left:50%;transform:translate(-50%)}.carousel__indicator{transition:all .3s ease-in-out;background-color:var(--carousel-indicator-inactive-color, #ccc);opacity:.5;cursor:pointer;border-radius:50%;width:10px;height:10px;min-width:8px;min-height:8px}.carousel__indicator:hover{opacity:.8}.carousel__indicator--active{transform:scale(1.2);background-color:var(--carousel-indicator-active-color, #333);opacity:1;animation:carousel__indicator-pulse 1s infinite alternate}:root{--carousel-nav-bg: #fff;--carousel-nav-border-color: #e0e0e0;--carousel-nav-disabled-bg: #f5f5f5;--carousel-nav-disabled-border: #ddd;--carousel-nav-disabled-opacity: .4}@keyframes carousel__indicator-pulse{0%{transform:scale(1.2);box-shadow:0 0 #3333334d}to{transform:scale(1.3);box-shadow:0 0 0 5px #3330}}@keyframes carousel__indicator-expand{0%{width:8px}to{width:36px}}\n"],dependencies:[{kind:"ngmodule",type:m},{kind:"directive",type:u.NgClass,selector:"[ngClass]",inputs:["class","ngClass"]},{kind:"directive",type:u.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:u.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:u.NgTemplateOutlet,selector:"[ngTemplateOutlet]",inputs:["ngTemplateOutletContext","ngTemplateOutlet","ngTemplateOutletInjector"]},{kind:"directive",type:u.NgStyle,selector:"[ngStyle]",inputs:["ngStyle"]}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"14.3.0",ngImport:t,type:N,decorators:[{type:o,args:[{selector:"carousel",standalone:!0,imports:[m],providers:[I],template:'<div class="carousel" \n [class.carousel--vertical]="isVertical" \n [ngClass]="configs.containerClass" \n [ngStyle]="containerStyles"\n [style.height]="configs.containerHeight || \'auto\'"\n [style.width]="configs.containerWidth || \'auto\'">\n <div\n #wrapper\n [style.--content-padding]="contentPadding"\n class="carousel__wrapper">\n <div\n #track\n [ngStyle]="trackStyles"\n [class.carousel__track--vertical]="isVertical"\n [style.--animation-duration]="animationDuration"\n [style.--animation-timing]="animationTiming"\n class="carousel__track">\n <ng-container *ngIf="hasItems(); else emptyState">\n <ng-container *ngFor="let slide of filteredItems; let i = index">\n <div class="carousel__item" \n [ngClass]="configs.itemClass" \n [ngStyle]="getItemStyle(i)" \n [style.--item-width]="configs.itemWidth || \'auto\'"\n [style.--item-height]="configs.itemHeight || \'auto\'">\n <ng-container *ngIf="itemTemplate; else defaultTemplate">\n <ng-container *ngTemplateOutlet="itemTemplate; context: { $implicit: slide, index: i }"></ng-container>\n </ng-container>\n <ng-template #defaultTemplate>\n <div class="carousel__item-default">\n {{ slide }}\n </div>\n </ng-template>\n </div>\n </ng-container>\n </ng-container>\n \n <ng-template #emptyState>\n <div class="carousel__empty-container" [ngStyle]="getEmptyStateContainerStyle()">\n <ng-container *ngIf="emptyStateTemplate; else defaultEmptyState">\n <ng-container *ngTemplateOutlet="emptyStateTemplate; context: { $implicit: emptyStateText }"></ng-container>\n </ng-container>\n <ng-template #defaultEmptyState>\n <div class="carousel__empty-state" [style.color]="emptyStateTextColor">\n <div *ngIf="showEmptyStateIcon" class="carousel__empty-icon">{{emptyStateIcon}}</div>\n <div class="carousel__empty-text">{{emptyStateText}}</div>\n </div>\n </ng-template>\n </div>\n </ng-template>\n </div>\n </div>\n\n <div *ngIf="showNavigation && hasItems()" [ngClass]="getNavControlsClass()" [ngStyle]="getNavControlsStyle()"> \n <button \n [class.carousel__nav-button--disabled]="!showPrevButton" \n [disabled]="!showPrevButton" \n [ngStyle]="getPrevButtonFullStyles()" \n (click)="previous()" \n style="pointer-events:auto;"\n class="carousel__nav-button">\n <span class="carousel__nav-icon" [ngStyle]="getIconStyles(false)">{{ prevIcon }}</span>\n </button>\n \n <button\n [class.carousel__nav-button--disabled]="!showNextButton"\n [disabled]="!showNextButton"\n [ngStyle]="getNextButtonFullStyles()"\n (click)="next()"\n style="pointer-events:auto;"\n class="carousel__nav-button">\n <span class="carousel__nav-icon" [ngStyle]="getIconStyles(true)">{{ nextIcon }}</span>\n </button>\n </div>\n\n \x3c!-- Carousel indicators --\x3e\n <div\n *ngIf="showIndicators && hasItems() && filteredItems.length > 1" \n class="carousel__indicators" \n [ngStyle]="getIndicatorContainerStyles()">\n <div\n *ngFor="let slide of filteredItems; let i = index"\n class="carousel__indicator"\n [class.carousel__indicator--active]="i === currentIndex"\n [ngStyle]="getIndicatorItemStyles(i)"\n (click)="goToSlide(i)">\n </div>\n </div>\n</div>\n',styles:[".carousel{--carousel-item-bg: #fff;--carousel-item-border-color: #e0e0e0;--carousel-empty-bg: #fff;--carousel-empty-color: #666;--carousel-nav-bg: #fff;--carousel-nav-border-color: #e0e0e0;--carousel-nav-disabled-bg: #f5f5f5;--carousel-nav-disabled-border: #ddd;--carousel-nav-disabled-opacity: .4;--carousel-empty-icon-size: 32px;--carousel-empty-text-size: 16px;--carousel-nav-icon-size: 16px;--carousel-nav-item-gap: 24px;--carousel-indicator-active-color: #333;--carousel-indicator-inactive-color: #ccc;--carousel-z-index: 100;position:relative;overflow:hidden;display:flex;flex-direction:column;border-radius:inherit;height:100%;min-height:inherit;box-sizing:border-box;width:fit-content}.carousel--vertical{flex-direction:column}.carousel__wrapper{flex:1;overflow:hidden;position:relative;width:100%;border-radius:inherit;height:100%;min-height:inherit;display:flex;flex-direction:column;box-sizing:border-box}.carousel__track{display:flex;flex-wrap:nowrap;transition:transform var(--animation-duration, .3s) var(--animation-timing, ease);width:fit-content;min-width:100%;height:fit-content!important;min-height:fit-content!important;border-radius:inherit;align-items:stretch;flex:1;box-sizing:border-box}.carousel__track--vertical{flex-direction:column;width:100%;height:fit-content!important;min-height:100%;align-items:stretch}.carousel__item{flex:0 0 auto;box-sizing:border-box;border-radius:inherit;min-height:100px;height:100%;display:flex;flex-direction:column;position:relative;overflow:hidden}.carousel__item[style*=--item-width]{flex:0 0 var(--item-width)!important;width:var(--item-width)!important;max-width:var(--item-width)!important;min-width:var(--item-width)!important}.carousel__item[style*=--item-height]{height:var(--item-height)!important;min-height:var(--item-height)!important;max-height:var(--item-height)!important}.carousel__item>*{height:100%!important;min-height:inherit!important;flex:1 1 auto!important;display:flex!important;flex-direction:column!important;box-sizing:border-box!important;overflow:hidden}.carousel--vertical .carousel__item{width:100%}.carousel__item-default{background:var(--carousel-item-bg);height:100%;width:100%;display:flex;align-items:center;justify-content:center;border:1px solid var(--carousel-item-border-color);border-radius:inherit;padding:20px;box-sizing:border-box;flex:1}.carousel__empty-container{width:100%;box-sizing:border-box;border-radius:inherit;flex:1;display:flex;align-items:center;justify-content:center;min-height:inherit;height:100%}.carousel__empty-state{background:var(--carousel-empty-bg);display:flex;flex-direction:column;align-items:center;justify-content:center;padding:30px;text-align:center;color:var(--carousel-empty-color);border-radius:inherit;min-height:200px;width:100%;height:100%;flex:1}.carousel__nav-controls{position:absolute;display:flex;gap:0;z-index:var(--carousel-z-index);pointer-events:none;padding:0;margin:0;width:100%;height:100%;top:0;left:0}.carousel__nav-button{background:var(--carousel-nav-bg);border:1px solid var(--carousel-nav-border-color);width:32px;height:32px;padding:0;margin:0;display:flex;align-items:center;justify-content:center;cursor:pointer;z-index:var(--carousel-z-index);position:absolute;outline:none;box-shadow:0 2px 4px #0000001a}.carousel__nav-button:hover:not(.carousel__nav-button--disabled){opacity:.9;box-shadow:0 3px 6px #00000026}.carousel__nav-button--disabled{opacity:var(--carousel-nav-disabled-opacity);cursor:not-allowed;background-color:var(--carousel-nav-disabled-bg);border-color:var(--carousel-nav-disabled-border);pointer-events:none}.carousel__nav-icon{display:flex;align-items:center;justify-content:center;width:100%;height:100%;font-size:var(--carousel-nav-icon-size);line-height:1}.carousel--vertical .carousel__nav-icon{transform:rotate(90deg)}.carousel__empty-icon{font-size:var(--carousel-empty-icon-size);margin-bottom:12px}.carousel__empty-text{font-size:var(--carousel-empty-text-size);margin-bottom:12px}.carousel__indicators{display:flex;flex-direction:row;justify-content:center;align-items:center;gap:5px;position:absolute;bottom:4px;left:50%;transform:translate(-50%);z-index:100;pointer-events:auto}.carousel--vertical .carousel__indicators{flex-direction:row;bottom:10px;left:50%;transform:translate(-50%)}.carousel__indicator{transition:all .3s ease-in-out;background-color:var(--carousel-indicator-inactive-color, #ccc);opacity:.5;cursor:pointer;border-radius:50%;width:10px;height:10px;min-width:8px;min-height:8px}.carousel__indicator:hover{opacity:.8}.carousel__indicator--active{transform:scale(1.2);background-color:var(--carousel-indicator-active-color, #333);opacity:1;animation:carousel__indicator-pulse 1s infinite alternate}:root{--carousel-nav-bg: #fff;--carousel-nav-border-color: #e0e0e0;--carousel-nav-disabled-bg: #f5f5f5;--carousel-nav-disabled-border: #ddd;--carousel-nav-disabled-opacity: .4}@keyframes carousel__indicator-pulse{0%{transform:scale(1.2);box-shadow:0 0 #3333334d}to{transform:scale(1.3);box-shadow:0 0 0 5px #3330}}@keyframes carousel__indicator-expand{0%{width:8px}to{width:36px}}\n"]}]}],propDecorators:{slides:[{type:r}],configs:[{type:r}],itemTemplate:[{type:a,args:["carouselItem"]}],emptyStateTemplate:[{type:a,args:["emptyState"]}],trackElement:[{type:l,args:["track"]}],wrapperElement:[{type:l,args:["wrapper"]}]}});class z{constructor(t,e){this.el=t,this.renderer=e,this.carouselLazyLoad="",this.errorImage="assets/images/no-image.png",this.isLoaded=!1}ngOnInit(){!this.isLoaded&&this.carouselLazyLoad&&("IntersectionObserver"in window?(this.observer=new IntersectionObserver((t=>{t.forEach((t=>{var e;t.isIntersecting&&(this.loadImage(),null===(e=this.observer)||void 0===e||e.unobserve(this.el.nativeElement))}))})),this.observer.observe(this.el.nativeElement)):this.loadImage())}ngOnDestroy(){this.observer&&(this.observer.disconnect(),this.observer=void 0)}loadImage(){this.isLoaded=!0;const t=this.el.nativeElement;if("IMG"===t.tagName){this.renderer.setAttribute(t,"src",this.carouselLazyLoad);const e=()=>{this.renderer.setAttribute(t,"src",this.errorImage);this.renderer.listen(t,"error",e)()};this.renderer.listen(t,"error",e)}else this.renderer.setStyle(t,"background-image",`url('${this.carouselLazyLoad}')`)}}z.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"14.3.0",ngImport:t,type:z,deps:[{token:t.ElementRef},{token:t.Renderer2}],target:t.ɵɵFactoryTarget.Directive}),z.ɵdir=t.ɵɵngDeclareDirective({minVersion:"14.0.0",version:"14.3.0",type:z,isStandalone:!0,selector:"[carouselLazyLoad]",inputs:{carouselLazyLoad:"carouselLazyLoad",errorImage:"errorImage"},ngImport:t}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"14.3.0",ngImport:t,type:z,decorators:[{type:c,args:[{selector:"[carouselLazyLoad]",standalone:!0}]}],ctorParameters:function(){return[{type:t.ElementRef},{type:t.Renderer2}]},propDecorators:{carouselLazyLoad:[{type:r}],errorImage:[{type:r}]}});class E{}E.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"14.3.0",ngImport:t,type:E,deps:[],target:t.ɵɵFactoryTarget.NgModule}),E.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"14.3.0",ngImport:t,type:E,imports:[N,z],exports:[N,z]}),E.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"14.3.0",ngImport:t,type:E,imports:[N]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"14.3.0",ngImport:t,type:E,decorators:[{type:d,args:[{imports:[N,z],exports:[N,z]}]}]});export{x as CAROUSEL_DEFAULTS,N as CarouselComponent,E as CarouselModule,I as CarouselService,z as LazyLoadDirective,T as calculateScrollAmount,w as createTranslation,b as easings,_ as getCssTimingFunction,S as parseTimeToMs,O as smoothScroll,C as smoothScrollVertical};