UNPKG

@taiga-ui/kit

Version:

Taiga UI Angular main components kit

144 lines (139 loc) 13.8 kB
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