| /** |
| * @license |
| * Copyright Google LLC All Rights Reserved. |
| * |
| * Use of this source code is governed by an MIT-style license that can be |
| * found in the LICENSE file at https://angular.io/license |
| */ |
| import { CDK_TREE_NODE_OUTLET_NODE, CdkNestedTreeNode, CdkTree, CdkTreeNode, CdkTreeNodeDef, CdkTreeNodePadding, CdkTreeNodeToggle, CdkTreeModule } from '@angular/cdk/tree'; |
| import { Directive, Inject, Optional, ViewContainerRef, Attribute, ContentChildren, ElementRef, Input, IterableDiffers, ChangeDetectionStrategy, Component, ViewChild, ViewEncapsulation, NgModule } from '@angular/core'; |
| import { mixinDisabled, mixinTabIndex, MatCommonModule } from '@angular/material/core'; |
| import { CommonModule } from '@angular/common'; |
| import { DataSource } from '@angular/cdk/collections'; |
| import { BehaviorSubject, merge } from 'rxjs'; |
| import { map, take } from 'rxjs/operators'; |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc |
| */ |
| /** |
| * Outlet for nested CdkNode. Put `[matTreeNodeOutlet]` on a tag to place children dataNodes |
| * inside the outlet. |
| */ |
| class MatTreeNodeOutlet { |
| /** |
| * @param {?} viewContainer |
| * @param {?=} _node |
| */ |
| constructor(viewContainer, _node) { |
| this.viewContainer = viewContainer; |
| this._node = _node; |
| } |
| } |
| MatTreeNodeOutlet.decorators = [ |
| { type: Directive, args: [{ |
| selector: '[matTreeNodeOutlet]' |
| },] }, |
| ]; |
| /** @nocollapse */ |
| MatTreeNodeOutlet.ctorParameters = () => [ |
| { type: ViewContainerRef }, |
| { type: undefined, decorators: [{ type: Inject, args: [CDK_TREE_NODE_OUTLET_NODE,] }, { type: Optional }] } |
| ]; |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc |
| */ |
| /** @type {?} */ |
| const _MatTreeNodeMixinBase = mixinTabIndex(mixinDisabled(CdkTreeNode)); |
| /** @type {?} */ |
| const _MatNestedTreeNodeMixinBase = mixinTabIndex(mixinDisabled(CdkNestedTreeNode)); |
| /** |
| * Wrapper for the CdkTree node with Material design styles. |
| * @template T |
| */ |
| class MatTreeNode extends _MatTreeNodeMixinBase { |
| /** |
| * @param {?} _elementRef |
| * @param {?} _tree |
| * @param {?} tabIndex |
| */ |
| constructor(_elementRef, _tree, tabIndex) { |
| super(_elementRef, _tree); |
| this._elementRef = _elementRef; |
| this._tree = _tree; |
| this.role = 'treeitem'; |
| this.tabIndex = Number(tabIndex) || 0; |
| } |
| } |
| MatTreeNode.decorators = [ |
| { type: Directive, args: [{ |
| selector: 'mat-tree-node', |
| exportAs: 'matTreeNode', |
| inputs: ['disabled', 'tabIndex'], |
| host: { |
| '[attr.aria-expanded]': 'isExpanded', |
| '[attr.aria-level]': 'role === "treeitem" ? level : null', |
| '[attr.role]': 'role', |
| 'class': 'mat-tree-node' |
| }, |
| providers: [{ provide: CdkTreeNode, useExisting: MatTreeNode }] |
| },] }, |
| ]; |
| /** @nocollapse */ |
| MatTreeNode.ctorParameters = () => [ |
| { type: ElementRef }, |
| { type: CdkTree }, |
| { type: String, decorators: [{ type: Attribute, args: ['tabindex',] }] } |
| ]; |
| MatTreeNode.propDecorators = { |
| role: [{ type: Input }] |
| }; |
| /** |
| * Wrapper for the CdkTree node definition with Material design styles. |
| * @template T |
| */ |
| class MatTreeNodeDef extends CdkTreeNodeDef { |
| } |
| MatTreeNodeDef.decorators = [ |
| { type: Directive, args: [{ |
| selector: '[matTreeNodeDef]', |
| inputs: [ |
| 'when: matTreeNodeDefWhen' |
| ], |
| providers: [{ provide: CdkTreeNodeDef, useExisting: MatTreeNodeDef }] |
| },] }, |
| ]; |
| MatTreeNodeDef.propDecorators = { |
| data: [{ type: Input, args: ['matTreeNode',] }] |
| }; |
| /** |
| * Wrapper for the CdkTree nested node with Material design styles. |
| * @template T |
| */ |
| class MatNestedTreeNode extends _MatNestedTreeNodeMixinBase { |
| /** |
| * @param {?} _elementRef |
| * @param {?} _tree |
| * @param {?} _differs |
| * @param {?} tabIndex |
| */ |
| constructor(_elementRef, _tree, _differs, tabIndex) { |
| super(_elementRef, _tree, _differs); |
| this._elementRef = _elementRef; |
| this._tree = _tree; |
| this._differs = _differs; |
| this.tabIndex = Number(tabIndex) || 0; |
| } |
| // This is a workaround for https://github.com/angular/angular/issues/23091 |
| // In aot mode, the lifecycle hooks from parent class are not called. |
| // TODO(tinayuangao): Remove when the angular issue #23091 is fixed |
| /** |
| * @return {?} |
| */ |
| ngAfterContentInit() { |
| super.ngAfterContentInit(); |
| } |
| /** |
| * @return {?} |
| */ |
| ngOnDestroy() { |
| super.ngOnDestroy(); |
| } |
| } |
| MatNestedTreeNode.decorators = [ |
| { type: Directive, args: [{ |
| selector: 'mat-nested-tree-node', |
| exportAs: 'matNestedTreeNode', |
| host: { |
| '[attr.aria-expanded]': 'isExpanded', |
| '[attr.role]': 'role', |
| 'class': 'mat-nested-tree-node', |
| }, |
| inputs: ['disabled', 'tabIndex'], |
| providers: [ |
| { provide: CdkNestedTreeNode, useExisting: MatNestedTreeNode }, |
| { provide: CdkTreeNode, useExisting: MatNestedTreeNode }, |
| { provide: CDK_TREE_NODE_OUTLET_NODE, useExisting: MatNestedTreeNode } |
| ] |
| },] }, |
| ]; |
| /** @nocollapse */ |
| MatNestedTreeNode.ctorParameters = () => [ |
| { type: ElementRef }, |
| { type: CdkTree }, |
| { type: IterableDiffers }, |
| { type: String, decorators: [{ type: Attribute, args: ['tabindex',] }] } |
| ]; |
| MatNestedTreeNode.propDecorators = { |
| node: [{ type: Input, args: ['matNestedTreeNode',] }], |
| nodeOutlet: [{ type: ContentChildren, args: [MatTreeNodeOutlet, { |
| // We need to use `descendants: true`, because Ivy will no longer match |
| // indirect descendants if it's left as false. |
| descendants: true |
| },] }] |
| }; |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc |
| */ |
| /** |
| * Wrapper for the CdkTree padding with Material design styles. |
| * @template T |
| */ |
| class MatTreeNodePadding extends CdkTreeNodePadding { |
| } |
| MatTreeNodePadding.decorators = [ |
| { type: Directive, args: [{ |
| selector: '[matTreeNodePadding]', |
| providers: [{ provide: CdkTreeNodePadding, useExisting: MatTreeNodePadding }] |
| },] }, |
| ]; |
| MatTreeNodePadding.propDecorators = { |
| level: [{ type: Input, args: ['matTreeNodePadding',] }], |
| indent: [{ type: Input, args: ['matTreeNodePaddingIndent',] }] |
| }; |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc |
| */ |
| /** |
| * Wrapper for the CdkTable with Material design styles. |
| * @template T |
| */ |
| class MatTree extends CdkTree { |
| } |
| MatTree.decorators = [ |
| { type: Component, args: [{selector: 'mat-tree', |
| exportAs: 'matTree', |
| template: `<ng-container matTreeNodeOutlet></ng-container>`, |
| host: { |
| 'class': 'mat-tree', |
| 'role': 'tree', |
| }, |
| styles: [".mat-tree{display:block}.mat-tree-node{display:flex;align-items:center;min-height:48px;flex:1;overflow:hidden;word-wrap:break-word}.mat-nested-tree-ndoe{border-bottom-width:0}"], |
| encapsulation: ViewEncapsulation.None, |
| // See note on CdkTree for explanation on why this uses the default change detection strategy. |
| // tslint:disable-next-line:validate-decorators |
| changeDetection: ChangeDetectionStrategy.Default, |
| providers: [{ provide: CdkTree, useExisting: MatTree }] |
| },] }, |
| ]; |
| MatTree.propDecorators = { |
| _nodeOutlet: [{ type: ViewChild, args: [MatTreeNodeOutlet, { static: true },] }] |
| }; |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc |
| */ |
| /** |
| * Wrapper for the CdkTree's toggle with Material design styles. |
| * @template T |
| */ |
| class MatTreeNodeToggle extends CdkTreeNodeToggle { |
| constructor() { |
| super(...arguments); |
| this.recursive = false; |
| } |
| } |
| MatTreeNodeToggle.decorators = [ |
| { type: Directive, args: [{ |
| selector: '[matTreeNodeToggle]', |
| providers: [{ provide: CdkTreeNodeToggle, useExisting: MatTreeNodeToggle }] |
| },] }, |
| ]; |
| MatTreeNodeToggle.propDecorators = { |
| recursive: [{ type: Input, args: ['matTreeNodeToggleRecursive',] }] |
| }; |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc |
| */ |
| /** @type {?} */ |
| const MAT_TREE_DIRECTIVES = [ |
| MatNestedTreeNode, |
| MatTreeNodeDef, |
| MatTreeNodePadding, |
| MatTreeNodeToggle, |
| MatTree, |
| MatTreeNode, |
| MatTreeNodeOutlet |
| ]; |
| class MatTreeModule { |
| } |
| MatTreeModule.decorators = [ |
| { type: NgModule, args: [{ |
| imports: [CdkTreeModule, CommonModule, MatCommonModule], |
| exports: MAT_TREE_DIRECTIVES, |
| declarations: MAT_TREE_DIRECTIVES, |
| },] }, |
| ]; |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc |
| */ |
| /** |
| * Tree flattener to convert a normal type of node to node with children & level information. |
| * Transform nested nodes of type `T` to flattened nodes of type `F`. |
| * |
| * For example, the input data of type `T` is nested, and contains its children data: |
| * SomeNode: { |
| * key: 'Fruits', |
| * children: [ |
| * NodeOne: { |
| * key: 'Apple', |
| * }, |
| * NodeTwo: { |
| * key: 'Pear', |
| * } |
| * ] |
| * } |
| * After flattener flatten the tree, the structure will become |
| * SomeNode: { |
| * key: 'Fruits', |
| * expandable: true, |
| * level: 1 |
| * }, |
| * NodeOne: { |
| * key: 'Apple', |
| * expandable: false, |
| * level: 2 |
| * }, |
| * NodeTwo: { |
| * key: 'Pear', |
| * expandable: false, |
| * level: 2 |
| * } |
| * and the output flattened type is `F` with additional information. |
| * @template T, F |
| */ |
| class MatTreeFlattener { |
| /** |
| * @param {?} transformFunction |
| * @param {?} getLevel |
| * @param {?} isExpandable |
| * @param {?} getChildren |
| */ |
| constructor(transformFunction, getLevel, isExpandable, getChildren) { |
| this.transformFunction = transformFunction; |
| this.getLevel = getLevel; |
| this.isExpandable = isExpandable; |
| this.getChildren = getChildren; |
| } |
| /** |
| * @param {?} node |
| * @param {?} level |
| * @param {?} resultNodes |
| * @param {?} parentMap |
| * @return {?} |
| */ |
| _flattenNode(node, level, resultNodes, parentMap) { |
| /** @type {?} */ |
| const flatNode = this.transformFunction(node, level); |
| resultNodes.push(flatNode); |
| if (this.isExpandable(flatNode)) { |
| /** @type {?} */ |
| const childrenNodes = this.getChildren(node); |
| if (childrenNodes) { |
| if (Array.isArray(childrenNodes)) { |
| this._flattenChildren(childrenNodes, level, resultNodes, parentMap); |
| } |
| else { |
| childrenNodes.pipe(take(1)).subscribe((/** |
| * @param {?} children |
| * @return {?} |
| */ |
| children => { |
| this._flattenChildren(children, level, resultNodes, parentMap); |
| })); |
| } |
| } |
| } |
| return resultNodes; |
| } |
| /** |
| * @param {?} children |
| * @param {?} level |
| * @param {?} resultNodes |
| * @param {?} parentMap |
| * @return {?} |
| */ |
| _flattenChildren(children, level, resultNodes, parentMap) { |
| children.forEach((/** |
| * @param {?} child |
| * @param {?} index |
| * @return {?} |
| */ |
| (child, index) => { |
| /** @type {?} */ |
| let childParentMap = parentMap.slice(); |
| childParentMap.push(index != children.length - 1); |
| this._flattenNode(child, level + 1, resultNodes, childParentMap); |
| })); |
| } |
| /** |
| * Flatten a list of node type T to flattened version of node F. |
| * Please note that type T may be nested, and the length of `structuredData` may be different |
| * from that of returned list `F[]`. |
| * @param {?} structuredData |
| * @return {?} |
| */ |
| flattenNodes(structuredData) { |
| /** @type {?} */ |
| let resultNodes = []; |
| structuredData.forEach((/** |
| * @param {?} node |
| * @return {?} |
| */ |
| node => this._flattenNode(node, 0, resultNodes, []))); |
| return resultNodes; |
| } |
| /** |
| * Expand flattened node with current expansion status. |
| * The returned list may have different length. |
| * @param {?} nodes |
| * @param {?} treeControl |
| * @return {?} |
| */ |
| expandFlattenedNodes(nodes, treeControl) { |
| /** @type {?} */ |
| let results = []; |
| /** @type {?} */ |
| let currentExpand = []; |
| currentExpand[0] = true; |
| nodes.forEach((/** |
| * @param {?} node |
| * @return {?} |
| */ |
| node => { |
| /** @type {?} */ |
| let expand = true; |
| for (let i = 0; i <= this.getLevel(node); i++) { |
| expand = expand && currentExpand[i]; |
| } |
| if (expand) { |
| results.push(node); |
| } |
| if (this.isExpandable(node)) { |
| currentExpand[this.getLevel(node) + 1] = treeControl.isExpanded(node); |
| } |
| })); |
| return results; |
| } |
| } |
| /** |
| * Data source for flat tree. |
| * The data source need to handle expansion/collapsion of the tree node and change the data feed |
| * to `MatTree`. |
| * The nested tree nodes of type `T` are flattened through `MatTreeFlattener`, and converted |
| * to type `F` for `MatTree` to consume. |
| * @template T, F |
| */ |
| class MatTreeFlatDataSource extends DataSource { |
| /** |
| * @param {?} _treeControl |
| * @param {?} _treeFlattener |
| * @param {?=} initialData |
| */ |
| constructor(_treeControl, _treeFlattener, initialData = []) { |
| super(); |
| this._treeControl = _treeControl; |
| this._treeFlattener = _treeFlattener; |
| this._flattenedData = new BehaviorSubject([]); |
| this._expandedData = new BehaviorSubject([]); |
| this._data = new BehaviorSubject(initialData); |
| } |
| /** |
| * @return {?} |
| */ |
| get data() { return this._data.value; } |
| /** |
| * @param {?} value |
| * @return {?} |
| */ |
| set data(value) { |
| this._data.next(value); |
| this._flattenedData.next(this._treeFlattener.flattenNodes(this.data)); |
| this._treeControl.dataNodes = this._flattenedData.value; |
| } |
| /** |
| * @param {?} collectionViewer |
| * @return {?} |
| */ |
| connect(collectionViewer) { |
| /** @type {?} */ |
| const changes = [ |
| collectionViewer.viewChange, |
| this._treeControl.expansionModel.onChange, |
| this._flattenedData |
| ]; |
| return merge(...changes).pipe(map((/** |
| * @return {?} |
| */ |
| () => { |
| this._expandedData.next(this._treeFlattener.expandFlattenedNodes(this._flattenedData.value, this._treeControl)); |
| return this._expandedData.value; |
| }))); |
| } |
| /** |
| * @return {?} |
| */ |
| disconnect() { |
| // no op |
| } |
| } |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc |
| */ |
| /** |
| * Data source for nested tree. |
| * |
| * The data source for nested tree doesn't have to consider node flattener, or the way to expand |
| * or collapse. The expansion/collapsion will be handled by TreeControl and each non-leaf node. |
| * @template T |
| */ |
| class MatTreeNestedDataSource extends DataSource { |
| constructor() { |
| super(...arguments); |
| this._data = new BehaviorSubject([]); |
| } |
| /** |
| * Data for the nested tree |
| * @return {?} |
| */ |
| get data() { return this._data.value; } |
| /** |
| * @param {?} value |
| * @return {?} |
| */ |
| set data(value) { this._data.next(value); } |
| /** |
| * @param {?} collectionViewer |
| * @return {?} |
| */ |
| connect(collectionViewer) { |
| return merge(...[collectionViewer.viewChange, this._data]) |
| .pipe(map((/** |
| * @return {?} |
| */ |
| () => { |
| return this.data; |
| }))); |
| } |
| /** |
| * @return {?} |
| */ |
| disconnect() { |
| // no op |
| } |
| } |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc |
| */ |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc |
| */ |
| |
| export { MatTreeNode, MatTreeNodeDef, MatNestedTreeNode, MatTreeNodePadding, MatTree, MatTreeModule, MatTreeNodeToggle, MatTreeNodeOutlet, MatTreeFlattener, MatTreeFlatDataSource, MatTreeNestedDataSource }; |
| //# sourceMappingURL=tree.js.map |