@taiga-ui/kit
Version:
Taiga UI Angular main components kit
144 lines (139 loc) • 13.8 kB
JavaScript
import * as i0 from '@angular/core';
import { viewChildren, ElementRef, computed, inject, input, model, ChangeDetectionStrategy, Component } from '@angular/core';
import { tuiInjectElement } from '@taiga-ui/cdk/utils/dom';
import { tuiIsFocusedIn } from '@taiga-ui/cdk/utils/focus';
import { tuiClamp } from '@taiga-ui/cdk/utils/math';
import { TuiButton } from '@taiga-ui/core/components/button';
import { TUI_COMMON_ICONS } from '@taiga-ui/core/tokens';
import { TUI_PAGINATION_TEXTS } from '@taiga-ui/kit/tokens';
import { PolymorpheusOutlet } from '@taiga-ui/polymorpheus';
import { tuiCreateOptions } from '@taiga-ui/cdk/utils/di';
const [TUI_PAGINATION_OPTIONS, tuiPaginationOptionsProvider] = tuiCreateOptions({
size: 'l',
appearance: (isActive) => (isActive ? 'primary' : 'flat'),
});
const ELLIPSIS_ITEM_LENGTH = 1;
const ACTIVE_ITEM_LENGTH = 1;
class TuiPagination {
constructor() {
this.els = viewChildren('element', { read: ElementRef });
this.el = tuiInjectElement();
this.maxHalfLength = computed(() => this.sidePadding() + ELLIPSIS_ITEM_LENGTH + this.activePadding());
this.maxElementsLength = computed(() => this.maxHalfLength() * 2 + ACTIVE_ITEM_LENGTH);
this.lastElementIndex = computed(() => this.elementsLength() - 1);
this.itemsFit = computed(() => this.length() <= this.maxElementsLength());
this.lastIndex = computed(() => this.length() - 1);
this.reverseIndex = computed(() => this.lastIndex() - this.index());
this.texts = inject(TUI_PAGINATION_TEXTS);
this.icons = inject(TUI_COMMON_ICONS);
this.options = inject(TUI_PAGINATION_OPTIONS);
this.buttonSize = computed(() => (this.size() === 'm' ? 'xs' : 's'));
this.elementsLength = computed(() => this.itemsFit() ? this.length() : this.maxElementsLength());
this.length = input(1);
this.focusable = input(true);
this.size = input(this.options.size);
this.disabled = input(false);
this.activePadding = input(1);
this.sidePadding = input(1);
this.content = input();
this.index = model(0);
this.arrowIsDisabledRight = computed(() => this.reverseIndex() === 0);
this.arrowIsDisabledLeft = computed(() => this.index() === 0);
this.nativeFocusableElement = computed(() => {
if (this.disabled()) {
return null;
}
let activeElementIndex = 0;
for (let i = 0; i < this.elementsLength(); i++) {
const itemIndex = this.getItemIndexByElementIndex(i);
if (itemIndex) {
activeElementIndex++;
}
if (itemIndex === this.index()) {
break;
}
}
return (this.els().find((_, index) => index === activeElementIndex)?.nativeElement ??
null);
});
}
get focused() {
return tuiIsFocusedIn(this.el);
}
elementIsFocusable(index) {
return this.index() === index && !this.focused;
}
/**
* Get index by element index
* @param elementIndex
* @returns index or null (for '…')
*/
getItemIndexByElementIndex(elementIndex) {
const reverseElementIndex = this.lastElementIndex() - elementIndex;
if (elementIndex < this.sidePadding()) {
return elementIndex;
}
if (reverseElementIndex < this.sidePadding()) {
return this.lastIndex() - reverseElementIndex;
}
if ((elementIndex === this.sidePadding() &&
this.hasCollapsedItems(this.index())) ||
(reverseElementIndex === this.sidePadding() &&
this.hasCollapsedItems(this.reverseIndex()))) {
return null;
}
const computedIndex = this.index() - this.maxHalfLength() + elementIndex;
return tuiClamp(computedIndex, elementIndex, this.lastIndex() - reverseElementIndex);
}
getElementMode(index = -1) {
return this.options.appearance(this.index() === index);
}
onElementClick(index) {
this.updateIndex(index);
}
onElementKeyDownArrowLeft(element) {
if (element === this.els()[0]?.nativeElement) {
return;
}
const previous = this.els().find((_, index, array) => array[index + 1]?.nativeElement === element);
previous?.nativeElement.focus();
}
onElementKeyDownArrowRight(element) {
if (element === this.els()[this.els().length - 1]?.nativeElement) {
return;
}
const next = this.els().find((_, index, array) => array[index - 1]?.nativeElement === element);
next?.nativeElement.focus();
}
onArrowClick(step) {
this.tryChangeTo(step);
this.nativeFocusableElement()?.focus();
}
/**
* Are there collapsed items at that index
* @param index
* @returns there are collapsed items
*/
hasCollapsedItems(index) {
return !this.itemsFit() && index > this.maxHalfLength();
}
tryChangeTo(step) {
this.updateIndex(tuiClamp(this.index() + step, 0, this.lastIndex()));
}
updateIndex(index) {
if (this.index() !== index) {
this.index.set(index);
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TuiPagination, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: TuiPagination, isStandalone: true, selector: "tui-pagination", inputs: { length: { classPropertyName: "length", publicName: "length", isSignal: true, isRequired: false, transformFunction: null }, focusable: { classPropertyName: "focusable", publicName: "focusable", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, activePadding: { classPropertyName: "activePadding", publicName: "activePadding", isSignal: true, isRequired: false, transformFunction: null }, sidePadding: { classPropertyName: "sidePadding", publicName: "sidePadding", isSignal: true, isRequired: false, transformFunction: null }, content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: false, transformFunction: null }, index: { classPropertyName: "index", publicName: "index", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { index: "indexChange" }, viewQueries: [{ propertyName: "els", predicate: ["element"], descendants: true, read: ElementRef, isSignal: true }], ngImport: i0, template: "<div class=\"t-content\">\n <button\n tabIndex=\"-1\"\n tuiIconButton\n type=\"button\"\n class=\"t-button\"\n [appearance]=\"getElementMode()\"\n [disabled]=\"arrowIsDisabledLeft()\"\n [iconStart]=\"icons.decrement\"\n [size]=\"buttonSize()\"\n (click)=\"onArrowClick(-1)\"\n (mousedown.zoneless.prevent)=\"(0)\"\n >\n {{ texts()[0] }}\n </button>\n @for (_ of '-'.repeat(elementsLength()); track $index) {\n @let index = getItemIndexByElementIndex($index);\n @if (index !== null) {\n <button\n #element\n automation-id=\"tui-pagination__element\"\n tuiButton\n type=\"button\"\n class=\"t-button\"\n [appearance]=\"getElementMode(index)\"\n [disabled]=\"disabled()\"\n [size]=\"buttonSize()\"\n [tabIndex]=\"elementIsFocusable(index) ? 0 : -1\"\n (click)=\"onElementClick(index)\"\n (keydown.arrowLeft.prevent)=\"onElementKeyDownArrowLeft(element)\"\n (keydown.arrowRight.prevent)=\"onElementKeyDownArrowRight(element)\"\n >\n <ng-container *polymorpheusOutlet=\"content() || index + 1 as text; context: {$implicit: index}\">\n {{ text }}\n </ng-container>\n </button>\n } @else {\n <div\n automation-id=\"tui-pagination__element\"\n class=\"t-ellipsis\"\n [class.t-ellipsis_small]=\"size() === 'm'\"\n ></div>\n }\n }\n\n <button\n tabIndex=\"-1\"\n tuiIconButton\n type=\"button\"\n class=\"t-button\"\n [appearance]=\"getElementMode()\"\n [disabled]=\"arrowIsDisabledRight()\"\n [iconStart]=\"icons.increment\"\n [size]=\"buttonSize()\"\n (click)=\"onArrowClick(1)\"\n (mousedown.zoneless.prevent)=\"(0)\"\n >\n {{ texts()[1] }}\n </button>\n</div>\n", styles: [":host{display:block;font:var(--tui-typography-body-s);color:var(--tui-text-primary);text-align:center}.t-content{display:flex;justify-content:center}.t-button{margin:0 .125rem;flex-shrink:0}.t-button[tuiButton]:not(.t-button_small){min-inline-size:var(--tui-height-s);padding:0 .5rem}.t-button[tuiButton]:not(.t-button_small)[data-size=xs]{min-inline-size:var(--tui-height-xs);padding:0 .375rem}.t-button:first-child{transform:scaleX(var(--tui-inline));margin-inline-start:0}.t-button:last-child{transform:scaleX(var(--tui-inline));margin-inline-end:0}.t-ellipsis{inline-size:var(--tui-height-s);block-size:var(--tui-height-s);line-height:var(--tui-height-s);margin:0 .125rem;flex-shrink:0;color:var(--tui-text-action);text-align:center;cursor:default}.t-ellipsis_small{inline-size:var(--tui-height-xs);block-size:var(--tui-height-xs);line-height:var(--tui-height-xs)}.t-ellipsis:before{content:\"\\2026\"}\n"], dependencies: [{ kind: "directive", type: PolymorpheusOutlet, selector: "[polymorpheusOutlet]", inputs: ["polymorpheusOutlet", "polymorpheusOutletContext"] }, { kind: "directive", type: TuiButton, selector: "a[tuiButton],button[tuiButton],a[tuiIconButton],button[tuiIconButton]", inputs: ["size"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TuiPagination, decorators: [{
type: Component,
args: [{ selector: 'tui-pagination', imports: [PolymorpheusOutlet, TuiButton], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"t-content\">\n <button\n tabIndex=\"-1\"\n tuiIconButton\n type=\"button\"\n class=\"t-button\"\n [appearance]=\"getElementMode()\"\n [disabled]=\"arrowIsDisabledLeft()\"\n [iconStart]=\"icons.decrement\"\n [size]=\"buttonSize()\"\n (click)=\"onArrowClick(-1)\"\n (mousedown.zoneless.prevent)=\"(0)\"\n >\n {{ texts()[0] }}\n </button>\n @for (_ of '-'.repeat(elementsLength()); track $index) {\n @let index = getItemIndexByElementIndex($index);\n @if (index !== null) {\n <button\n #element\n automation-id=\"tui-pagination__element\"\n tuiButton\n type=\"button\"\n class=\"t-button\"\n [appearance]=\"getElementMode(index)\"\n [disabled]=\"disabled()\"\n [size]=\"buttonSize()\"\n [tabIndex]=\"elementIsFocusable(index) ? 0 : -1\"\n (click)=\"onElementClick(index)\"\n (keydown.arrowLeft.prevent)=\"onElementKeyDownArrowLeft(element)\"\n (keydown.arrowRight.prevent)=\"onElementKeyDownArrowRight(element)\"\n >\n <ng-container *polymorpheusOutlet=\"content() || index + 1 as text; context: {$implicit: index}\">\n {{ text }}\n </ng-container>\n </button>\n } @else {\n <div\n automation-id=\"tui-pagination__element\"\n class=\"t-ellipsis\"\n [class.t-ellipsis_small]=\"size() === 'm'\"\n ></div>\n }\n }\n\n <button\n tabIndex=\"-1\"\n tuiIconButton\n type=\"button\"\n class=\"t-button\"\n [appearance]=\"getElementMode()\"\n [disabled]=\"arrowIsDisabledRight()\"\n [iconStart]=\"icons.increment\"\n [size]=\"buttonSize()\"\n (click)=\"onArrowClick(1)\"\n (mousedown.zoneless.prevent)=\"(0)\"\n >\n {{ texts()[1] }}\n </button>\n</div>\n", styles: [":host{display:block;font:var(--tui-typography-body-s);color:var(--tui-text-primary);text-align:center}.t-content{display:flex;justify-content:center}.t-button{margin:0 .125rem;flex-shrink:0}.t-button[tuiButton]:not(.t-button_small){min-inline-size:var(--tui-height-s);padding:0 .5rem}.t-button[tuiButton]:not(.t-button_small)[data-size=xs]{min-inline-size:var(--tui-height-xs);padding:0 .375rem}.t-button:first-child{transform:scaleX(var(--tui-inline));margin-inline-start:0}.t-button:last-child{transform:scaleX(var(--tui-inline));margin-inline-end:0}.t-ellipsis{inline-size:var(--tui-height-s);block-size:var(--tui-height-s);line-height:var(--tui-height-s);margin:0 .125rem;flex-shrink:0;color:var(--tui-text-action);text-align:center;cursor:default}.t-ellipsis_small{inline-size:var(--tui-height-xs);block-size:var(--tui-height-xs);line-height:var(--tui-height-xs)}.t-ellipsis:before{content:\"\\2026\"}\n"] }]
}] });
/**
* Generated bundle index. Do not edit.
*/
export { TUI_PAGINATION_OPTIONS, TuiPagination, tuiPaginationOptionsProvider };
//# sourceMappingURL=taiga-ui-kit-components-pagination.mjs.map