UNPKG

@taiga-ui/kit

Version:

Taiga UI Angular main components kit

307 lines (293 loc) 21.4 kB
import * as i0 from '@angular/core'; import { input, Directive, InjectionToken, inject, forwardRef, ChangeDetectionStrategy, Component, contentChildren, SkipSelf, viewChild, output, Injectable } from '@angular/core'; import { toSignal } from '@angular/core/rxjs-interop'; import { EMPTY_FUNCTION, TUI_TRUE_HANDLER, TUI_STRINGIFY } from '@taiga-ui/cdk/constants'; import { tuiProvide } from '@taiga-ui/cdk/utils/di'; import { injectContext, PolymorpheusComponent, PolymorpheusOutlet } from '@taiga-ui/polymorpheus'; import { Subject, map, distinctUntilChanged, startWith, mergeMap, tap } from 'rxjs'; import { tuiInjectElement } from '@taiga-ui/cdk/utils/dom'; import { TuiExpand } from '@taiga-ui/core/components/expand'; import { NgTemplateOutlet } from '@angular/common'; import { TuiButton } from '@taiga-ui/core/components/button'; import { TUI_COMMON_ICONS } from '@taiga-ui/core/tokens'; import { TUI_MORE_WORD } from '@taiga-ui/kit/tokens'; import { tuiIsPresent } from '@taiga-ui/cdk/utils/miscellaneous'; class TuiTreeChildren { constructor() { this.childrenHandler = input(TuiTreeChildren.defaultHandler); } static defaultHandler(item) { return Array.isArray(item) ? item : []; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TuiTreeChildren, deps: [], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.21", type: TuiTreeChildren, isStandalone: true, selector: "tui-tree[childrenHandler]", inputs: { childrenHandler: { classPropertyName: "childrenHandler", publicName: "childrenHandler", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TuiTreeChildren, decorators: [{ type: Directive, args: [{ selector: 'tui-tree[childrenHandler]' }] }] }); const TUI_DEFAULT_TREE_CONTROLLER = { isExpanded: TUI_TRUE_HANDLER, toggle: EMPTY_FUNCTION, }; /** * Controller for tracking value - TuiTreeItemComponent pairs */ const TUI_TREE_ACCESSOR = new InjectionToken(ngDevMode ? 'TUI_TREE_ACCESSOR' : ''); /** * Controller for expanding the tree */ const TUI_TREE_CONTROLLER = new InjectionToken(ngDevMode ? 'TUI_TREE_CONTROLLER' : '', { factory: () => TUI_DEFAULT_TREE_CONTROLLER }); /** * A node of a tree view */ const TUI_TREE_NODE = new InjectionToken(ngDevMode ? 'TUI_TREE_NODE' : ''); /** * A tree node placeholder for loading */ const TUI_TREE_LOADING = new InjectionToken(ngDevMode ? 'TUI_TREE_LOADING' : '', { factory: () => ({}), }); /** * A tree node starting point */ const TUI_TREE_START = new InjectionToken(ngDevMode ? 'TUI_TREE_START' : ''); /** * A service to load tree progressively */ const TUI_TREE_LOADER = new InjectionToken(ngDevMode ? 'TUI_TREE_LOADER' : ''); /** * Nesting level of current TreeView node */ const TUI_TREE_LEVEL = new InjectionToken(ngDevMode ? 'TUI_TREE_LEVEL' : '', { factory: () => -1, }); class TuiTreeItemContent { constructor() { this.controller = inject(forwardRef(() => TUI_TREE_CONTROLLER)); this.icons = inject(TUI_COMMON_ICONS); this.more = inject(TUI_MORE_WORD); this.context = injectContext(); } get isExpandable() { return (this.context.$implicit.isExpandable && this.controller !== TUI_DEFAULT_TREE_CONTROLLER); } onClick() { this.controller.toggle(this.context.$implicit); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TuiTreeItemContent, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: TuiTreeItemContent, isStandalone: true, selector: "ng-component", host: { properties: { "class._expandable": "isExpandable" } }, ngImport: i0, template: "@if (isExpandable) {\n <button\n appearance=\"flat\"\n size=\"xs\"\n tuiIconButton\n type=\"button\"\n class=\"t-button\"\n [class.t-button_expanded]=\"context.$implicit.expanded()\"\n [iconStart]=\"icons.more\"\n [style.border-radius.%]=\"100\"\n (click)=\"onClick()\"\n >\n {{ more() }}\n </button>\n}\n<ng-container [ngTemplateOutlet]=\"context.template\" />\n", styles: [":host{display:flex;align-items:center}:host :host-context(tui-tree-item._expandable):not(._expandable){padding-inline-start:2rem}.t-button{transition-property:transform;transition-duration:var(--tui-duration, .3s);transition-timing-function:ease-in-out;margin-inline-end:.5rem}.t-button_expanded{transform:rotate(90deg)}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { 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: TuiTreeItemContent, decorators: [{ type: Component, args: [{ imports: [NgTemplateOutlet, TuiButton], changeDetection: ChangeDetectionStrategy.OnPush, host: { '[class._expandable]': 'isExpandable' }, template: "@if (isExpandable) {\n <button\n appearance=\"flat\"\n size=\"xs\"\n tuiIconButton\n type=\"button\"\n class=\"t-button\"\n [class.t-button_expanded]=\"context.$implicit.expanded()\"\n [iconStart]=\"icons.more\"\n [style.border-radius.%]=\"100\"\n (click)=\"onClick()\"\n >\n {{ more() }}\n </button>\n}\n<ng-container [ngTemplateOutlet]=\"context.template\" />\n", styles: [":host{display:flex;align-items:center}:host :host-context(tui-tree-item._expandable):not(._expandable){padding-inline-start:2rem}.t-button{transition-property:transform;transition-duration:var(--tui-duration, .3s);transition-timing-function:ease-in-out;margin-inline-end:.5rem}.t-button_expanded{transform:rotate(90deg)}\n"] }] }] }); const TUI_TREE_ITEM_CONTENT = new PolymorpheusComponent(TuiTreeItemContent); /** * Content for a tree item */ const TUI_TREE_CONTENT = new InjectionToken(ngDevMode ? 'TUI_TREE_CONTENT' : '', { factory: () => TUI_TREE_ITEM_CONTENT }); class TuiTreeItem { constructor() { this.nested = contentChildren(TUI_TREE_NODE); this.el = tuiInjectElement(); this.change$ = new Subject(); this.controller = inject(forwardRef(() => TUI_TREE_CONTROLLER)); this.level = inject(forwardRef(() => TUI_TREE_LEVEL)); this.content = inject(forwardRef(() => TUI_TREE_CONTENT)); this.attached = toSignal(this.change$.pipe(map(() => this.el.isConnected), distinctUntilChanged()), { initialValue: this.el.isConnected }); this.expanded = toSignal(this.change$.pipe(startWith(null), map(() => this.isExpanded), distinctUntilChanged()), { initialValue: this.isExpanded }); } get isExpandable() { return !!this.nested().length; } get isExpanded() { return this.controller.isExpanded(this); } ngDoCheck() { this.checkChanges(); } checkChanges() { this.change$.next(); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TuiTreeItem, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: TuiTreeItem, isStandalone: true, selector: "tui-tree-item", host: { attributes: { "role": "treeitem" }, properties: { "class._expandable": "isExpandable" } }, providers: [ tuiProvide(TUI_TREE_NODE, TuiTreeItem), { provide: TUI_TREE_LEVEL, deps: [[new SkipSelf(), TUI_TREE_LEVEL]], useFactory: (level) => ++level, }, ], queries: [{ propertyName: "nested", predicate: TUI_TREE_NODE, isSignal: true }], ngImport: i0, template: "<ng-template #template>\n <ng-content />\n</ng-template>\n<ng-container *polymorpheusOutlet=\"content as text; context: {$implicit: this, template: template}\">\n {{ text }}\n</ng-container>\n@if (isExpandable) {\n <tui-expand\n role=\"group\"\n class=\"t-children\"\n [expanded]=\"expanded()\"\n >\n <div>\n <ng-content select=\"tui-tree-item\" />\n <ng-content select=\"tui-tree\" />\n </div>\n </tui-expand>\n}\n@if (attached()) {}\n", styles: [":host{display:block}.t-children{position:relative;margin-inline-start:var(--tui-tree-item-indent, 1.5rem)}\n"], dependencies: [{ kind: "directive", type: PolymorpheusOutlet, selector: "[polymorpheusOutlet]", inputs: ["polymorpheusOutlet", "polymorpheusOutletContext"] }, { kind: "component", type: TuiExpand, selector: "tui-expand", inputs: ["expanded"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TuiTreeItem, decorators: [{ type: Component, args: [{ selector: 'tui-tree-item', imports: [PolymorpheusOutlet, TuiExpand], changeDetection: ChangeDetectionStrategy.OnPush, providers: [ tuiProvide(TUI_TREE_NODE, TuiTreeItem), { provide: TUI_TREE_LEVEL, deps: [[new SkipSelf(), TUI_TREE_LEVEL]], useFactory: (level) => ++level, }, ], host: { role: 'treeitem', '[class._expandable]': 'isExpandable', }, template: "<ng-template #template>\n <ng-content />\n</ng-template>\n<ng-container *polymorpheusOutlet=\"content as text; context: {$implicit: this, template: template}\">\n {{ text }}\n</ng-container>\n@if (isExpandable) {\n <tui-expand\n role=\"group\"\n class=\"t-children\"\n [expanded]=\"expanded()\"\n >\n <div>\n <ng-content select=\"tui-tree-item\" />\n <ng-content select=\"tui-tree\" />\n </div>\n </tui-expand>\n}\n@if (attached()) {}\n", styles: [":host{display:block}.t-children{position:relative;margin-inline-start:var(--tui-tree-item-indent, 1.5rem)}\n"] }] }] }); class TuiTreeNode { constructor() { this.component = inject(TuiTreeItem); this.directive = inject(TUI_TREE_ACCESSOR, { optional: true, }); this.value = input.required({ alias: 'tuiTreeNode' }); } ngOnChanges() { this.directive?.register(this.component, this.value()); } ngOnDestroy() { this.directive?.unregister(this.component); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TuiTreeNode, deps: [], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.21", type: TuiTreeNode, isStandalone: true, selector: "tui-tree-item[tuiTreeNode]", inputs: { value: { classPropertyName: "value", publicName: "tuiTreeNode", isSignal: true, isRequired: true, transformFunction: null } }, usesOnChanges: true, ngImport: i0 }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TuiTreeNode, decorators: [{ type: Directive, args: [{ selector: 'tui-tree-item[tuiTreeNode]' }] }] }); class TuiTreeComponent { constructor() { this.check$ = new Subject(); this.item = viewChild(TuiTreeItem); this.child = viewChild(TuiTreeComponent); this.children = toSignal(this.check$.pipe(map(() => this.handler(this.value())), distinctUntilChanged()), { initialValue: [] }); this.directive = inject(TuiTreeChildren, { optional: true, }); this.value = input.required(); this.trackBy = input((_, item) => item); this.content = input(TUI_STRINGIFY); } ngDoCheck() { this.checkChanges(); } checkChanges() { this.check$.next(); this.item()?.checkChanges(); this.child()?.checkChanges(); } get handler() { return this.directive?.childrenHandler() || TuiTreeChildren.defaultHandler; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TuiTreeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: TuiTreeComponent, isStandalone: true, selector: "tui-tree", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: true, transformFunction: null }, trackBy: { classPropertyName: "trackBy", publicName: "trackBy", isSignal: true, isRequired: false, transformFunction: null }, content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "tree" } }, providers: [tuiProvide(TUI_TREE_NODE, TuiTreeComponent)], viewQueries: [{ propertyName: "item", first: true, predicate: TuiTreeItem, descendants: true, isSignal: true }, { propertyName: "child", first: true, predicate: TuiTreeComponent, descendants: true, isSignal: true }], ngImport: i0, template: "<tui-tree-item\n #view\n [tuiTreeNode]=\"value()\"\n>\n @if (value() !== children()) {\n <ng-container *polymorpheusOutlet=\"content() as text; context: {$implicit: value(), node: view}\">\n {{ text }}\n </ng-container>\n }\n @for (child of children(); track trackBy()($index, child)) {\n <tui-tree\n [content]=\"content()\"\n [trackBy]=\"trackBy()\"\n [value]=\"child\"\n />\n }\n</tui-tree-item>\n", styles: [":host{position:relative;display:block}\n"], dependencies: [{ kind: "component", type: TuiTreeComponent, selector: "tui-tree", inputs: ["value", "trackBy", "content"] }, { kind: "directive", type: PolymorpheusOutlet, selector: "[polymorpheusOutlet]", inputs: ["polymorpheusOutlet", "polymorpheusOutletContext"] }, { kind: "component", type: TuiTreeItem, selector: "tui-tree-item" }, { kind: "directive", type: TuiTreeNode, selector: "tui-tree-item[tuiTreeNode]", inputs: ["tuiTreeNode"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TuiTreeComponent, decorators: [{ type: Component, args: [{ selector: 'tui-tree', imports: [PolymorpheusOutlet, TuiTreeItem, TuiTreeNode], changeDetection: ChangeDetectionStrategy.OnPush, providers: [tuiProvide(TUI_TREE_NODE, TuiTreeComponent)], host: { role: 'tree' }, template: "<tui-tree-item\n #view\n [tuiTreeNode]=\"value()\"\n>\n @if (value() !== children()) {\n <ng-container *polymorpheusOutlet=\"content() as text; context: {$implicit: value(), node: view}\">\n {{ text }}\n </ng-container>\n }\n @for (child of children(); track trackBy()($index, child)) {\n <tui-tree\n [content]=\"content()\"\n [trackBy]=\"trackBy()\"\n [value]=\"child\"\n />\n }\n</tui-tree-item>\n", styles: [":host{position:relative;display:block}\n"] }] }] }); class TuiTreeControllerDirective { constructor() { this.items = new Map(); this.fallback = input(true, { alias: 'tuiTreeController' }); this.map = input(new Map()); this.toggled = output(); } register(item, value) { this.items.set(item, value); } unregister(item) { this.items.delete(item); } isExpanded(item) { const value = this.items.get(item); return (value && this.map().get(value)) ?? this.fallback(); } toggle(item) { const value = this.items.get(item); const expanded = this.isExpanded(item); if (!tuiIsPresent(value)) { return; } this.toggled.emit(value); this.map().set(value, !expanded); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TuiTreeControllerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.21", type: TuiTreeControllerDirective, isStandalone: true, selector: "[tuiTreeController][map]", inputs: { fallback: { classPropertyName: "fallback", publicName: "tuiTreeController", isSignal: true, isRequired: false, transformFunction: null }, map: { classPropertyName: "map", publicName: "map", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { toggled: "toggled" }, providers: [ tuiProvide(TUI_TREE_ACCESSOR, TuiTreeControllerDirective), tuiProvide(TUI_TREE_CONTROLLER, TuiTreeControllerDirective), ], exportAs: ["tuiTreeController"], ngImport: i0 }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TuiTreeControllerDirective, decorators: [{ type: Directive, args: [{ selector: '[tuiTreeController][map]', providers: [ tuiProvide(TUI_TREE_ACCESSOR, TuiTreeControllerDirective), tuiProvide(TUI_TREE_CONTROLLER, TuiTreeControllerDirective), ], exportAs: 'tuiTreeController', }] }] }); class TuiTreeItemController { constructor() { this.map = new WeakMap(); this.fallback = input(true, { alias: 'tuiTreeController' }); } isExpanded(item) { return this.map.get(item) ?? this.fallback(); } toggle(item) { this.map.set(item, !this.isExpanded(item)); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TuiTreeItemController, deps: [], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.21", type: TuiTreeItemController, isStandalone: true, selector: "[tuiTreeController]:not([map])", inputs: { fallback: { classPropertyName: "fallback", publicName: "tuiTreeController", isSignal: true, isRequired: false, transformFunction: null } }, providers: [tuiProvide(TUI_TREE_CONTROLLER, TuiTreeItemController)], exportAs: ["tuiTreeController"], ngImport: i0 }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TuiTreeItemController, decorators: [{ type: Directive, args: [{ selector: '[tuiTreeController]:not([map])', providers: [tuiProvide(TUI_TREE_CONTROLLER, TuiTreeItemController)], exportAs: 'tuiTreeController', }] }] }); class TuiTreeService { constructor() { this.loading = inject(TUI_TREE_LOADING); this.start = inject(TUI_TREE_START); this.loader = inject(TUI_TREE_LOADER); this.map = new Map([[this.loading, []]]); this.load$ = new Subject(); this.data$ = this.load$.pipe(mergeMap((item) => this.loader.loadChildren(item).pipe(tap((children) => this.map.set(item, children)), map((children) => children.filter((item) => !this.loader.hasChildren(item))), tap((children) => children.forEach((child) => this.map.set(child, []))))), startWith(null), map(() => this.start)); } getChildren(item) { return this.map.get(item) || [this.loading]; } loadChildren(item) { if (this.map.get(item)) { return; } this.map.set(item, [this.loading]); this.load$.next(item); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TuiTreeService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TuiTreeService }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TuiTreeService, decorators: [{ type: Injectable }] }); const TuiTree = [ TuiTreeComponent, TuiTreeItem, TuiTreeItemContent, TuiTreeChildren, TuiTreeItemController, TuiTreeControllerDirective, TuiTreeNode, ]; /** * Generated bundle index. Do not edit. */ export { TUI_DEFAULT_TREE_CONTROLLER, TUI_TREE_ACCESSOR, TUI_TREE_CONTENT, TUI_TREE_CONTROLLER, TUI_TREE_ITEM_CONTENT, TUI_TREE_LEVEL, TUI_TREE_LOADER, TUI_TREE_LOADING, TUI_TREE_NODE, TUI_TREE_START, TuiTree, TuiTreeChildren, TuiTreeComponent, TuiTreeControllerDirective, TuiTreeItem, TuiTreeItemContent, TuiTreeItemController, TuiTreeNode, TuiTreeService }; //# sourceMappingURL=taiga-ui-kit-components-tree.mjs.map