primeng
Version:
PrimeNG is a premium UI library for Angular featuring a rich set of 90+ components, a theme designer, various theme alternatives such as Material, Bootstrap, Tailwind, premium templates and professional support. In addition, it integrates with PrimeBlock,
1 lines • 144 kB
Source Map (JSON)
{"version":3,"file":"primeng-carousel.mjs","sources":["../../src/carousel/style/carouselstyle.ts","../../src/carousel/carousel-token.ts","../../src/carousel/carousel-content.ts","../../src/carousel/carousel-item.ts","../../src/carousel/carousel-next.ts","../../src/carousel/carousel-prev.ts","../../src/carousel/carousel-indicator.ts","../../src/carousel/carousel-indicators.ts","../../src/carousel/carousel-legacy.ts","../../src/carousel/carousel.ts","../../src/carousel/primeng-carousel.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\nimport { style } from '@primeuix/styles/carousel';\nimport { BaseStyle } from 'primeng/base';\n\nconst classes = {\n root: ({ instance }) => [\n 'p-carousel p-component',\n {\n 'p-carousel-vertical': instance.isVertical(),\n 'p-carousel-horizontal': !instance.isVertical()\n }\n ],\n header: 'p-carousel-header',\n contentContainer: 'p-carousel-content-container',\n content: 'p-carousel-content',\n pcPrevButton: ({ instance }) => [\n 'p-carousel-prev-button',\n {\n 'p-disabled': instance.isBackwardNavDisabled()\n }\n ],\n viewport: 'p-carousel-viewport',\n itemList: 'p-carousel-item-list',\n itemClone: ({ instance, index }) => [\n 'p-carousel-item p-carousel-item-clone',\n {\n 'p-carousel-item-active': instance.totalShiftedItems() * -1 === instance.value()?.length,\n 'p-carousel-item-start': 0 === index,\n 'p-carousel-item-end': instance.clonedItemsForStarting().length - 1 === index\n }\n ],\n item: ({ instance, index }) => [\n 'p-carousel-item',\n {\n 'p-carousel-item-active': instance.firstIndex() <= index && instance.lastIndex() >= index,\n 'p-carousel-item-start': instance.firstIndex() === index,\n 'p-carousel-item-end': instance.lastIndex() === index\n }\n ],\n pcNextButton: ({ instance }) => [\n 'p-carousel-next-button',\n {\n 'p-disabled': instance.isForwardNavDisabled()\n }\n ],\n indicatorList: ({ instance }) => ['p-carousel-indicator-list', instance.indicatorsContentClass()],\n indicator: ({ instance, index }) => [\n 'p-carousel-indicator',\n {\n 'p-carousel-indicator-active': instance._page() === index\n }\n ],\n indicatorButton: ({ instance }) => ['p-carousel-indicator-button', instance.indicatorStyleClass()],\n footer: 'p-carousel-footer',\n // Composition mode\n compositionRoot: 'p-carousel p-component',\n compositionIndicator: ({ instance, index }) => ['p-carousel-indicator-button', { 'p-carousel-indicator-active': instance.pageState() === index }],\n compositionContent: ({ instance }) => ['p-carousel-content', instance.orientation() === 'vertical' ? 'p-carousel-content-vertical' : 'p-carousel-content-horizontal'],\n compositionItem: 'p-carousel-item',\n compositionPrev: ({ instance }) => [{ 'p-disabled': instance.isPrevDisabled() }],\n compositionNext: ({ instance }) => [{ 'p-disabled': instance.isNextDisabled() }]\n};\n\n@Injectable()\nexport class CarouselStyle extends BaseStyle {\n name = 'carousel';\n\n style = style;\n\n classes = classes;\n}\n\n/**\n *\n * Carousel is a content slider featuring various customization options.\n *\n * [Live Demo](https://www.primeng.org/carousel/)\n *\n * @module carouselstyle\n *\n */\nexport enum CarouselClasses {\n /**\n * Class name of the root element\n */\n root = 'p-carousel',\n /**\n * Class name of the header element\n */\n header = 'p-carousel-header',\n /**\n * Class name of the content container element\n */\n contentContainer = 'p-carousel-content-container',\n /**\n * Class name of the content element\n */\n content = 'p-carousel-content',\n /**\n * Class name of the previous button element\n */\n pcPrevButton = 'p-carousel-prev-button',\n /**\n * Class name of the viewport element\n */\n viewport = 'p-carousel-viewport',\n /**\n * Class name of the item list element\n */\n itemList = 'p-carousel-item-list',\n /**\n * Class name of the item clone element\n */\n itemClone = 'p-carousel-item-clone',\n /**\n * Class name of the item element\n */\n item = 'p-carousel-item',\n /**\n * Class name of the next button element\n */\n pcNextButton = 'p-carousel-next-button',\n /**\n * Class name of the indicator list element\n */\n indicatorList = 'p-carousel-indicator-list',\n /**\n * Class name of the indicator element\n */\n indicator = 'p-carousel-indicator',\n /**\n * Class name of the indicator button element\n */\n indicatorButton = 'p-carousel-indicator-button',\n /**\n * Class name of the footer element\n */\n footer = 'p-carousel-footer'\n}\n\nexport interface CarouselStyle extends BaseStyle {}\n","import { InjectionToken } from '@angular/core';\n\nexport const CAROUSEL_ROOT = new InjectionToken<any>('CAROUSEL_ROOT');\n","import { afterNextRender, ChangeDetectionStrategy, Component, computed, inject, ViewEncapsulation } from '@angular/core';\nimport { BaseComponent, PARENT_INSTANCE } from 'primeng/basecomponent';\nimport { Bind, BindModule } from 'primeng/bind';\nimport { CAROUSEL_ROOT } from './carousel-token';\nimport { CarouselStyle } from './style/carouselstyle';\nimport type { CarouselContentPassThrough } from 'primeng/types/carousel';\n\n/**\n * CarouselContent is the scrollable track element that contains carousel items.\n * @group Components\n */\n@Component({\n selector: 'p-carousel-content',\n standalone: true,\n imports: [BindModule],\n template: `<ng-content></ng-content>`,\n providers: [CarouselStyle, { provide: PARENT_INSTANCE, useExisting: CarouselContent }],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n host: {\n '[class]': \"root.cx('compositionContent')\",\n '[attr.data-scope]': \"'carousel'\",\n '[attr.data-part]': \"'content'\",\n '[attr.data-orientation]': 'dataOrientation()',\n '[attr.data-align]': 'dataAlign()',\n '[attr.data-page]': 'dataPage()',\n '[attr.data-autosize]': 'dataAutosize()',\n '[attr.data-swiping]': 'dataSwiping()',\n '[style.display]': \"'flex'\",\n '[style.flex-direction]': 'flexDirection()',\n '[style.overflow-x]': 'overflowX()',\n '[style.overflow-y]': 'overflowY()',\n '[style.overscroll-behavior-x]': 'overscrollX()',\n '[style.overscroll-behavior-y]': 'overscrollY()',\n '[style.gap]': \"'var(--px-spacing-items)'\",\n '[style.scroll-snap-type]': \"'var(--px-scroll-snap-type)'\",\n '[style.scrollbar-width]': \"'none'\",\n '[style.position]': \"'relative'\",\n '[style.--px-slides-per-page]': 'slidesPerPage()',\n '[style.--px-spacing-items]': 'spacingItems()',\n '[style.--px-scroll-snap-type]': 'scrollSnapType()',\n '(pointerdown)': 'onPointerDown($event)',\n '(pointermove)': 'onPointerMove($event)',\n '(pointerup)': 'onPointerUp($event)',\n '(wheel)': 'onWheel($event)'\n },\n hostDirectives: [Bind]\n})\nexport class CarouselContent extends BaseComponent<CarouselContentPassThrough> {\n componentName = 'CarouselContent';\n\n bindDirectiveInstance = inject(Bind, { self: true });\n\n root = inject(CAROUSEL_ROOT);\n\n isVertical = computed(() => this.root.orientation() === 'vertical');\n\n flexDirection = computed(() => (this.isVertical() ? 'column' : 'row'));\n\n overflowX = computed(() => (this.isVertical() ? null : 'scroll'));\n\n overflowY = computed(() => (this.isVertical() ? 'scroll' : null));\n\n overscrollX = computed(() => (this.isVertical() ? null : 'contain'));\n\n overscrollY = computed(() => (this.isVertical() ? 'contain' : null));\n\n dataAutosize = computed(() => (this.root.autoSize() ? '' : null));\n\n dataSwiping = computed(() => (this.root.swiping() ? '' : null));\n\n dataOrientation = computed(() => this.root.orientation());\n\n dataAlign = computed(() => this.root.align());\n\n dataPage = computed(() => this.root.pageState());\n\n slidesPerPage = computed(() => this.root.slidesPerPage());\n\n spacingItems = computed(() => this.root.spacing() + 'px');\n\n scrollSnapType = computed(() => this.root.resolveSnapType());\n\n onPointerDown(e: PointerEvent) {\n this.root.onContentPointerDown(e);\n }\n\n onPointerMove(e: PointerEvent) {\n this.root.onContentPointerMove(e);\n }\n\n onPointerUp(e: PointerEvent) {\n this.root.onContentPointerUp(e);\n }\n\n onWheel(e: WheelEvent) {\n this.root.onContentWheel(e);\n }\n\n onAfterViewChecked() {\n this.bindDirectiveInstance.setAttrs(this.ptms(['host', 'root']));\n }\n\n constructor() {\n super();\n afterNextRender(() => {\n this.root.setContentEl(this.$el);\n this.root.setupObservers();\n });\n }\n}\n","import { ChangeDetectionStrategy, Component, computed, inject, input, ViewEncapsulation } from '@angular/core';\nimport { BaseComponent, PARENT_INSTANCE } from 'primeng/basecomponent';\nimport { Bind, BindModule } from 'primeng/bind';\nimport { CAROUSEL_ROOT } from './carousel-token';\nimport { CarouselStyle } from './style/carouselstyle';\nimport type { CarouselItemPassThrough } from 'primeng/types/carousel';\n\n/**\n * CarouselItem represents an individual item in the composition-based carousel.\n * @group Components\n */\n@Component({\n selector: 'p-carousel-item',\n standalone: true,\n imports: [BindModule],\n template: `<ng-content></ng-content>`,\n providers: [CarouselStyle, { provide: PARENT_INSTANCE, useExisting: CarouselItem }],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n host: {\n '[class]': \"root.cx('compositionItem')\",\n '[attr.data-scope]': \"'carousel'\",\n '[attr.data-part]': \"'item'\",\n '[attr.data-item]': \"''\",\n '[attr.data-value]': 'value()',\n '[attr.data-orientation]': 'dataOrientation()',\n '[attr.data-align]': 'dataAlign()',\n '[attr.data-page]': 'dataPage()',\n '[attr.data-swiping]': 'dataSwiping()',\n '[attr.data-autosize]': 'dataAutosize()',\n '[style.flex-grow]': '0',\n '[style.flex-shrink]': '0',\n '[style.min-width]': '0',\n '[style.flex-basis]': 'flexBasis()',\n '[style.scroll-snap-align]': 'scrollSnapAlign()'\n },\n hostDirectives: [Bind]\n})\nexport class CarouselItem extends BaseComponent<CarouselItemPassThrough> {\n componentName = 'CarouselItem';\n\n bindDirectiveInstance = inject(Bind, { self: true });\n\n /**\n * The value/identifier of the carousel item.\n * @group Props\n */\n value = input<unknown>();\n\n root = inject(CAROUSEL_ROOT);\n\n dataOrientation = computed(() => this.root.orientation());\n\n dataAlign = computed(() => this.root.align());\n\n dataPage = computed(() => this.root.pageState());\n\n dataSwiping = computed(() => (this.root.swiping() ? '' : null));\n\n dataAutosize = computed(() => (this.root.autoSize() ? '' : null));\n\n flexBasis = computed(() => (this.root.autoSize() ? 'auto' : 'calc(100% / var(--px-slides-per-page) - var(--px-spacing-items) * (var(--px-slides-per-page) - 1) / var(--px-slides-per-page))'));\n\n scrollSnapAlign = computed(() => this.root.align());\n\n onAfterViewChecked() {\n this.bindDirectiveInstance.setAttrs(this.ptms(['host', 'root']));\n }\n}\n","import { computed, Directive, inject } from '@angular/core';\nimport { BaseComponent, PARENT_INSTANCE } from 'primeng/basecomponent';\nimport { CAROUSEL_ROOT } from './carousel-token';\nimport { CarouselStyle } from './style/carouselstyle';\nimport type { CarouselNextPassThrough } from 'primeng/types/carousel';\n\n/**\n * CarouselNext is a directive for the next navigation button.\n * @group Directives\n */\n@Directive({\n selector: '[pCarouselNext]',\n standalone: true,\n providers: [CarouselStyle, { provide: PARENT_INSTANCE, useExisting: CarouselNext }],\n host: {\n '[class]': 'hostClass()',\n '[attr.data-scope]': \"'carousel'\",\n '[attr.data-part]': \"'next'\",\n '[attr.data-orientation]': 'dataOrientation()',\n '[attr.data-align]': 'dataAlign()',\n '[attr.data-page]': 'dataPage()',\n '[attr.data-disabled]': 'dataDisabled()',\n '[attr.data-swiping]': 'dataSwiping()',\n '[attr.disabled]': 'attrDisabled()',\n '(click)': 'onClick()'\n }\n})\nexport class CarouselNext extends BaseComponent<CarouselNextPassThrough> {\n componentName = 'CarouselNext';\n\n root = inject(CAROUSEL_ROOT);\n\n _componentStyle = inject(CarouselStyle);\n\n hostClass = computed(() => this.root.cx('compositionNext'));\n\n dataOrientation = computed(() => this.root.orientation());\n\n dataAlign = computed(() => this.root.align());\n\n dataPage = computed(() => this.root.pageState());\n\n dataDisabled = computed(() => this.root.isNextDisabled());\n\n dataSwiping = computed(() => (this.root.swiping() ? '' : null));\n\n attrDisabled = computed(() => (this.root.isNextDisabled() ? true : null));\n\n onClick() {\n this.root.next();\n }\n}\n","import { computed, Directive, inject } from '@angular/core';\nimport { BaseComponent, PARENT_INSTANCE } from 'primeng/basecomponent';\nimport { CAROUSEL_ROOT } from './carousel-token';\nimport { CarouselStyle } from './style/carouselstyle';\nimport type { CarouselPrevPassThrough } from 'primeng/types/carousel';\n\n/**\n * CarouselPrev is a directive for the previous navigation button.\n * @group Directives\n */\n@Directive({\n selector: '[pCarouselPrev]',\n standalone: true,\n providers: [CarouselStyle, { provide: PARENT_INSTANCE, useExisting: CarouselPrev }],\n host: {\n '[class]': 'hostClass()',\n '[attr.data-scope]': \"'carousel'\",\n '[attr.data-part]': \"'prev'\",\n '[attr.data-orientation]': 'dataOrientation()',\n '[attr.data-align]': 'dataAlign()',\n '[attr.data-page]': 'dataPage()',\n '[attr.data-disabled]': 'dataDisabled()',\n '[attr.data-swiping]': 'dataSwiping()',\n '[attr.disabled]': 'attrDisabled()',\n '(click)': 'onClick()'\n }\n})\nexport class CarouselPrev extends BaseComponent<CarouselPrevPassThrough> {\n componentName = 'CarouselPrev';\n\n root = inject(CAROUSEL_ROOT);\n\n _componentStyle = inject(CarouselStyle);\n\n hostClass = computed(() => this.root.cx('compositionPrev'));\n\n dataOrientation = computed(() => this.root.orientation());\n\n dataAlign = computed(() => this.root.align());\n\n dataPage = computed(() => this.root.pageState());\n\n dataDisabled = computed(() => this.root.isPrevDisabled());\n\n dataSwiping = computed(() => (this.root.swiping() ? '' : null));\n\n attrDisabled = computed(() => (this.root.isPrevDisabled() ? true : null));\n\n onClick() {\n this.root.prev();\n }\n}\n","import { computed, Directive, inject, input, numberAttribute } from '@angular/core';\nimport { BaseComponent, PARENT_INSTANCE } from 'primeng/basecomponent';\nimport { Bind } from 'primeng/bind';\nimport { CAROUSEL_ROOT } from './carousel-token';\nimport { CarouselStyle } from './style/carouselstyle';\nimport type { CarouselIndicatorPassThrough } from 'primeng/types/carousel';\n\n/**\n * CarouselIndicator is a directive for an individual page indicator button.\n * @group Directives\n */\n@Directive({\n selector: '[pCarouselIndicator]',\n standalone: true,\n providers: [CarouselStyle, { provide: PARENT_INSTANCE, useExisting: CarouselIndicator }],\n host: {\n '[class]': 'hostClass()',\n '[attr.data-scope]': \"'carousel'\",\n '[attr.data-part]': \"'indicator'\",\n '[attr.data-orientation]': 'dataOrientation()',\n '[attr.data-align]': 'dataAlign()',\n '[attr.data-page]': 'dataPage()',\n '[attr.data-active]': 'dataActive()',\n '[attr.data-swiping]': 'dataSwiping()',\n '(click)': 'onClick()'\n },\n hostDirectives: [Bind]\n})\nexport class CarouselIndicator extends BaseComponent<CarouselIndicatorPassThrough> {\n componentName = 'CarouselIndicator';\n\n /**\n * The page index this indicator represents.\n * @group Props\n */\n page = input(0, { transform: numberAttribute });\n\n root = inject(CAROUSEL_ROOT);\n\n bindDirectiveInstance = inject(Bind, { self: true });\n\n _componentStyle = inject(CarouselStyle);\n\n isActive = computed(() => this.root.pageState() === this.page());\n\n hostClass = computed(() => this.root.cx('compositionIndicator', { index: this.page() }));\n\n dataOrientation = computed(() => this.root.orientation());\n\n dataAlign = computed(() => this.root.align());\n\n dataPage = computed(() => this.root.pageState());\n\n dataActive = computed(() => (this.isActive() ? '' : null));\n\n dataSwiping = computed(() => (this.root.swiping() ? '' : null));\n\n onClick() {\n this.root.scrollToPage(this.page());\n }\n\n onAfterViewChecked() {\n this.bindDirectiveInstance.setAttrs(this.ptms(['host', 'root']));\n }\n}\n","import { ChangeDetectionStrategy, Component, computed, inject, ViewEncapsulation } from '@angular/core';\nimport { BaseComponent, PARENT_INSTANCE } from 'primeng/basecomponent';\nimport { Bind, BindModule } from 'primeng/bind';\nimport { CAROUSEL_ROOT } from './carousel-token';\nimport { CarouselIndicator } from './carousel-indicator';\nimport type { CarouselIndicatorsPassThrough } from 'primeng/types/carousel';\n\n/**\n * CarouselIndicators renders the list of page indicators.\n * Auto-generates button indicators based on snap points.\n * @group Components\n */\n@Component({\n selector: 'p-carousel-indicators',\n standalone: true,\n imports: [BindModule, CarouselIndicator],\n template: `\n @for (page of pages(); track page) {\n <button type=\"button\" pCarouselIndicator [page]=\"page\"></button>\n }\n `,\n providers: [{ provide: PARENT_INSTANCE, useExisting: CarouselIndicators }],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n host: {\n '[class]': 'hostClass()',\n '[attr.data-scope]': \"'carousel'\",\n '[attr.data-part]': \"'indicators'\",\n '[attr.data-orientation]': 'dataOrientation()',\n '[attr.data-align]': 'dataAlign()',\n '[attr.data-page]': 'dataPage()',\n '[attr.data-swiping]': 'dataSwiping()'\n },\n hostDirectives: [Bind]\n})\nexport class CarouselIndicators extends BaseComponent<CarouselIndicatorsPassThrough> {\n componentName = 'CarouselIndicators';\n\n bindDirectiveInstance = inject(Bind, { self: true });\n\n root = inject(CAROUSEL_ROOT);\n\n hostClass = computed(() => this.root.cx('indicatorList'));\n\n dataOrientation = computed(() => this.root.orientation());\n\n dataAlign = computed(() => this.root.align());\n\n dataPage = computed(() => this.root.pageState());\n\n dataSwiping = computed(() => (this.root.swiping() ? '' : null));\n\n pages = computed(() => {\n const points = this.root.snapPoints();\n return Array.from(points).map((_, i) => i);\n });\n\n onAfterViewChecked() {\n this.bindDirectiveInstance.setAttrs(this.ptms(['host', 'root']));\n }\n}\n","import { isPlatformBrowser } from '@angular/common';\nimport { booleanAttribute, computed, contentChild, Directive, effect, ElementRef, inject, input, numberAttribute, output, signal, TemplateRef, untracked, viewChild } from '@angular/core';\nimport { addClass, find, findSingle, getAttribute, removeClass, setAttribute, uuid } from '@primeuix/utils';\nimport { Footer, Header } from 'primeng/api';\nimport { BaseComponent } from 'primeng/basecomponent';\nimport type { ButtonDirectiveOptions } from 'primeng/types/button';\nimport type { CSSProperties } from 'primeng/types/shared';\nimport type { CarouselItemTemplateContext, CarouselOrientation, CarouselPageEvent, CarouselResponsiveOptions } from 'primeng/types/carousel';\nimport { CarouselStyle } from './style/carouselstyle';\n\n/**\n * Base class containing all legacy (data-driven) carousel logic.\n * Extended by the Carousel component.\n * @deprecated Use the composition API of Carousel instead (e.g. p-carousel-content, p-carousel-item).\n */\n@Directive()\nexport abstract class CarouselLegacyBase extends BaseComponent {\n /**\n * Index of the first item.\n * @defaultValue 0\n * @group Props\n */\n page = input(0, { transform: numberAttribute });\n\n /**\n * Number of items per page.\n * @defaultValue 1\n * @group Props\n */\n numVisible = input(1, { transform: numberAttribute });\n\n /**\n * Number of items to scroll.\n * @defaultValue 1\n * @group Props\n */\n numScroll = input(1, { transform: numberAttribute });\n\n /**\n * An array of options for responsive design.\n * @see {CarouselResponsiveOptions}\n * @group Props\n */\n responsiveOptions = input<CarouselResponsiveOptions[]>();\n\n /**\n * Specifies the layout of the component.\n * @group Props\n */\n orientation = input<CarouselOrientation>('horizontal');\n\n /**\n * Height of the viewport in vertical layout.\n * @group Props\n */\n verticalViewPortHeight = input('300px');\n\n /**\n * Style class of main content.\n * @group Props\n */\n contentClass = input('');\n\n /**\n * Style class of the indicator items.\n * @group Props\n */\n indicatorsContentClass = input('');\n\n /**\n * Inline style of the indicator items.\n * @group Props\n */\n indicatorsContentStyle = input<CSSProperties>();\n\n /**\n * Style class of the indicators.\n * @group Props\n */\n indicatorStyleClass = input('');\n\n /**\n * Style of the indicators.\n * @group Props\n */\n indicatorStyle = input<CSSProperties>();\n\n /**\n * An array of objects to display.\n * @defaultValue null\n * @group Props\n */\n value = input<any[]>();\n\n /**\n * Defines if scrolling would be infinite.\n * @group Props\n */\n circular = input(false, { transform: booleanAttribute });\n\n /**\n * Whether to display indicator container.\n * @group Props\n */\n showIndicators = input(true, { transform: booleanAttribute });\n\n /**\n * Whether to display navigation buttons in container.\n * @group Props\n */\n showNavigators = input(true, { transform: booleanAttribute });\n\n /**\n * Time in milliseconds to scroll items automatically.\n * @group Props\n */\n autoplayInterval = input(0, { transform: numberAttribute });\n\n /**\n * Configuration object forwarded to the underlying button.\n * @group Props\n */\n prevButtonProps = input<ButtonDirectiveOptions>({\n severity: 'secondary',\n variant: 'text',\n rounded: true\n });\n\n /**\n * Configuration object forwarded to the underlying button.\n * @group Props\n */\n nextButtonProps = input<ButtonDirectiveOptions>({\n severity: 'secondary',\n variant: 'text',\n rounded: true\n });\n\n /**\n * Callback to invoke after scroll.\n * @param {CarouselPageEvent} event - Custom page event.\n * @group Emits\n */\n onPage = output<CarouselPageEvent>();\n\n itemsContainer = viewChild<ElementRef>('itemsContainer');\n\n indicatorContent = viewChild<ElementRef>('indicatorContent');\n\n headerFacet = contentChild(Header, { descendants: false });\n\n footerFacet = contentChild(Footer, { descendants: false });\n\n /**\n * Custom item template.\n * @group Templates\n */\n itemTemplate = contentChild<TemplateRef<CarouselItemTemplateContext>>('item', { descendants: false });\n\n /**\n * Custom header template.\n * @group Templates\n */\n headerTemplate = contentChild<TemplateRef<void>>('header', { descendants: false });\n\n /**\n * Custom footer template.\n * @group Templates\n */\n footerTemplate = contentChild<TemplateRef<void>>('footer', { descendants: false });\n\n /**\n * Custom previous icon template.\n * @group Templates\n */\n previousIconTemplate = contentChild<TemplateRef<void>>('previousicon', { descendants: false });\n\n /**\n * Custom next icon template.\n * @group Templates\n */\n nextIconTemplate = contentChild<TemplateRef<void>>('nexticon', { descendants: false });\n\n _componentStyle = inject(CarouselStyle);\n\n _numVisible = 1;\n\n _numScroll = 1;\n\n _oldNumScroll = 0;\n\n prevState = {\n numScroll: 0,\n numVisible: 0,\n value: [] as unknown[]\n };\n\n defaultNumScroll = 1;\n\n defaultNumVisible = 1;\n\n _page = signal(0);\n\n carouselStyle: HTMLStyleElement | null = null;\n\n id: string | undefined;\n\n totalShiftedItems = signal(0);\n\n isRemainingItemsAdded = false;\n\n animationTimeout: ReturnType<typeof setTimeout> | undefined;\n\n translateTimeout: ReturnType<typeof setTimeout> | undefined;\n\n remainingItems = 0;\n\n startPos: { x: number; y: number } | null = null;\n\n documentResizeListener: VoidFunction | null = null;\n\n clonedItemsForStarting = signal<unknown[]>([]);\n\n clonedItemsForFinishing = signal<unknown[]>([]);\n\n allowAutoplay = signal(false);\n\n interval: ReturnType<typeof setInterval> | undefined;\n\n isCreated = false;\n\n swipeThreshold = 20;\n\n window: Window;\n\n viewportStyle = computed(() => {\n return { height: this.isVertical() ? this.verticalViewPortHeight() : 'auto' };\n });\n\n constructor() {\n super();\n this.window = this.document.defaultView as Window;\n this.totalShiftedItems.set(this.page() * this.numScroll() * -1);\n\n // Effect for page changes\n effect(() => {\n const pageVal = this.page();\n untracked(() => {\n if (this.isCreated && pageVal !== this._page()) {\n if (this.autoplayInterval()) {\n this.stopAutoplay();\n }\n\n if (pageVal > this._page() && pageVal <= this.totalDots() - 1) {\n this.step(-1, pageVal);\n } else if (pageVal < this._page()) {\n this.step(1, pageVal);\n }\n }\n this._page.set(pageVal);\n });\n });\n\n // Effect for value changes\n effect(() => {\n const val = this.value();\n if (isPlatformBrowser(this.platformId)) {\n if (this.circular() && val) {\n this.setCloneItems();\n }\n }\n });\n\n // Effect for numVisible/numScroll changes\n effect(() => {\n const numVisibleVal = this.numVisible();\n const numScrollVal = this.numScroll();\n const responsiveOpts = this.responsiveOptions();\n\n untracked(() => {\n if (this.isCreated) {\n if (responsiveOpts) {\n this.defaultNumVisible = numVisibleVal;\n this.defaultNumScroll = numScrollVal;\n }\n\n if (this.isCircular()) {\n this.setCloneItems();\n }\n\n this.createStyle();\n this.calculatePosition();\n }\n\n this._numVisible = numVisibleVal;\n this._numScroll = numScrollVal;\n });\n });\n }\n\n legacyOnAfterContentInit() {\n this.id = uuid('pn_id_');\n if (isPlatformBrowser(this.platformId)) {\n this.allowAutoplay.set(!!this.autoplayInterval());\n\n if (this.circular()) {\n this.setCloneItems();\n }\n\n if (this.responsiveOptions()) {\n this.defaultNumScroll = this._numScroll;\n this.defaultNumVisible = this._numVisible;\n }\n\n this.createStyle();\n this.calculatePosition();\n\n if (this.responsiveOptions()) {\n this.bindDocumentListeners();\n }\n }\n }\n\n legacyOnAfterContentChecked() {\n if (isPlatformBrowser(this.platformId)) {\n const isCircular = this.isCircular();\n let totalShiftedItems = this.totalShiftedItems();\n const val = this.value();\n\n if (val && this.itemsContainer() && (this.prevState.numScroll !== this._numScroll || this.prevState.numVisible !== this._numVisible || this.prevState.value.length !== val.length)) {\n if (this.autoplayInterval()) {\n this.stopAutoplay(false);\n }\n\n this.remainingItems = (val.length - this._numVisible) % this._numScroll;\n\n let page = this._page();\n if (this.totalDots() !== 0 && page >= this.totalDots()) {\n page = this.totalDots() - 1;\n this._page.set(page);\n this.onPage.emit({\n page: this._page()\n });\n }\n\n totalShiftedItems = page * this._numScroll * -1;\n if (isCircular) {\n totalShiftedItems -= this._numVisible;\n }\n\n if (page === this.totalDots() - 1 && this.remainingItems > 0) {\n totalShiftedItems += -1 * this.remainingItems + this._numScroll;\n this.isRemainingItemsAdded = true;\n } else {\n this.isRemainingItemsAdded = false;\n }\n\n if (totalShiftedItems !== this.totalShiftedItems()) {\n this.totalShiftedItems.set(totalShiftedItems);\n }\n\n this._oldNumScroll = this._numScroll;\n this.prevState.numScroll = this._numScroll;\n this.prevState.numVisible = this._numVisible;\n this.prevState.value = [...val];\n\n const itemsContainerEl = this.itemsContainer();\n if (this.totalDots() > 0 && itemsContainerEl?.nativeElement) {\n itemsContainerEl.nativeElement.style.transform = this.isVertical() ? `translate3d(0, ${totalShiftedItems * (100 / this._numVisible)}%, 0)` : `translate3d(${totalShiftedItems * (100 / this._numVisible)}%, 0, 0)`;\n }\n\n this.isCreated = true;\n\n if (this.autoplayInterval() && this.isAutoplay()) {\n this.startAutoplay();\n }\n }\n\n if (isCircular && val) {\n if (this._page() === 0) {\n totalShiftedItems = -1 * this._numVisible;\n } else if (totalShiftedItems === 0) {\n totalShiftedItems = -1 * val.length;\n if (this.remainingItems > 0) {\n this.isRemainingItemsAdded = true;\n }\n }\n\n if (totalShiftedItems !== this.totalShiftedItems()) {\n this.totalShiftedItems.set(totalShiftedItems);\n }\n }\n }\n }\n\n createStyle() {\n if (!this.carouselStyle) {\n const styleEl = this.renderer.createElement('style') as HTMLStyleElement;\n setAttribute(styleEl, 'nonce', this.config?.csp()?.nonce);\n this.renderer.appendChild(this.document.head, styleEl);\n this.carouselStyle = styleEl;\n }\n\n let innerHTML = `\n #${this.id} .p-carousel-item {\n\t\t\t\tflex: 1 0 ${100 / this._numVisible}%\n\t\t\t}\n `;\n\n const responsiveOpts = this.responsiveOptions();\n if (responsiveOpts && !this.$unstyled()) {\n responsiveOpts.sort((data1, data2) => {\n const value1 = data1.breakpoint;\n const value2 = data2.breakpoint;\n let result: number | null = null;\n\n if (value1 == null && value2 != null) result = -1;\n else if (value1 != null && value2 == null) result = 1;\n else if (value1 == null && value2 == null) result = 0;\n else if (typeof value1 === 'string' && typeof value2 === 'string') result = value1.localeCompare(value2, undefined, { numeric: true });\n else result = value1 < value2 ? -1 : value1 > value2 ? 1 : 0;\n\n return -1 * result;\n });\n\n for (let i = 0; i < responsiveOpts.length; i++) {\n let res = responsiveOpts[i];\n\n innerHTML += `\n @media screen and (max-width: ${res.breakpoint}) {\n #${this.id} .p-carousel-item {\n flex: 1 0 ${100 / res.numVisible}%\n }\n }\n `;\n }\n }\n\n this.carouselStyle!.innerHTML = innerHTML;\n }\n\n calculatePosition() {\n const responsiveOpts = this.responsiveOptions();\n if (responsiveOpts) {\n let matchedResponsiveData = {\n numVisible: this.defaultNumVisible,\n numScroll: this.defaultNumScroll\n };\n\n if (typeof window !== 'undefined') {\n let windowWidth = window.innerWidth;\n for (let i = 0; i < responsiveOpts.length; i++) {\n let res = responsiveOpts[i];\n\n if (parseInt(res.breakpoint, 10) >= windowWidth) {\n matchedResponsiveData = res;\n }\n }\n }\n\n if (this._numScroll !== matchedResponsiveData.numScroll) {\n let page = this._page();\n page = Math.floor((page * this._numScroll) / matchedResponsiveData.numScroll);\n\n let totalShiftedItems = matchedResponsiveData.numScroll * this._page() * -1;\n\n if (this.isCircular()) {\n totalShiftedItems -= matchedResponsiveData.numVisible;\n }\n\n this.totalShiftedItems.set(totalShiftedItems);\n this._numScroll = matchedResponsiveData.numScroll;\n\n this._page.set(page);\n this.onPage.emit({\n page: this._page()\n });\n }\n\n if (this._numVisible !== matchedResponsiveData.numVisible) {\n this._numVisible = matchedResponsiveData.numVisible;\n this.setCloneItems();\n }\n }\n }\n\n setCloneItems() {\n const val = this.value();\n if (this.isCircular() && val) {\n this.clonedItemsForStarting.set([...val.slice(-1 * this._numVisible)]);\n this.clonedItemsForFinishing.set([...val.slice(0, this._numVisible)]);\n } else {\n this.clonedItemsForStarting.set([]);\n this.clonedItemsForFinishing.set([]);\n }\n }\n\n firstIndex() {\n return this.isCircular() ? -1 * (this.totalShiftedItems() + this._numVisible) : this.totalShiftedItems() * -1;\n }\n\n lastIndex() {\n return this.firstIndex() + this._numVisible - 1;\n }\n\n totalDots() {\n const val = this.value();\n return val?.length ? Math.ceil((val.length - this._numVisible) / this._numScroll) + 1 : 0;\n }\n\n totalDotsArray() {\n const totalDots = this.totalDots();\n return totalDots <= 0 ? [] : Array.from({ length: totalDots }, (_, i) => i);\n }\n\n isVertical() {\n return this.orientation() === 'vertical';\n }\n\n isCircular() {\n const val = this.value();\n return this.circular() && val && val.length >= this._numVisible;\n }\n\n isAutoplay() {\n return this.autoplayInterval() && this.allowAutoplay();\n }\n\n isForwardNavDisabled() {\n return this.isEmpty() || (this._page() >= this.totalDots() - 1 && !this.isCircular());\n }\n\n isBackwardNavDisabled() {\n return this.isEmpty() || (this._page() <= 0 && !this.isCircular());\n }\n\n isEmpty() {\n const val = this.value();\n return !val || val.length === 0;\n }\n\n // Template helper methods\n hasHeader() {\n return !!(this.headerFacet() || this.headerTemplate());\n }\n\n hasFooter() {\n return !!(this.footerFacet() || this.footerTemplate());\n }\n\n ariaLive() {\n return this.allowAutoplay() ? 'polite' : 'off';\n }\n\n showDefaultPrevIcon() {\n return !this.previousIconTemplate();\n }\n\n showPrevIconTemplate() {\n return !!this.previousIconTemplate();\n }\n\n showDefaultNextIcon() {\n return !this.nextIconTemplate();\n }\n\n showNextIconTemplate() {\n return !!this.nextIconTemplate();\n }\n\n // Clone items (starting) helpers\n isCloneStartAriaHidden() {\n return !(this.totalShiftedItems() * -1 === this.value()?.length);\n }\n\n isCloneStartActive() {\n return this.totalShiftedItems() * -1 === (this.value()?.length ?? 0) + this.numVisible();\n }\n\n isCloneStartEnd(index: number) {\n const cloned = this.clonedItemsForStarting();\n return cloned.length > 0 && cloned.length - 1 === index;\n }\n\n // Main items helpers\n isItemActive(index: number) {\n return this.firstIndex() <= index && this.lastIndex() >= index;\n }\n\n isItemAriaHidden(index: number) {\n return !this.isItemActive(index);\n }\n\n isItemStart(index: number) {\n return this.firstIndex() === index;\n }\n\n isItemEnd(index: number) {\n return this.lastIndex() === index;\n }\n\n // Indicator helpers\n isIndicatorActive(index: number) {\n return this._page() === index;\n }\n\n getIndicatorAriaCurrent(index: number) {\n return this._page() === index ? 'page' : undefined;\n }\n\n getIndicatorTabindex(index: number) {\n return this._page() === index ? 0 : -1;\n }\n\n navForward(e: MouseEvent | TouchEvent, index?: number) {\n if (this.isCircular() || this._page() < this.totalDots() - 1) {\n this.step(-1, index);\n }\n\n if (this.autoplayInterval()) {\n this.stopAutoplay();\n }\n\n if (e && e.cancelable) {\n e.preventDefault();\n }\n }\n\n navBackward(e: MouseEvent | TouchEvent, index?: number) {\n if (this.isCircular() || this._page() !== 0) {\n this.step(1, index);\n }\n\n if (this.autoplayInterval()) {\n this.stopAutoplay();\n }\n\n if (e && e.cancelable) {\n e.preventDefault();\n }\n }\n\n onDotClick(e: MouseEvent, index: number) {\n let page = this._page();\n\n if (this.autoplayInterval()) {\n this.stopAutoplay();\n }\n\n if (index > page) {\n this.navForward(e, index);\n } else if (index < page) {\n this.navBackward(e, index);\n }\n }\n\n onIndicatorKeydown(event: KeyboardEvent) {\n switch (event.code) {\n case 'ArrowRight':\n this.onRightKey();\n break;\n\n case 'ArrowLeft':\n this.onLeftKey();\n break;\n }\n }\n\n onRightKey() {\n const indicators = [...find(this.indicatorContent()?.nativeElement, '[data-pc-section=\"indicator\"]')];\n const activeIndex = this.findFocusedIndicatorIndex();\n\n this.changedFocusedIndicator(activeIndex, activeIndex + 1 === indicators.length ? indicators.length - 1 : activeIndex + 1);\n }\n\n onLeftKey() {\n const activeIndex = this.findFocusedIndicatorIndex();\n\n this.changedFocusedIndicator(activeIndex, activeIndex - 1 <= 0 ? 0 : activeIndex - 1);\n }\n\n onHomeKey() {\n const activeIndex = this.findFocusedIndicatorIndex();\n\n this.changedFocusedIndicator(activeIndex, 0);\n }\n\n onEndKey() {\n const indicators = [...find(this.indicatorContent()?.nativeElement, '[data-pc-section=\"indicator\"]')];\n const activeIndex = this.findFocusedIndicatorIndex();\n\n this.changedFocusedIndicator(activeIndex, indicators.length - 1);\n }\n\n onTabKey() {\n const indicators = [...find(this.indicatorContent()?.nativeElement, '[data-pc-section=\"indicator\"]')] as HTMLElement[];\n const highlightedIndex = indicators.findIndex((ind) => getAttribute(ind, 'data-p-highlight') === true);\n\n const activeIndicator = findSingle(this.indicatorContent()?.nativeElement, '[data-pc-section=\"indicator\"] > button[tabindex=\"0\"]') as HTMLElement | null;\n const activeIndex = indicators.findIndex((ind) => ind === activeIndicator?.parentElement);\n\n if (activeIndex >= 0 && highlightedIndex >= 0) {\n (indicators[activeIndex].children[0] as HTMLElement).tabIndex = -1;\n (indicators[highlightedIndex].children[0] as HTMLElement).tabIndex = 0;\n }\n }\n\n findFocusedIndicatorIndex() {\n const indicators = [...find(this.indicatorContent()?.nativeElement, '[data-pc-section=\"indicator\"]')];\n const activeIndicator = findSingle(this.indicatorContent()?.nativeElement, '[data-pc-section=\"indicator\"] > button[tabindex=\"0\"]');\n\n return indicators.findIndex((ind) => ind === activeIndicator?.parentElement);\n }\n\n changedFocusedIndicator(prevInd: number, nextInd: number) {\n const indicators = [...find(this.indicatorContent()?.nativeElement, '[data-pc-section=\"indicator\"]')] as HTMLElement[];\n\n if (indicators[prevInd] && indicators[nextInd]) {\n (indicators[prevInd].children[0] as HTMLElement).tabIndex = -1;\n (indicators[nextInd].children[0] as HTMLElement).tabIndex = 0;\n (indicators[nextInd].children[0] as HTMLElement).focus();\n }\n }\n\n step(dir: number, page?: number) {\n let totalShiftedItems = this.totalShiftedItems();\n const isCircular = this.isCircular();\n const val = this.value();\n\n if (page != null) {\n totalShiftedItems = this._numScroll * page * -1;\n\n if (isCircular) {\n totalShiftedItems -= this._numVisible;\n }\n\n this.isRemainingItemsAdded = false;\n } else {\n totalShiftedItems += this._numScroll * dir;\n if (this.isRemainingItemsAdded) {\n totalShiftedItems += this.remainingItems - this._numScroll * dir;\n this.isRemainingItemsAdded = false;\n }\n\n let originalShiftedItems = isCircular ? totalShiftedItems + this._numVisible : totalShiftedItems;\n page = Math.abs(Math.floor(originalShiftedItems / this._numScroll));\n }\n\n if (isCircular && this._page() === this.totalDots() - 1 && dir === -1 && val) {\n totalShiftedItems = -1 * (val.length + this._numVisible);\n page = 0;\n } else if (isCircular && this._page() === 0 && dir === 1) {\n totalShiftedItems = 0;\n page = this.totalDots() - 1;\n } else if (page === this.totalDots() - 1 && this.remainingItems > 0) {\n totalShiftedItems += this.remainingItems * -1 - this._numScroll * dir;\n this.isRemainingItemsAdded = true;\n }\n\n const itemsContainerEl = this.itemsContainer();\n if (itemsContainerEl) {\n !this.$unstyled() && removeClass(itemsContainerEl.nativeElement, 'p-items-hidden');\n itemsContainerEl.nativeElement.style.transform = this.isVertical() ? `translate3d(0, ${totalShiftedItems * (100 / this._numVisible)}%, 0)` : `translate3d(${totalShiftedItems * (100 / this._numVisible)}%, 0, 0)`;\n itemsContainerEl.nativeElement.style.transition = 'transform 500ms ease 0s';\n }\n\n this.totalShiftedItems.set(totalShiftedItems);\n this._page.set(page);\n this.onPage.emit({\n page: this._page()\n });\n }\n\n startAutoplay() {\n if (this.interval) {\n clearInterval(this.interval);\n }\n\n this.interval = setInterval(() => {\n if (this.totalDots() > 0) {\n if (this._page() === this.totalDots() - 1) {\n this.step(-1, 0);\n } else {\n this.step(-1, this._page() + 1);\n }\n }\n }, this.autoplayInterval());\n this.allowAutoplay.set(true);\n }\n\n stopAutoplay(changeAllow: boolean = true) {\n if (this.interval) {\n clearInterval(this.interval);\n this.interval = undefined;\n if (changeAllow) {\n this.allowAutoplay.set(false);\n }\n }\n }\n\n isPlaying(): boolean {\n return !!this.interval;\n }\n\n onTransitionEnd() {\n const itemsContainerEl = this.itemsContainer();\n if (itemsContainerEl) {\n !this.$unstyled() && addClass(itemsContainerEl.nativeElement, 'p-items-hidden');\n itemsContainerEl.nativeElement.style.transition = '';\n\n if ((this._page() === 0 || this._page() === this.totalDots() - 1) && this.isCircular()) {\n itemsContainerEl.nativeElement.style.transform = this.isVertical() ? `translate3d(0, ${this.totalShiftedItems() * (100 / this._numVisible)}%, 0)` : `translate3d(${this.totalShiftedItems() * (100 / this._numVisible)}%, 0, 0)`;\n }\n }\n }\n\n onTouchStart(e: TouchEvent) {\n let touchobj = e.changedTouches[0];\n\n this.startPos = {\n x: touchobj.pageX,\n y: touchobj.pageY\n };\n }\n\n onTouchMove(e: TouchEvent | MouseEvent) {\n if (e.cancelable) {\n e.preventDefault();\n }\n }\n\n onTouchEnd(e: TouchEvent) {\n if (!this.startPos) return;\n\n const touchobj = e.changedTouches[0];\n\n if (this.isVertical()) {\n this.changePageOnTouch(e, touchobj.pageY - this.startPos.y);\n } else {\n this.changePageOnTouch(e, touchobj.pageX - this.startPos.x);\n }\n }\n\n changePageOnTouch(e: TouchEvent | MouseEvent, diff: number) {\n if (Math.abs(diff) > this.swipeThreshold) {\n if (diff < 0) {\n this.navForward(e);\n } else {\n this.navBackward(e);\n }\n }\n }\n\n ariaPrevButtonLabel() {\n return this.config.translation.aria ? this.config.translation.aria?.prevPageLabel : undefined;\n }\n\n ariaSlideLabel() {\n return this.config.translation.aria ? this.config.translation.aria?.slide : undefined;\n }\n\n ariaNextButtonLabel() {\n return this.config.translation.aria ? this.config.translation.aria?.nextPageLabel : undefined;\n }\n\n ariaSlideNumber(value: number) {\n return this.config.translation.aria ? this.config.translation.aria?.slideNumber?.replace(/{slideNumber}/g, String(value)) : undefined;\n }\n\n ariaPageLabel(value: number) {\n return this.config.translation.aria ? this.config.translation.aria?.pageLabel?.replace(/{page}/g, String(value)) : undefined;\n }\n\n getIndicatorPTOptions(key: string, index: number) {\n return this.ptm(key, {\n context: {\n highlighted: index === this._page()\n }\n });\n }\n\n getItemPTOptions(key: string, index: number) {\n return this.ptm(key, {\n context: {\n index,\n active: this.firstIndex() <= index && this.lastIndex() >= index,\n start: this.firstIndex() === index,\n end: this.lastIndex() === index\n }\n });\n }\n\n bindDocumentListeners() {\n if (isPlatformBrowser(this.platformId)) {\n if (!this.documentResizeListener) {\n this.documentResizeListener = this.renderer.listen(this.window, 'resize', () => {\n this.calculatePosition();\n });\n }\n }\n }\n\n unbindDocumentListeners() {\n if (isPlatformBrowser(this.platformId)) {\n if (this.documentResizeListener) {\n this.documentResizeListener();\n this.documentResizeListener = null;\n }\n }\n }\n\n legacyOnDestroy() {\n this.unbindDocumentListeners();\n this.stopAutoplay();\n\n if (this.carouselStyle) {\n this.carouselStyle.remove();\n this.carouselStyle = null;\n }\n }\n}\n","import { NgTemplateOutlet } from '@angular/common';\nimport { booleanAttribute, ChangeDetectionStrategy, Component, computed, contentChildren, effect, inject, input, NgModule, numberAttribute, output, signal, untracked, ViewEncapsulation } from '@angular/core';\nimport { SharedModule } from 'primeng/api';\nimport { PARENT_INSTANCE } from 'primeng/basecomponent';\nimport