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,020 lines (1,015 loc) • 109 kB
JavaScript
export * from 'primeng/types/galleria';
import * as i0 from '@angular/core';
import { InjectionToken, input, inject, computed, ChangeDetectionStrategy, Component, Injectable, booleanAttribute, output, linkedSignal, effect, viewChild, model, HostListener, numberAttribute, signal, contentChild, ElementRef, ViewEncapsulation, NgModule } from '@angular/core';
import { removeClass, setAttribute, find, getAttribute, findSingle, addClass, uuid, focus } from '@primeuix/utils';
import { SharedModule } from 'primeng/api';
import { BaseComponent, PARENT_INSTANCE } from 'primeng/basecomponent';
import * as i1 from 'primeng/bind';
import { Bind, BindModule } from 'primeng/bind';
import { blockBodyScroll, unblockBodyScroll } from 'primeng/dom';
import { FocusTrap } from 'primeng/focustrap';
import * as i2 from 'primeng/motion';
import { MotionModule } from 'primeng/motion';
import { ZIndexUtils } from 'primeng/utils';
import { NgTemplateOutlet, isPlatformBrowser } from '@angular/common';
import { Times } from '@primeicons/angular/times';
import { ChevronLeft } from '@primeicons/angular/chevron-left';
import { ChevronRight } from '@primeicons/angular/chevron-right';
import { style } from '@primeuix/styles/galleria';
import { BaseStyle } from 'primeng/base';
import { ChevronDown } from '@primeicons/angular/chevron-down';
import { ChevronUp } from '@primeicons/angular/chevron-up';
import { Ripple } from 'primeng/ripple';
const GALLERIA_INSTANCE = new InjectionToken('GALLERIA_INSTANCE');
class GalleriaItemSlot extends BaseComponent {
hostName = 'Galleria';
index = input(/* @ts-ignore */
...(ngDevMode ? [undefined, { debugName: "index" }] : /* istanbul ignore next */ []));
item = input(/* @ts-ignore */
...(ngDevMode ? [undefined, { debugName: "item" }] : /* istanbul ignore next */ []));
type = input(/* @ts-ignore */
...(ngDevMode ? [undefined, { debugName: "type" }] : /* istanbul ignore next */ []));
galleria = inject(GALLERIA_INSTANCE);
$pcGalleria = inject(GALLERIA_INSTANCE, { optional: true, skipSelf: true }) ?? undefined;
contentTemplate = computed(() => {
const type = this.type();
switch (type) {
case 'item':
return this.galleria.itemTemplate();
case 'caption':
return this.galleria.captionTemplate();
case 'thumbnail':
return this.galleria.thumbnailTemplate();
case 'indicator':
return this.galleria.indicatorTemplate();
case 'footer':
return this.galleria.footerTemplate();
case 'header':
return this.galleria.headerTemplate();
default:
return this.galleria.itemTemplate();
}
}, /* @ts-ignore */
...(ngDevMode ? [{ debugName: "contentTemplate" }] : /* istanbul ignore next */ []));
context = computed(() => {
const type = this.type();
if (type === 'indicator') {
return { $implicit: this.index() };
}
return { $implicit: this.item() };
}, /* @ts-ignore */
...(ngDevMode ? [{ debugName: "context" }] : /* istanbul ignore next */ []));
shouldRender() {
return !!this.contentTemplate();
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: GalleriaItemSlot, deps: null, target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.6", type: GalleriaItemSlot, isStandalone: true, selector: "div[pGalleriaItemSlot]", inputs: { index: { classPropertyName: "index", publicName: "index", isSignal: true, isRequired: false, transformFunction: null }, item: { classPropertyName: "item", publicName: "item", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: `
@if (shouldRender()) {
<ng-container [ngTemplateOutlet]="contentTemplate()" [ngTemplateOutletContext]="context()"></ng-container>
}
`, isInline: true, dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: GalleriaItemSlot, decorators: [{
type: Component,
args: [{
selector: 'div[pGalleriaItemSlot]',
standalone: true,
imports: [NgTemplateOutlet],
template: `
@if (shouldRender()) {
<ng-container [ngTemplateOutlet]="contentTemplate()" [ngTemplateOutletContext]="context()"></ng-container>
}
`,
changeDetection: ChangeDetectionStrategy.OnPush
}]
}], propDecorators: { index: [{ type: i0.Input, args: [{ isSignal: true, alias: "index", required: false }] }], item: [{ type: i0.Input, args: [{ isSignal: true, alias: "item", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }] } });
const classes = {
mask: 'p-galleria-mask p-overlay-mask',
root: ({ instance }) => {
const thumbnailsPosClass = instance.galleria.showThumbnails() && instance.getPositionClass('p-galleria-thumbnails', instance.galleria.thumbnailsPosition());
const indicatorPosClass = instance.galleria.showIndicators() && instance.getPositionClass('p-galleria-indicators', instance.galleria.indicatorsPosition());
return [
'p-galleria p-component',
{
'p-galleria-fullscreen': instance.galleria.fullScreen(),
'p-galleria-inset-indicators': instance.galleria.showIndicatorsOnItem(),
'p-galleria-hover-navigators': instance.galleria.showItemNavigatorsOnHover() && !instance.galleria.fullScreen()
},
thumbnailsPosClass,
indicatorPosClass
];
},
closeButton: 'p-galleria-close-button',
closeIcon: 'p-galleria-close-icon',
header: 'p-galleria-header',
content: 'p-galleria-content',
footer: 'p-galleria-footer',
itemsContainer: 'p-galleria-items-container',
items: 'p-galleria-items',
prevButton: ({ instance }) => [
'p-galleria-prev-button p-galleria-nav-button',
{
'p-disabled': instance.isNavBackwardDisabled()
}
],
prevIcon: 'p-galleria-prev-icon',
item: 'p-galleria-item',
nextButton: ({ instance }) => [
'p-galleria-next-button p-galleria-nav-button',
{
'p-disabled': instance.isNavForwardDisabled()
}
],
nextIcon: 'p-galleria-next-icon',
caption: 'p-galleria-caption',
indicatorList: 'p-galleria-indicator-list',
indicator: ({ instance, index }) => [
'p-galleria-indicator',
{
'p-galleria-indicator-active': instance.isIndicatorItemActive(index)
}
],
indicatorButton: 'p-galleria-indicator-button',
thumbnails: 'p-galleria-thumbnails',
thumbnailContent: 'p-galleria-thumbnails-content',
thumbnailPrevButton: ({ instance }) => [
'p-galleria-thumbnail-prev-button p-galleria-thumbnail-nav-button',
{
'p-disabled': instance.isNavBackwardDisabled()
}
],
thumbnailPrevIcon: 'p-galleria-thumbnail-prev-icon',
thumbnailsViewport: 'p-galleria-thumbnails-viewport',
thumbnailItems: 'p-galleria-thumbnail-items',
thumbnailItem: ({ instance, index, activeIndex }) => [
'p-galleria-thumbnail-item',
{
'p-galleria-thumbnail-item-current': activeIndex === index,
'p-galleria-thumbnail-item-active': instance.isItemActive(index),
'p-galleria-thumbnail-item-start': instance.firstItemAciveIndex() === index,
'p-galleria-thumbnail-item-end': instance.lastItemActiveIndex() === index
}
],
thumbnail: 'p-galleria-thumbnail',
thumbnailNextButton: ({ instance }) => [
'p-galleria-thumbnail-next-button p-galleria-thumbnail-nav-button',
{
'p-disabled': instance.isNavForwardDisabled()
}
],
thumbnailNextIcon: 'p-galleria-thumbnail-next-icon'
};
class GalleriaStyle extends BaseStyle {
name = 'galleria';
style = style;
classes = classes;
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: GalleriaStyle, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: GalleriaStyle });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: GalleriaStyle, decorators: [{
type: Injectable
}] });
/**
*
* Galleria is an advanced content gallery component.
*
* [Live Demo](https://www.primeng.org/galleria/)
*
* @module galleriastyle
*
*/
var GalleriaClasses;
(function (GalleriaClasses) {
/**
* Class name of the mask element
*/
GalleriaClasses["mask"] = "p-galleria-mask";
/**
* Class name of the root element
*/
GalleriaClasses["root"] = "p-galleria";
/**
* Class name of the close button element
*/
GalleriaClasses["closeButton"] = "p-galleria-close-button";
/**
* Class name of the close icon element
*/
GalleriaClasses["closeIcon"] = "p-galleria-close-icon";
/**
* Class name of the header element
*/
GalleriaClasses["header"] = "p-galleria-header";
/**
* Class name of the content element
*/
GalleriaClasses["content"] = "p-galleria-content";
/**
* Class name of the footer element
*/
GalleriaClasses["footer"] = "p-galleria-footer";
/**
* Class name of the items container element
*/
GalleriaClasses["itemsContainer"] = "p-galleria-items-container";
/**
* Class name of the items element
*/
GalleriaClasses["items"] = "p-galleria-items";
/**
* Class name of the previous item button element
*/
GalleriaClasses["prevButton"] = "p-galleria-prev-button";
/**
* Class name of the previous item icon element
*/
GalleriaClasses["prevIcon"] = "p-galleria-prev-icon";
/**
* Class name of the item element
*/
GalleriaClasses["item"] = "p-galleria-item";
/**
* Class name of the next item button element
*/
GalleriaClasses["nextButton"] = "p-galleria-next-button";
/**
* Class name of the next item icon element
*/
GalleriaClasses["nextIcon"] = "p-galleria-next-icon";
/**
* Class name of the caption element
*/
GalleriaClasses["caption"] = "p-galleria-caption";
/**
* Class name of the indicator list element
*/
GalleriaClasses["indicatorList"] = "p-galleria-indicator-list";
/**
* Class name of the indicator element
*/
GalleriaClasses["indicator"] = "p-galleria-indicator";
/**
* Class name of the indicator button element
*/
GalleriaClasses["indicatorButton"] = "p-galleria-indicator-button";
/**
* Class name of the thumbnails element
*/
GalleriaClasses["thumbnails"] = "p-galleria-thumbnails";
/**
* Class name of the thumbnail content element
*/
GalleriaClasses["thumbnailContent"] = "p-galleria-thumbnails-content";
/**
* Class name of the previous thumbnail button element
*/
GalleriaClasses["previousThumbnailButton"] = "p-galleria-thumbnail-prev-button";
/**
* Class name of the previous thumbnail icon element
*/
GalleriaClasses["previousThumbnailIcon"] = "p-galleria-thumbnail-prev-icon";
/**
* Class name of the thumbnails viewport element
*/
GalleriaClasses["thumbnailsViewport"] = "p-galleria-thumbnails-viewport";
/**
* Class name of the thumbnail items element
*/
GalleriaClasses["thumbnailItems"] = "p-galleria-thumbnail-items";
/**
* Class name of the thumbnail item element
*/
GalleriaClasses["thumbnailItem"] = "p-galleria-thumbnail-item";
/**
* Class name of the thumbnail element
*/
GalleriaClasses["thumbnail"] = "p-galleria-thumbnail";
/**
* Class name of the next thumbnail button element
*/
GalleriaClasses["nextThumbnailButton"] = "p-galleria-thumbnail-next-button";
/**
* Class name of the next thumbnail icon element
*/
GalleriaClasses["nextThumbnailIcon"] = "p-galleria-thumbnail-next-icon";
})(GalleriaClasses || (GalleriaClasses = {}));
class GalleriaItem extends BaseComponent {
hostName = 'Galleria';
galleria = inject(GALLERIA_INSTANCE);
bindDirectiveInstance = inject(Bind, { self: true });
onAfterViewChecked() {
this.bindDirectiveInstance.setAttrs(this.ptm('itemsContainer'));
}
id = input(/* @ts-ignore */
...(ngDevMode ? [undefined, { debugName: "id" }] : /* istanbul ignore next */ []));
circular = input(false, { ...(ngDevMode ? { debugName: "circular" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
value = input(/* @ts-ignore */
...(ngDevMode ? [undefined, { debugName: "value" }] : /* istanbul ignore next */ []));
showItemNavigators = input(false, { ...(ngDevMode ? { debugName: "showItemNavigators" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
showIndicators = input(true, { ...(ngDevMode ? { debugName: "showIndicators" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
slideShowActive = input(true, { ...(ngDevMode ? { debugName: "slideShowActive" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
changeItemOnIndicatorHover = input(true, { ...(ngDevMode ? { debugName: "changeItemOnIndicatorHover" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
autoPlay = input(false, { ...(ngDevMode ? { debugName: "autoPlay" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
startSlideShow = output();
stopSlideShow = output();
onActiveIndexChange = output();
_componentStyle = inject(GalleriaStyle);
_activeIndex = linkedSignal(() => this.activeIndexInput(), /* @ts-ignore */
...(ngDevMode ? [{ debugName: "_activeIndex" }] : /* istanbul ignore next */ []));
activeItem = computed(() => {
const val = this.value();
return val && val[this._activeIndex()];
}, /* @ts-ignore */
...(ngDevMode ? [{ debugName: "activeItem" }] : /* istanbul ignore next */ []));
activeItemId = computed(() => this.id() + '_item_' + this._activeIndex(), /* @ts-ignore */
...(ngDevMode ? [{ debugName: "activeItemId" }] : /* istanbul ignore next */ []));
leftButtonFocused = false;
rightButtonFocused = false;
get aria() {
return this.galleria.config.translation.aria;
}
constructor() {
super();
// Handle autoPlay changes
effect(() => {
const auto = this.autoPlay();
if (auto) {
this.startSlideShow.emit();
}
});
}
activeIndexInput = input(0, { ...(ngDevMode ? { debugName: "activeIndexInput" } : /* istanbul ignore next */ {}), alias: 'activeIndex' });
getIndicatorPTOptions(index) {
return this.ptm('indicator', {
context: {
highlighted: this._activeIndex() === index
}
});
}
next() {
const val = this.value();
const currentIndex = this._activeIndex();
let nextItemIndex = currentIndex + 1;
let activeIndex = this.circular() && val.length - 1 === currentIndex ? 0 : nextItemIndex;
this.onActiveIndexChange.emit(activeIndex);
}
prev() {
const val = this.value();
const currentIndex = this._activeIndex();
let prevItemIndex = currentIndex !== 0 ? currentIndex - 1 : 0;
let activeIndex = this.circular() && currentIndex === 0 ? val.length - 1 : prevItemIndex;
this.onActiveIndexChange.emit(activeIndex);
}
onButtonFocus(pos) {
if (pos === 'left') {
this.leftButtonFocused = true;
}
else
this.rightButtonFocused = true;
}
onButtonBlur(pos) {
if (pos === 'left') {
this.leftButtonFocused = false;
}
else
this.rightButtonFocused = false;
}
stopTheSlideShow() {
if (this.slideShowActive()) {
this.stopSlideShow.emit();
}
}
navForward(e) {
this.stopTheSlideShow();
this.next();
if (e && e.cancelable) {
e.stopPropagation();
e.preventDefault();
}
}
navBackward(e) {
this.stopTheSlideShow();
this.prev();
if (e && e.cancelable) {
e.stopPropagation();
e.preventDefault();
}
}
onIndicatorClick(index) {
this.stopTheSlideShow();
this.onActiveIndexChange.emit(index);
}
onIndicatorMouseEnter(index) {
if (this.changeItemOnIndicatorHover()) {
this.stopTheSlideShow();
this.onActiveIndexChange.emit(index);
}
}
onIndicatorKeyDown(event, index) {
switch (event.code) {
case 'Enter':
case 'Space':
this.stopTheSlideShow();
this.onActiveIndexChange.emit(index);
event.preventDefault();
break;
case 'ArrowDown':
case 'ArrowUp':
event.preventDefault();
break;
default:
break;
}
}
isNavForwardDisabled() {
const val = this.value();
return !this.circular() && this._activeIndex() === val.length - 1;
}
isNavBackwardDisabled() {
return !this.circular() && this._activeIndex() === 0;
}
isIndicatorItemActive(index) {
return this._activeIndex() === index;
}
ariaSlideLabel() {
return this.aria?.slide;
}
ariaSlideNumber(value) {
return this.aria?.slideNumber?.replace(/{slideNumber}/g, value);
}
ariaPageLabel(value) {
return this.aria?.pageLabel?.replace(/{page}/g, value);
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: GalleriaItem, deps: [], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.6", type: GalleriaItem, isStandalone: true, selector: "div[pGalleriaItem]", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, circular: { classPropertyName: "circular", publicName: "circular", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, showItemNavigators: { classPropertyName: "showItemNavigators", publicName: "showItemNavigators", isSignal: true, isRequired: false, transformFunction: null }, showIndicators: { classPropertyName: "showIndicators", publicName: "showIndicators", isSignal: true, isRequired: false, transformFunction: null }, slideShowActive: { classPropertyName: "slideShowActive", publicName: "slideShowActive", isSignal: true, isRequired: false, transformFunction: null }, changeItemOnIndicatorHover: { classPropertyName: "changeItemOnIndicatorHover", publicName: "changeItemOnIndicatorHover", isSignal: true, isRequired: false, transformFunction: null }, autoPlay: { classPropertyName: "autoPlay", publicName: "autoPlay", isSignal: true, isRequired: false, transformFunction: null }, activeIndexInput: { classPropertyName: "activeIndexInput", publicName: "activeIndex", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { startSlideShow: "startSlideShow", stopSlideShow: "stopSlideShow", onActiveIndexChange: "onActiveIndexChange" }, providers: [GalleriaStyle], usesInheritance: true, hostDirectives: [{ directive: i1.Bind }], ngImport: i0, template: `
<div [pBind]="ptm('items')" [class]="cx('items')">
@if (showItemNavigators()) {
<button type="button" role="navigation" [pBind]="ptm('prevButton')" [class]="cx('prevButton')" (click)="navBackward($event)" (focus)="onButtonFocus('left')" (blur)="onButtonBlur('left')" data-pc-group-section="itemnavigator">
@if (!galleria.itemPreviousIconTemplate()) {
<svg data-p-icon="chevron-left" [pBind]="ptm('prevIcon')" [class]="cx('prevIcon')" />
}
<ng-template [ngTemplateOutlet]="galleria.itemPreviousIconTemplate()"></ng-template>
</button>
}
<div
pGalleriaItemSlot
[pBind]="ptm('item')"
[unstyled]="unstyled()"
[class]="cx('item')"
[item]="activeItem()"
[id]="activeItemId()"
role="group"
[attr.aria-label]="ariaSlideNumber(_activeIndex() + 1)"
[attr.aria-roledescription]="ariaSlideLabel()"
></div>
@if (showItemNavigators()) {
<button type="button" [pBind]="ptm('nextButton')" [class]="cx('nextButton')" (click)="navForward($event)" role="navigation" (focus)="onButtonFocus('right')" (blur)="onButtonBlur('right')" data-pc-group-section="itemnavigator">
@if (!galleria.itemNextIconTemplate()) {
<svg data-p-icon="chevron-right" [pBind]="ptm('nextIcon')" [class]="cx('nextIcon')" />
}
<ng-template [ngTemplateOutlet]="galleria.itemNextIconTemplate()"></ng-template>
</button>
}
@if (galleria.captionTemplate()) {
<div pGalleriaItemSlot [pBind]="ptm('caption')" [unstyled]="unstyled()" [class]="cx('caption')" type="caption" [item]="activeItem()"></div>
}
</div>
@if (showIndicators()) {
<ul [pBind]="ptm('indicatorList')" [class]="cx('indicatorList')">
@for (item of value(); track $index) {
<li
[pBind]="getIndicatorPTOptions($index)"
tabindex="0"
(click)="onIndicatorClick($index)"
(mouseenter)="onIndicatorMouseEnter($index)"
(keydown)="onIndicatorKeyDown($event, $index)"
[class]="cx('indicator', { index: $index })"
[attr.aria-label]="ariaPageLabel($index + 1)"
[attr.aria-selected]="_activeIndex() === $index"
[attr.aria-controls]="id() + '_item_' + $index"
[pBind]="ptm('indicator', getIndicatorPTOptions($index))"
[attr.data-p-active]="isIndicatorItemActive($index)"
>
@if (!galleria.indicatorTemplate()) {
<button type="button" tabIndex="-1" [pBind]="ptm('indicatorButton', getIndicatorPTOptions($index))" [class]="cx('indicatorButton')"></button>
} @else {
<div pGalleriaItemSlot type="indicator" [index]="$index" [pBind]="ptm('item')" [unstyled]="unstyled()"></div>
}
</li>
}
</ul>
}
`, isInline: true, dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: BindModule }, { kind: "directive", type: i1.Bind, selector: "[pBind]", inputs: ["pBind"] }, { kind: "component", type: ChevronLeft, selector: "svg[data-p-icon=\"chevron-left\"]" }, { kind: "component", type: ChevronRight, selector: "svg[data-p-icon=\"chevron-right\"]" }, { kind: "component", type: GalleriaItemSlot, selector: "div[pGalleriaItemSlot]", inputs: ["index", "item", "type"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: GalleriaItem, decorators: [{
type: Component,
args: [{
selector: 'div[pGalleriaItem]',
standalone: true,
imports: [NgTemplateOutlet, BindModule, ChevronLeft, ChevronRight, GalleriaItemSlot],
template: `
<div [pBind]="ptm('items')" [class]="cx('items')">
@if (showItemNavigators()) {
<button type="button" role="navigation" [pBind]="ptm('prevButton')" [class]="cx('prevButton')" (click)="navBackward($event)" (focus)="onButtonFocus('left')" (blur)="onButtonBlur('left')" data-pc-group-section="itemnavigator">
@if (!galleria.itemPreviousIconTemplate()) {
<svg data-p-icon="chevron-left" [pBind]="ptm('prevIcon')" [class]="cx('prevIcon')" />
}
<ng-template [ngTemplateOutlet]="galleria.itemPreviousIconTemplate()"></ng-template>
</button>
}
<div
pGalleriaItemSlot
[pBind]="ptm('item')"
[unstyled]="unstyled()"
[class]="cx('item')"
[item]="activeItem()"
[id]="activeItemId()"
role="group"
[attr.aria-label]="ariaSlideNumber(_activeIndex() + 1)"
[attr.aria-roledescription]="ariaSlideLabel()"
></div>
@if (showItemNavigators()) {
<button type="button" [pBind]="ptm('nextButton')" [class]="cx('nextButton')" (click)="navForward($event)" role="navigation" (focus)="onButtonFocus('right')" (blur)="onButtonBlur('right')" data-pc-group-section="itemnavigator">
@if (!galleria.itemNextIconTemplate()) {
<svg data-p-icon="chevron-right" [pBind]="ptm('nextIcon')" [class]="cx('nextIcon')" />
}
<ng-template [ngTemplateOutlet]="galleria.itemNextIconTemplate()"></ng-template>
</button>
}
@if (galleria.captionTemplate()) {
<div pGalleriaItemSlot [pBind]="ptm('caption')" [unstyled]="unstyled()" [class]="cx('caption')" type="caption" [item]="activeItem()"></div>
}
</div>
@if (showIndicators()) {
<ul [pBind]="ptm('indicatorList')" [class]="cx('indicatorList')">
@for (item of value(); track $index) {
<li
[pBind]="getIndicatorPTOptions($index)"
tabindex="0"
(click)="onIndicatorClick($index)"
(mouseenter)="onIndicatorMouseEnter($index)"
(keydown)="onIndicatorKeyDown($event, $index)"
[class]="cx('indicator', { index: $index })"
[attr.aria-label]="ariaPageLabel($index + 1)"
[attr.aria-selected]="_activeIndex() === $index"
[attr.aria-controls]="id() + '_item_' + $index"
[pBind]="ptm('indicator', getIndicatorPTOptions($index))"
[attr.data-p-active]="isIndicatorItemActive($index)"
>
@if (!galleria.indicatorTemplate()) {
<button type="button" tabIndex="-1" [pBind]="ptm('indicatorButton', getIndicatorPTOptions($index))" [class]="cx('indicatorButton')"></button>
} @else {
<div pGalleriaItemSlot type="indicator" [index]="$index" [pBind]="ptm('item')" [unstyled]="unstyled()"></div>
}
</li>
}
</ul>
}
`,
changeDetection: ChangeDetectionStrategy.OnPush,
providers: [GalleriaStyle],
hostDirectives: [Bind]
}]
}], ctorParameters: () => [], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], circular: [{ type: i0.Input, args: [{ isSignal: true, alias: "circular", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], showItemNavigators: [{ type: i0.Input, args: [{ isSignal: true, alias: "showItemNavigators", required: false }] }], showIndicators: [{ type: i0.Input, args: [{ isSignal: true, alias: "showIndicators", required: false }] }], slideShowActive: [{ type: i0.Input, args: [{ isSignal: true, alias: "slideShowActive", required: false }] }], changeItemOnIndicatorHover: [{ type: i0.Input, args: [{ isSignal: true, alias: "changeItemOnIndicatorHover", required: false }] }], autoPlay: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoPlay", required: false }] }], startSlideShow: [{ type: i0.Output, args: ["startSlideShow"] }], stopSlideShow: [{ type: i0.Output, args: ["stopSlideShow"] }], onActiveIndexChange: [{ type: i0.Output, args: ["onActiveIndexChange"] }], activeIndexInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeIndex", required: false }] }] } });
class GalleriaThumbnails extends BaseComponent {
hostName = 'Galleria';
galleria = inject(GALLERIA_INSTANCE);
bindDirectiveInstance = inject(Bind, { self: true });
onAfterViewChecked() {
this.bindDirectiveInstance.setAttrs(this.ptm('thumbnails'));
}
containerId = input(/* @ts-ignore */
...(ngDevMode ? [undefined, { debugName: "containerId" }] : /* istanbul ignore next */ []));
value = input(/* @ts-ignore */
...(ngDevMode ? [undefined, { debugName: "value" }] : /* istanbul ignore next */ []));
isVertical = input(false, { ...(ngDevMode ? { debugName: "isVertical" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
slideShowActive = input(false, { ...(ngDevMode ? { debugName: "slideShowActive" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
circular = input(false, { ...(ngDevMode ? { debugName: "circular" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
responsiveOptions = input(/* @ts-ignore */
...(ngDevMode ? [undefined, { debugName: "responsiveOptions" }] : /* istanbul ignore next */ []));
contentHeight = input('300px', /* @ts-ignore */
...(ngDevMode ? [{ debugName: "contentHeight" }] : /* istanbul ignore next */ []));
showThumbnailNavigators = input(true, { ...(ngDevMode ? { debugName: "showThumbnailNavigators" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
numVisibleInput = input(0, { ...(ngDevMode ? { debugName: "numVisibleInput" } : /* istanbul ignore next */ {}), alias: 'numVisible' });
activeIndexInput = input(0, { ...(ngDevMode ? { debugName: "activeIndexInput" } : /* istanbul ignore next */ {}), alias: 'activeIndex' });
onActiveIndexChange = output();
stopSlideShow = output();
itemsContainer = viewChild('itemsContainer', /* @ts-ignore */
...(ngDevMode ? [{ debugName: "itemsContainer" }] : /* istanbul ignore next */ []));
index;
startPos = null;
thumbnailsStyle = null;
sortedResponsiveOptions = null;
totalShiftedItems = 0;
page = 0;
documentResizeListener;
_numVisible = linkedSignal(() => this.numVisibleInput(), /* @ts-ignore */
...(ngDevMode ? [{ debugName: "_numVisible" }] : /* istanbul ignore next */ []));
_oldNumVisible = 0;
d_numVisible = linkedSignal({ ...(ngDevMode ? { debugName: "d_numVisible" } : /* istanbul ignore next */ {}), source: () => this.numVisibleInput(),
computation: (source, previous) => {
if (previous) {
this._oldNumVisible = previous.value;
}
return source;
} });
_oldactiveIndex = 0;
_activeIndex = linkedSignal({ ...(ngDevMode ? { debugName: "_activeIndex" } : /* istanbul ignore next */ {}), source: () => this.activeIndexInput(),
computation: (source, previous) => {
if (previous) {
this._oldactiveIndex = previous.value;
}
return source;
} });
_componentStyle = inject(GalleriaStyle);
viewportHeight = computed(() => (this.isVertical() ? this.contentHeight() : ''), /* @ts-ignore */
...(ngDevMode ? [{ debugName: "viewportHeight" }] : /* istanbul ignore next */ []));
get aria() {
return this.galleria.config.translation.aria;
}
isActiveItem(index) {
return this._activeIndex() === index;
}
getItemTabIndex(index) {
return this.isActiveItem(index) ? 0 : -1;
}
getAriaCurrent(index) {
return this.isActiveItem(index) ? 'page' : undefined;
}
getAriaControls(index) {
return this.containerId() + '_item_' + index;
}
onInit() {
if (isPlatformBrowser(this.platformId)) {
this.createStyle();
if (this.responsiveOptions()) {
this.bindDocumentListeners();
}
}
}
onAfterContentChecked() {
let totalShiftedItems = this.totalShiftedItems;
const d_numVisible = this.d_numVisible();
const activeIndex = this._activeIndex();
const itemsContainer = this.itemsContainer();
const val = this.value();
if ((this._oldNumVisible !== d_numVisible || this._oldactiveIndex !== activeIndex) && itemsContainer) {
if (activeIndex <= this.getMedianItemIndex()) {
totalShiftedItems = 0;
}
else if (val.length - d_numVisible + this.getMedianItemIndex() < activeIndex) {
totalShiftedItems = d_numVisible - val.length;
}
else if (val.length - d_numVisible < activeIndex && d_numVisible % 2 === 0) {
totalShiftedItems = activeIndex * -1 + this.getMedianItemIndex() + 1;
}
else {
totalShiftedItems = activeIndex * -1 + this.getMedianItemIndex();
}
if (totalShiftedItems !== this.totalShiftedItems) {
this.totalShiftedItems = totalShiftedItems;
}
if (itemsContainer && itemsContainer.nativeElement) {
itemsContainer.nativeElement.style.transform = this.isVertical() ? `translate3d(0, ${totalShiftedItems * (100 / d_numVisible)}%, 0)` : `translate3d(${totalShiftedItems * (100 / d_numVisible)}%, 0, 0)`;
}
if (this._oldactiveIndex !== activeIndex) {
this.document.body.setAttribute('data-p-items-hidden', 'false');
!this.$unstyled() && removeClass(itemsContainer.nativeElement, 'p-items-hidden');
itemsContainer.nativeElement.style.transition = 'transform 500ms ease 0s';
}
this._oldactiveIndex = activeIndex;
this._oldNumVisible = d_numVisible;
}
}
onAfterViewInit() {
if (isPlatformBrowser(this.platformId)) {
this.calculatePosition();
}
}
createStyle() {
if (!this.thumbnailsStyle) {
this.thumbnailsStyle = this.document.createElement('style');
setAttribute(this.thumbnailsStyle, 'nonce', this.galleria.config?.csp()?.nonce);
this.document.body.appendChild(this.thumbnailsStyle);
}
const d_numVisible = this.d_numVisible();
let innerHTML = `
#${this.containerId()} .p-galleria-thumbnail-item {
flex: 1 0 ${100 / d_numVisible}%
}
`;
const responsiveOptions = this.responsiveOptions();
if (responsiveOptions && !this.$unstyled()) {
this.sortedResponsiveOptions = [...responsiveOptions];
this.sortedResponsiveOptions.sort((data1, data2) => {
const value1 = data1.breakpoint;
const value2 = data2.breakpoint;
let result;
if (value1 == null && value2 != null)
result = -1;
else if (value1 != null && value2 == null)
result = 1;
else if (value1 == null && value2 == null)
result = 0;
else if (typeof value1 === 'string' && typeof value2 === 'string')
result = value1.localeCompare(value2, undefined, { numeric: true });
else
result = value1 < value2 ? -1 : value1 > value2 ? 1 : 0;
return -1 * result;
});
for (let i = 0; i < this.sortedResponsiveOptions.length; i++) {
let res = this.sortedResponsiveOptions[i];
innerHTML += `
@media screen and (max-width: ${res.breakpoint}) {
#${this.containerId()} .p-galleria-thumbnail-item {
flex: 1 0 ${100 / res.numVisible}%
}
}
`;
}
}
this.thumbnailsStyle.innerHTML = innerHTML;
setAttribute(this.thumbnailsStyle, 'nonce', this.galleria.config?.csp()?.nonce);
}
calculatePosition() {
if (isPlatformBrowser(this.platformId)) {
const itemsContainer = this.itemsContainer();
if (itemsContainer && this.sortedResponsiveOptions) {
let windowWidth = window.innerWidth;
let matchedResponsiveData = {
numVisible: this._numVisible()
};
for (let i = 0; i < this.sortedResponsiveOptions.length; i++) {
let res = this.sortedResponsiveOptions[i];
if (parseInt(res.breakpoint, 10) >= windowWidth) {
matchedResponsiveData = res;
}
}
if (this.d_numVisible() !== matchedResponsiveData.numVisible) {
this.d_numVisible.set(matchedResponsiveData.numVisible);
}
}
}
}
getTabIndex(index) {
return this.isItemActive(index) ? 0 : null;
}
navForward(e) {
this.stopTheSlideShow();
const activeIndex = this._activeIndex();
const val = this.value();
let nextItemIndex = activeIndex + 1;
if (nextItemIndex + this.totalShiftedItems > this.getMedianItemIndex() && (-1 * this.totalShiftedItems < this.getTotalPageNumber() - 1 || this.circular())) {
this.step(-1);
}
let newActiveIndex = this.circular() && val.length - 1 === activeIndex ? 0 : nextItemIndex;
this.onActiveIndexChange.emit(newActiveIndex);
if (e.cancelable) {
e.preventDefault();
}
}
navBackward(e) {
this.stopTheSlideShow();
const activeIndex = this._activeIndex();
const val = this.value();
let prevItemIndex = activeIndex !== 0 ? activeIndex - 1 : 0;
let diff = prevItemIndex + this.totalShiftedItems;
if (this.d_numVisible() - diff - 1 > this.getMedianItemIndex() && (-1 * this.totalShiftedItems !== 0 || this.circular())) {
this.step(1);
}
let newActiveIndex = this.circular() && activeIndex === 0 ? val.length - 1 : prevItemIndex;
this.onActiveIndexChange.emit(newActiveIndex);
if (e.cancelable) {
e.preventDefault();
}
}
onItemClick(index) {
this.stopTheSlideShow();
const activeIndex = this._activeIndex();
let selectedItemIndex = index;
if (selectedItemIndex !== activeIndex) {
const diff = selectedItemIndex + this.totalShiftedItems;
let dir = 0;
if (selectedItemIndex < activeIndex) {
dir = this.d_numVisible() - diff - 1 - this.getMedianItemIndex();
if (dir > 0 && -1 * this.totalShiftedItems !== 0) {
this.step(dir);
}
}
else {
dir = this.getMedianItemIndex() - diff;
if (dir < 0 && -1 * this.totalShiftedItems < this.getTotalPageNumber() - 1) {
this.step(dir);
}
}
this._activeIndex.set(selectedItemIndex);
this.onActiveIndexChange.emit(selectedItemIndex);
}
}
onThumbnailKeydown(event, index) {
if (event.code === 'Enter' || event.code === 'Space') {
this.onItemClick(index);
event.preventDefault();
}
switch (event.code) {
case 'ArrowRight':
this.onRightKey();
break;
case 'ArrowLeft':
this.onLeftKey();
break;
case 'Home':
this.onHomeKey();
event.preventDefault();
break;
case 'End':
this.onEndKey();
event.preventDefault();
break;
case 'ArrowUp':
case 'ArrowDown':
event.preventDefault();
break;
case 'Tab':
this.onTabKey();
break;
default:
break;
}
}
onRightKey() {
const itemsContainer = this.itemsContainer();
const indicators = find(itemsContainer?.nativeElement, '[data-pc-section="thumbnailitem"]');
const activeIndex = this.findFocusedIndicatorIndex();
this.changedFocusedIndicator(activeIndex, activeIndex + 1 === indicators.length ? indicators.length - 1 : activeIndex + 1);
}
onLeftKey() {
const activeIndex = this.findFocusedIndicatorIndex();
this.changedFocusedIndicator(activeIndex, activeIndex - 1 <= 0 ? 0 : activeIndex - 1);
}
onHomeKey() {
const activeIndex = this.findFocusedIndicatorIndex();
this.changedFocusedIndicator(activeIndex, 0);
}
onEndKey() {
const itemsContainer = this.itemsContainer();
const indicators = find(itemsContainer?.nativeElement, '[data-pc-section="thumbnailitem"]');
const activeIndex = this.findFocusedIndicatorIndex();
this.changedFocusedIndicator(activeIndex, indicators.length - 1);
}
onTabKey() {
const itemsContainer = this.itemsContainer();
const indicators = [...find(itemsContainer?.nativeElement, '[data-pc-section="thumbnailitem"]')];
const highlightedIndex = indicators.findIndex((ind) => getAttribute(ind, 'data-p-active') === true);
const activeIndicator = findSingle(itemsContainer?.nativeElement, '[tabindex="0"]');
const activeIndex = indicators.findIndex((ind) => ind === activeIndicator?.parentElement);
indicators[activeIndex].children[0].tabIndex = '-1';
indicators[highlightedIndex].children[0].tabIndex = '0';
}
findFocusedIndicatorIndex() {
const itemsContainer = this.itemsContainer();
const indicators = [...find(itemsContainer?.nativeElement, '[data-pc-section="thumbnailitem"]')];
const activeIndicator = findSingle(itemsContainer?.nativeElement, '[data-pc-section="thumbnailitem"] > [tabindex="0"]');
return indicators.findIndex((ind) => ind === activeIndicator?.parentElement);
}
changedFocusedIndicator(prevInd, nextInd) {
const itemsContainer = this.itemsContainer();
const indicators = find(itemsContainer?.nativeElement, '[data-pc-section="thumbnailitem"]');
indicators[prevInd].children[0].tabIndex = '-1';
indicators[nextInd].children[0].tabIndex = '0';
indicators[nextInd].children[0].focus();
}
step(dir) {
const d_numVisible = this.d_numVisible();
const val = this.value();
const activeIndex = this._activeIndex();
let totalShiftedItems = this.totalShiftedItems + dir;
if (dir < 0 && -1 * totalShiftedItems + d_numVisible > val.length - 1) {
totalShiftedItems = d_numVisible - val.length;
}
else if (dir > 0 && totalShiftedItems > 0) {
totalShiftedItems = 0;
}
if (this.circular()) {
if (dir < 0 && val.length - 1 === activeIndex) {
totalShiftedItems = 0;
}
else if (dir > 0 && activeIndex === 0) {
totalShiftedItems = d_numVisible - val.length;
}
}
const itemsContainer = this.itemsContainer();
if (itemsContainer) {
this.document.body.setAttribute('data-p-items-hidden', 'false');
!this.$unstyled() && removeClass(itemsContainer.nativeElement, 'p-items-hidden');
itemsContainer.nativeElement.style.transform = this.isVertical() ? `translate3d(0, ${totalShiftedItems * (100 / d_numVisible)}%, 0)` : `translate3d(${totalShiftedItems * (100 / d_numVisible)}%, 0, 0)`;
itemsContainer.nativeElement.style.transition = 'transform 500ms ease 0s';
}
this.totalShiftedItems = totalShiftedItems;
}
stopTheSlideShow() {
if (this.slideShowActive()) {
this.stopSlideShow.emit();
}
}
changePageOnTouch(e, diff) {
if (diff < 0) {
// left
this.navForward(e);
}
else {
// right
this.navBackward(e);
}
}
getTotalPageNumber() {
const val = this.value();
const d_numVisible = this.d_numVisible();
return val.length > d_numVisible ? val.length - d_numVisible + 1 : 0;
}
getMedianItemIndex() {
const d_numVisible = this.d_numVisible();
let index = Math.floor(d_numVisible / 2);
return d_numVisible % 2 ? index : index - 1;
}
onTransitionEnd() {
const itemsContainer = this.itemsContainer();
if (itemsContainer && itemsContainer.nativeElement) {
this.document.body.setAttribute('data-p-items-hidden', 'true');
!this.$unstyled() && addClass(itemsContainer.nativeElement, 'p-items-hidden');
itemsContainer.nativeElement.style.transition = '';
}
}
onTouchEnd(e) {
let touchobj = e.changedTouches[0];
if (this.isVertical()) {
this.changePageOnTouch(e, touchobj.pageY - this.startPos.y);
}
else {
this.changePageOnTouch(e, touchobj.pageX - this.startPos.x);
}
}
onTouchMove(e) {
if (e.cancelable) {
e.preventDefault();
}
}
onTouchStart(e) {
let touchobj = e.changedTouches[0];
this.startPos = {
x: touchobj.pageX,
y: touchobj.pageY
};
}
isNavBackwardDisabled() {
const val = this.value();
const d_numVisible = this.d_numVisible();
return (!this.circular() && this._activeIndex() === 0) || val.length <= d_numVisible;
}
isNavForwardDisabled() {
const val = this.value();
const d_numVisible = this.d_numVisible();
return (!this.circular() && this._activeIndex() === val.length - 1) || val.length <= d_numVisible;
}
firstItemAciveIndex() {
return this.totalShiftedItems * -1;
}
lastItemActiveIndex() {
return this.firstItemAciveIndex() + this.d_numVisible() - 1;
}
isItemActive(index) {
return this.firstItemAciveIndex() <= index && this.lastItemActiveIndex() >= index;
}
bindDocumentListeners() {
if (isPlatformBrowser(this.platformId)) {
const window = this.document.defaultView || 'window';
this.documentResizeListener = this.renderer.listen(window, 'resize', () => {
this.calculatePosition();
});
}
}
unbindDocumentListeners() {
if (this.documentResizeListener) {
this.documentResizeListener();
this.documentResizeListener = null;
}
}
onDestroy() {
if (this.responsiveOptions()) {
this.unbindDocumentListeners();
}
if (this.thumbnailsStyle) {
this.thumbnailsStyle.parentNode?.removeChild(this.thumbnailsStyle);
}
}
ariaPrevButtonLabel() {
return this.aria?.prevPageLabel;
}
ariaNextButtonLabel() {
return this.aria?.nextPageLabel;
}
ariaPageLabel(value) {
return this.aria?.pageLabel?.replace(/{page}/g, value);
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: GalleriaThumbnails, deps: null, target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.6", type: GalleriaThumbnails, isStandalone: true, selector: "div[pGalleriaThumbnails]", inputs: { containerId: { classPropertyName: "containerId", publicName: "containerId", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, isVertical: { classPropertyName: "isVertical", publicName: "isVertical", isSignal: true, isRequired: false, transformFunction: null }, slideShowActive: { classPropertyName: "slideShowActive", publicName: "slideShowActive", isSignal: true, isRequired: false, transformFunction: null }, circular: { classPropertyName: "circular", publicName: "circular", isSignal: true, isRequired: false, transformFunction: null }, responsiveOptions: { classPropertyName: "responsiveOptions", publicName: "responsiveOptions", isSignal: true, isRequired: false, transformFunction: null }, contentHeight: { cla