UNPKG

@taiga-ui/kit

Version:

Taiga UI Angular main components kit

192 lines (184 loc) 11.8 kB
import { TuiItem } from '@taiga-ui/cdk/directives/item'; import { AsyncPipe, NgForOf, NgIf, NgTemplateOutlet } from '@angular/common'; import * as i0 from '@angular/core'; import { Directive, Input, inject, Injectable, TemplateRef, Component, ChangeDetectionStrategy, ContentChildren, ContentChild } from '@angular/core'; import { toSignal } from '@angular/core/rxjs-interop'; import { MutationObserverService, WA_MUTATION_OBSERVER_INIT } from '@ng-web-apis/mutation-observer'; import { ResizeObserverService } from '@ng-web-apis/resize-observer'; import { EMPTY_QUERY } from '@taiga-ui/cdk/constants'; import { Subject, Observable, merge, debounceTime, map, distinctUntilChanged, share } from 'rxjs'; import { tuiZonefreeScheduler, tuiZoneOptimized } from '@taiga-ui/cdk/observables'; import { tuiInjectElement } from '@taiga-ui/cdk/utils/dom'; import { tuiClamp } from '@taiga-ui/cdk/utils/math'; class TuiItemsWithMoreDirective { constructor() { this.itemsLimit = Infinity; this.required = -1; this.side = 'end'; // TODO: refactor to signal inputs after Angular update this.change$ = new Subject(); } ngOnChanges() { this.change$.next(); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TuiItemsWithMoreDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: TuiItemsWithMoreDirective, isStandalone: true, inputs: { itemsLimit: "itemsLimit", required: "required", side: "side" }, usesOnChanges: true, ngImport: i0 }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TuiItemsWithMoreDirective, decorators: [{ type: Directive, args: [{ standalone: true, }] }], propDecorators: { itemsLimit: [{ type: Input }], required: [{ type: Input }], side: [{ type: Input }] } }); class TuiItemsWithMoreService extends Observable { constructor() { super((subscriber) => this.stream$.subscribe(subscriber)); this.el = tuiInjectElement(); this.directive = inject(TuiItemsWithMoreDirective); this.stream$ = merge(this.directive.change$, inject(MutationObserverService, { self: true }), inject(ResizeObserverService, { self: true })).pipe(debounceTime(0, tuiZonefreeScheduler()), map(() => this.getOverflowIndex()), distinctUntilChanged(), tuiZoneOptimized(), share()); } getOverflowIndex() { const { side, itemsLimit } = this.directive; const { clientWidth, children } = this.el; const items = Array.from(children, ({ clientWidth }) => clientWidth); const index = side === 'start' ? 0 : items.length - 1; const more = children[index]?.tagName === 'SPAN' ? (items[index] ?? 0) : 0; const total = items.reduce((sum, width) => sum + width, 0) - more; if (total <= clientWidth && itemsLimit >= items.length) { return side === 'end' ? itemsLimit : 0; } return side === 'start' ? this.getIndexStart(items, total, more) : this.getIndexEnd(items, total, more); } getIndexStart(items, total, more) { const { required, itemsLimit } = this.directive; const { clientWidth } = this.el; const min = Number.isFinite(itemsLimit) ? items.length - itemsLimit - 1 : 0; const last = items.length - 1; const mandatory = required === -1 ? last : required; for (let i = 1; i < last; i++) { if (i === mandatory + 1) { continue; } total -= items[i] ?? 0; if (total + more <= clientWidth) { return tuiClamp(i, mandatory < min ? min + 1 : min, items.length); } } return items.length; } getIndexEnd(items, total, more) { const { required, itemsLimit } = this.directive; const { clientWidth } = this.el; const max = itemsLimit > required ? itemsLimit - 1 : itemsLimit - 2; const last = items.length - 1; const mandatory = required === -1 ? 0 : required; for (let i = last - 1; i > 0; i--) { if (i === mandatory) { continue; } total -= items[i] ?? 0; if (total + more <= clientWidth) { return tuiClamp(i - 1, -1, max); } } return -1; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TuiItemsWithMoreService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TuiItemsWithMoreService }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TuiItemsWithMoreService, decorators: [{ type: Injectable }], ctorParameters: function () { return []; } }); class TuiMore { static ngTemplateContextGuard(_dir, _ctx) { return true; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TuiMore, deps: [], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: TuiMore, isStandalone: true, selector: "[tuiMore]", ngImport: i0 }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TuiMore, decorators: [{ type: Directive, args: [{ standalone: true, selector: '[tuiMore]', }] }] }); class TuiItemsWithMoreComponent { constructor() { this.items = EMPTY_QUERY; this.directive = inject(TuiItemsWithMoreDirective); this.lastIndex = toSignal(inject(TuiItemsWithMoreService), { initialValue: 0, }); } get isMoreHidden() { const { side } = this.directive; return ((this.lastIndex() >= this.items.length - 1 && side === 'end') || (!this.lastIndex() && side === 'start')); } isHidden(index) { const { side, required } = this.directive; return ((index > this.lastIndex() && index !== required && side === 'end') || (index < this.lastIndex() && index !== required && side === 'start')); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TuiItemsWithMoreComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: TuiItemsWithMoreComponent, isStandalone: true, selector: "tui-items-with-more", providers: [ MutationObserverService, ResizeObserverService, TuiItemsWithMoreService, { provide: WA_MUTATION_OBSERVER_INIT, useValue: { childList: true, characterData: true, subtree: true, }, }, ], queries: [{ propertyName: "more", first: true, predicate: TuiMore, descendants: true, read: TemplateRef }, { propertyName: "items", predicate: TuiItem, descendants: true, read: TemplateRef }], hostDirectives: [{ directive: TuiItemsWithMoreDirective, inputs: ["itemsLimit", "itemsLimit", "required", "required", "side", "side"] }], ngImport: i0, template: "<ng-container *ngIf=\"items.changes | async\" />\n<ng-container\n *ngIf=\"directive.side === 'start'\"\n [ngTemplateOutlet]=\"template\"\n/>\n<div\n *ngFor=\"let item of items; let index = index\"\n class=\"t-item\"\n [class.t-item_hidden]=\"isHidden(index)\"\n>\n <ng-container *ngTemplateOutlet=\"item\" />\n</div>\n<ng-container\n *ngIf=\"directive.side === 'end'\"\n [ngTemplateOutlet]=\"template\"\n/>\n<ng-template #template>\n <span\n *ngIf=\"!isMoreHidden\"\n class=\"t-item\"\n >\n <ng-container\n [ngTemplateOutlet]=\"more || null\"\n [ngTemplateOutletContext]=\"{$implicit: lastIndex()}\"\n />\n </span>\n</ng-template>\n", styles: [":host{position:relative;display:flex;min-inline-size:0;flex:1;align-items:center;white-space:nowrap}.t-item{flex:0 0 auto}.t-item_hidden{position:absolute;visibility:hidden}\n"], dependencies: [{ kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "directive", type: NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TuiItemsWithMoreComponent, decorators: [{ type: Component, args: [{ standalone: true, selector: 'tui-items-with-more', imports: [AsyncPipe, NgForOf, NgIf, NgTemplateOutlet], changeDetection: ChangeDetectionStrategy.OnPush, providers: [ MutationObserverService, ResizeObserverService, TuiItemsWithMoreService, { provide: WA_MUTATION_OBSERVER_INIT, useValue: { childList: true, characterData: true, subtree: true, }, }, ], hostDirectives: [ { directive: TuiItemsWithMoreDirective, inputs: ['itemsLimit', 'required', 'side'], }, ], template: "<ng-container *ngIf=\"items.changes | async\" />\n<ng-container\n *ngIf=\"directive.side === 'start'\"\n [ngTemplateOutlet]=\"template\"\n/>\n<div\n *ngFor=\"let item of items; let index = index\"\n class=\"t-item\"\n [class.t-item_hidden]=\"isHidden(index)\"\n>\n <ng-container *ngTemplateOutlet=\"item\" />\n</div>\n<ng-container\n *ngIf=\"directive.side === 'end'\"\n [ngTemplateOutlet]=\"template\"\n/>\n<ng-template #template>\n <span\n *ngIf=\"!isMoreHidden\"\n class=\"t-item\"\n >\n <ng-container\n [ngTemplateOutlet]=\"more || null\"\n [ngTemplateOutletContext]=\"{$implicit: lastIndex()}\"\n />\n </span>\n</ng-template>\n", styles: [":host{position:relative;display:flex;min-inline-size:0;flex:1;align-items:center;white-space:nowrap}.t-item{flex:0 0 auto}.t-item_hidden{position:absolute;visibility:hidden}\n"] }] }], propDecorators: { items: [{ type: ContentChildren, args: [TuiItem, { read: TemplateRef, descendants: true }] }], more: [{ type: ContentChild, args: [TuiMore, { read: TemplateRef }] }] } }); const TuiItemsWithMore = [ TuiItemsWithMoreComponent, TuiItemsWithMoreDirective, TuiMore, TuiItem, ]; /** * Generated bundle index. Do not edit. */ export { TuiItemsWithMore, TuiItemsWithMoreComponent, TuiItemsWithMoreDirective, TuiItemsWithMoreService, TuiMore }; //# sourceMappingURL=taiga-ui-kit-components-items-with-more.mjs.map