You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
555 lines
25 KiB
555 lines
25 KiB
import { CdkTreeNode, CdkTree, CdkTreeNodeDef, CdkNestedTreeNode, CDK_TREE_NODE_OUTLET_NODE, CdkTreeNodePadding, CdkTreeNodeOutlet, CdkTreeNodeToggle, CdkTreeModule } from '@angular/cdk/tree';
|
|
import { Directive, ElementRef, Attribute, Input, IterableDiffers, ViewContainerRef, Inject, Optional, Component, ViewEncapsulation, ChangeDetectionStrategy, ViewChild, NgModule } from '@angular/core';
|
|
import { mixinTabIndex, mixinDisabled, MatCommonModule } from '@angular/material/core';
|
|
import { coerceBooleanProperty } from '@angular/cdk/coercion';
|
|
import { DataSource } from '@angular/cdk/collections';
|
|
import { BehaviorSubject, merge } from 'rxjs';
|
|
import { take, map } from 'rxjs/operators';
|
|
|
|
/**
|
|
* @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 * as ɵngcc0 from '@angular/core';
|
|
import * as ɵngcc1 from '@angular/cdk/tree';
|
|
const _MatTreeNodeBase = mixinTabIndex(mixinDisabled(CdkTreeNode));
|
|
/**
|
|
* Wrapper for the CdkTree node with Material design styles.
|
|
*/
|
|
class MatTreeNode extends _MatTreeNodeBase {
|
|
constructor(elementRef, tree, tabIndex) {
|
|
super(elementRef, tree);
|
|
this.tabIndex = Number(tabIndex) || 0;
|
|
// The classes are directly added here instead of in the host property because classes on
|
|
// the host property are not inherited with View Engine. It is not set as a @HostBinding because
|
|
// it is not set by the time it's children nodes try to read the class from it.
|
|
// TODO: move to host after View Engine deprecation
|
|
elementRef.nativeElement.classList.add('mat-tree-node');
|
|
}
|
|
// This is a workaround for https://github.com/angular/angular/issues/23091
|
|
// In aot mode, the lifecycle hooks from parent class are not called.
|
|
ngOnInit() {
|
|
super.ngOnInit();
|
|
}
|
|
ngDoCheck() {
|
|
super.ngDoCheck();
|
|
}
|
|
ngOnDestroy() {
|
|
super.ngOnDestroy();
|
|
}
|
|
}
|
|
MatTreeNode.ɵfac = function MatTreeNode_Factory(t) { return new (t || MatTreeNode)(ɵngcc0.ɵɵdirectiveInject(ɵngcc0.ElementRef), ɵngcc0.ɵɵdirectiveInject(ɵngcc1.CdkTree), ɵngcc0.ɵɵinjectAttribute('tabindex')); };
|
|
MatTreeNode.ɵdir = /*@__PURE__*/ ɵngcc0.ɵɵdefineDirective({ type: MatTreeNode, selectors: [["mat-tree-node"]], inputs: { role: "role", disabled: "disabled", tabIndex: "tabIndex" }, exportAs: ["matTreeNode"], features: [ɵngcc0.ɵɵProvidersFeature([{ provide: CdkTreeNode, useExisting: MatTreeNode }]), ɵngcc0.ɵɵInheritDefinitionFeature] });
|
|
MatTreeNode.ctorParameters = () => [
|
|
{ type: ElementRef },
|
|
{ type: CdkTree },
|
|
{ type: String, decorators: [{ type: Attribute, args: ['tabindex',] }] }
|
|
];
|
|
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && ɵngcc0.ɵsetClassMetadata(MatTreeNode, [{
|
|
type: Directive,
|
|
args: [{
|
|
selector: 'mat-tree-node',
|
|
exportAs: 'matTreeNode',
|
|
inputs: ['role', 'disabled', 'tabIndex'],
|
|
providers: [{ provide: CdkTreeNode, useExisting: MatTreeNode }]
|
|
}]
|
|
}], function () { return [{ type: ɵngcc0.ElementRef }, { type: ɵngcc1.CdkTree }, { type: String, decorators: [{
|
|
type: Attribute,
|
|
args: ['tabindex']
|
|
}] }]; }, null); })();
|
|
/**
|
|
* Wrapper for the CdkTree node definition with Material design styles.
|
|
* Captures the node's template and a when predicate that describes when this node should be used.
|
|
*/
|
|
class MatTreeNodeDef extends CdkTreeNodeDef {
|
|
}
|
|
MatTreeNodeDef.ɵfac = /*@__PURE__*/ function () { let ɵMatTreeNodeDef_BaseFactory; return function MatTreeNodeDef_Factory(t) { return (ɵMatTreeNodeDef_BaseFactory || (ɵMatTreeNodeDef_BaseFactory = ɵngcc0.ɵɵgetInheritedFactory(MatTreeNodeDef)))(t || MatTreeNodeDef); }; }();
|
|
MatTreeNodeDef.ɵdir = /*@__PURE__*/ ɵngcc0.ɵɵdefineDirective({ type: MatTreeNodeDef, selectors: [["", "matTreeNodeDef", ""]], inputs: { when: ["matTreeNodeDefWhen", "when"], data: ["matTreeNode", "data"] }, features: [ɵngcc0.ɵɵProvidersFeature([{ provide: CdkTreeNodeDef, useExisting: MatTreeNodeDef }]), ɵngcc0.ɵɵInheritDefinitionFeature] });
|
|
MatTreeNodeDef.propDecorators = {
|
|
data: [{ type: Input, args: ['matTreeNode',] }]
|
|
};
|
|
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && ɵngcc0.ɵsetClassMetadata(MatTreeNodeDef, [{
|
|
type: Directive,
|
|
args: [{
|
|
selector: '[matTreeNodeDef]',
|
|
inputs: [
|
|
'when: matTreeNodeDefWhen'
|
|
],
|
|
providers: [{ provide: CdkTreeNodeDef, useExisting: MatTreeNodeDef }]
|
|
}]
|
|
}], null, { data: [{
|
|
type: Input,
|
|
args: ['matTreeNode']
|
|
}] }); })();
|
|
/**
|
|
* Wrapper for the CdkTree nested node with Material design styles.
|
|
*/
|
|
class MatNestedTreeNode extends CdkNestedTreeNode {
|
|
constructor(elementRef, tree, differs, tabIndex) {
|
|
super(elementRef, tree, differs);
|
|
this._disabled = false;
|
|
this.tabIndex = Number(tabIndex) || 0;
|
|
// The classes are directly added here instead of in the host property because classes on
|
|
// the host property are not inherited with View Engine. It is not set as a @HostBinding because
|
|
// it is not set by the time it's children nodes try to read the class from it.
|
|
// TODO: move to host after View Engine deprecation
|
|
elementRef.nativeElement.classList.add('mat-nested-tree-node');
|
|
}
|
|
/** Whether the node is disabled. */
|
|
get disabled() { return this._disabled; }
|
|
set disabled(value) { this._disabled = coerceBooleanProperty(value); }
|
|
/** Tabindex for the node. */
|
|
get tabIndex() { return this.disabled ? -1 : this._tabIndex; }
|
|
set tabIndex(value) {
|
|
// If the specified tabIndex value is null or undefined, fall back to the default value.
|
|
this._tabIndex = value != null ? value : 0;
|
|
}
|
|
// This is a workaround for https://github.com/angular/angular/issues/19145
|
|
// In aot mode, the lifecycle hooks from parent class are not called.
|
|
// TODO(tinayuangao): Remove when the angular issue #19145 is fixed
|
|
ngOnInit() {
|
|
super.ngOnInit();
|
|
}
|
|
ngDoCheck() {
|
|
super.ngDoCheck();
|
|
}
|
|
ngAfterContentInit() {
|
|
super.ngAfterContentInit();
|
|
}
|
|
ngOnDestroy() {
|
|
super.ngOnDestroy();
|
|
}
|
|
}
|
|
MatNestedTreeNode.ɵfac = function MatNestedTreeNode_Factory(t) { return new (t || MatNestedTreeNode)(ɵngcc0.ɵɵdirectiveInject(ɵngcc0.ElementRef), ɵngcc0.ɵɵdirectiveInject(ɵngcc1.CdkTree), ɵngcc0.ɵɵdirectiveInject(ɵngcc0.IterableDiffers), ɵngcc0.ɵɵinjectAttribute('tabindex')); };
|
|
MatNestedTreeNode.ɵdir = /*@__PURE__*/ ɵngcc0.ɵɵdefineDirective({ type: MatNestedTreeNode, selectors: [["mat-nested-tree-node"]], inputs: { role: "role", disabled: "disabled", tabIndex: "tabIndex", node: ["matNestedTreeNode", "node"] }, exportAs: ["matNestedTreeNode"], features: [ɵngcc0.ɵɵProvidersFeature([
|
|
{ provide: CdkNestedTreeNode, useExisting: MatNestedTreeNode },
|
|
{ provide: CdkTreeNode, useExisting: MatNestedTreeNode },
|
|
{ provide: CDK_TREE_NODE_OUTLET_NODE, useExisting: MatNestedTreeNode }
|
|
]), ɵngcc0.ɵɵInheritDefinitionFeature] });
|
|
MatNestedTreeNode.ctorParameters = () => [
|
|
{ type: ElementRef },
|
|
{ type: CdkTree },
|
|
{ type: IterableDiffers },
|
|
{ type: String, decorators: [{ type: Attribute, args: ['tabindex',] }] }
|
|
];
|
|
MatNestedTreeNode.propDecorators = {
|
|
node: [{ type: Input, args: ['matNestedTreeNode',] }],
|
|
disabled: [{ type: Input }],
|
|
tabIndex: [{ type: Input }]
|
|
};
|
|
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && ɵngcc0.ɵsetClassMetadata(MatNestedTreeNode, [{
|
|
type: Directive,
|
|
args: [{
|
|
selector: 'mat-nested-tree-node',
|
|
exportAs: 'matNestedTreeNode',
|
|
inputs: ['role', 'disabled', 'tabIndex'],
|
|
providers: [
|
|
{ provide: CdkNestedTreeNode, useExisting: MatNestedTreeNode },
|
|
{ provide: CdkTreeNode, useExisting: MatNestedTreeNode },
|
|
{ provide: CDK_TREE_NODE_OUTLET_NODE, useExisting: MatNestedTreeNode }
|
|
]
|
|
}]
|
|
}], function () { return [{ type: ɵngcc0.ElementRef }, { type: ɵngcc1.CdkTree }, { type: ɵngcc0.IterableDiffers }, { type: String, decorators: [{
|
|
type: Attribute,
|
|
args: ['tabindex']
|
|
}] }]; }, { tabIndex: [{
|
|
type: Input
|
|
}], disabled: [{
|
|
type: Input
|
|
}], node: [{
|
|
type: Input,
|
|
args: ['matNestedTreeNode']
|
|
}] }); })();
|
|
|
|
/**
|
|
* @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
|
|
*/
|
|
/**
|
|
* Wrapper for the CdkTree padding with Material design styles.
|
|
*/
|
|
class MatTreeNodePadding extends CdkTreeNodePadding {
|
|
/** The level of depth of the tree node. The padding will be `level * indent` pixels. */
|
|
get level() { return this._level; }
|
|
set level(value) { this._setLevelInput(value); }
|
|
/** The indent for each level. Default number 40px from material design menu sub-menu spec. */
|
|
get indent() { return this._indent; }
|
|
set indent(indent) { this._setIndentInput(indent); }
|
|
}
|
|
MatTreeNodePadding.ɵfac = /*@__PURE__*/ function () { let ɵMatTreeNodePadding_BaseFactory; return function MatTreeNodePadding_Factory(t) { return (ɵMatTreeNodePadding_BaseFactory || (ɵMatTreeNodePadding_BaseFactory = ɵngcc0.ɵɵgetInheritedFactory(MatTreeNodePadding)))(t || MatTreeNodePadding); }; }();
|
|
MatTreeNodePadding.ɵdir = /*@__PURE__*/ ɵngcc0.ɵɵdefineDirective({ type: MatTreeNodePadding, selectors: [["", "matTreeNodePadding", ""]], inputs: { level: ["matTreeNodePadding", "level"], indent: ["matTreeNodePaddingIndent", "indent"] }, features: [ɵngcc0.ɵɵProvidersFeature([{ provide: CdkTreeNodePadding, useExisting: MatTreeNodePadding }]), ɵngcc0.ɵɵInheritDefinitionFeature] });
|
|
MatTreeNodePadding.propDecorators = {
|
|
level: [{ type: Input, args: ['matTreeNodePadding',] }],
|
|
indent: [{ type: Input, args: ['matTreeNodePaddingIndent',] }]
|
|
};
|
|
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && ɵngcc0.ɵsetClassMetadata(MatTreeNodePadding, [{
|
|
type: Directive,
|
|
args: [{
|
|
selector: '[matTreeNodePadding]',
|
|
providers: [{ provide: CdkTreeNodePadding, useExisting: MatTreeNodePadding }]
|
|
}]
|
|
}], null, { level: [{
|
|
type: Input,
|
|
args: ['matTreeNodePadding']
|
|
}], indent: [{
|
|
type: Input,
|
|
args: ['matTreeNodePaddingIndent']
|
|
}] }); })();
|
|
|
|
/**
|
|
* @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
|
|
*/
|
|
/**
|
|
* Outlet for nested CdkNode. Put `[matTreeNodeOutlet]` on a tag to place children dataNodes
|
|
* inside the outlet.
|
|
*/
|
|
class MatTreeNodeOutlet {
|
|
constructor(viewContainer, _node) {
|
|
this.viewContainer = viewContainer;
|
|
this._node = _node;
|
|
}
|
|
}
|
|
MatTreeNodeOutlet.ɵfac = function MatTreeNodeOutlet_Factory(t) { return new (t || MatTreeNodeOutlet)(ɵngcc0.ɵɵdirectiveInject(ɵngcc0.ViewContainerRef), ɵngcc0.ɵɵdirectiveInject(CDK_TREE_NODE_OUTLET_NODE, 8)); };
|
|
MatTreeNodeOutlet.ɵdir = /*@__PURE__*/ ɵngcc0.ɵɵdefineDirective({ type: MatTreeNodeOutlet, selectors: [["", "matTreeNodeOutlet", ""]], features: [ɵngcc0.ɵɵProvidersFeature([{
|
|
provide: CdkTreeNodeOutlet,
|
|
useExisting: MatTreeNodeOutlet
|
|
}])] });
|
|
MatTreeNodeOutlet.ctorParameters = () => [
|
|
{ type: ViewContainerRef },
|
|
{ type: undefined, decorators: [{ type: Inject, args: [CDK_TREE_NODE_OUTLET_NODE,] }, { type: Optional }] }
|
|
];
|
|
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && ɵngcc0.ɵsetClassMetadata(MatTreeNodeOutlet, [{
|
|
type: Directive,
|
|
args: [{
|
|
selector: '[matTreeNodeOutlet]',
|
|
providers: [{
|
|
provide: CdkTreeNodeOutlet,
|
|
useExisting: MatTreeNodeOutlet
|
|
}]
|
|
}]
|
|
}], function () { return [{ type: ɵngcc0.ViewContainerRef }, { type: undefined, decorators: [{
|
|
type: Inject,
|
|
args: [CDK_TREE_NODE_OUTLET_NODE]
|
|
}, {
|
|
type: Optional
|
|
}] }]; }, null); })();
|
|
|
|
/**
|
|
* @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
|
|
*/
|
|
/**
|
|
* Wrapper for the CdkTable with Material design styles.
|
|
*/
|
|
class MatTree extends CdkTree {
|
|
}
|
|
MatTree.ɵfac = /*@__PURE__*/ function () { let ɵMatTree_BaseFactory; return function MatTree_Factory(t) { return (ɵMatTree_BaseFactory || (ɵMatTree_BaseFactory = ɵngcc0.ɵɵgetInheritedFactory(MatTree)))(t || MatTree); }; }();
|
|
MatTree.ɵcmp = /*@__PURE__*/ ɵngcc0.ɵɵdefineComponent({ type: MatTree, selectors: [["mat-tree"]], viewQuery: function MatTree_Query(rf, ctx) { if (rf & 1) {
|
|
ɵngcc0.ɵɵviewQuery(MatTreeNodeOutlet, 7);
|
|
} if (rf & 2) {
|
|
let _t;
|
|
ɵngcc0.ɵɵqueryRefresh(_t = ɵngcc0.ɵɵloadQuery()) && (ctx._nodeOutlet = _t.first);
|
|
} }, hostAttrs: ["role", "tree", 1, "mat-tree", "cdk-tree"], exportAs: ["matTree"], features: [ɵngcc0.ɵɵProvidersFeature([{ provide: CdkTree, useExisting: MatTree }]), ɵngcc0.ɵɵInheritDefinitionFeature], decls: 1, vars: 0, consts: [["matTreeNodeOutlet", ""]], template: function MatTree_Template(rf, ctx) { if (rf & 1) {
|
|
ɵngcc0.ɵɵelementContainer(0, 0);
|
|
} }, directives: [MatTreeNodeOutlet], styles: [".mat-tree{display:block}.mat-tree-node{display:flex;align-items:center;flex:1;word-wrap:break-word}.mat-nested-tree-node{border-bottom-width:0}\n"], encapsulation: 2 });
|
|
MatTree.propDecorators = {
|
|
_nodeOutlet: [{ type: ViewChild, args: [MatTreeNodeOutlet, { static: true },] }]
|
|
};
|
|
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && ɵngcc0.ɵsetClassMetadata(MatTree, [{
|
|
type: Component,
|
|
args: [{
|
|
selector: 'mat-tree',
|
|
exportAs: 'matTree',
|
|
template: `<ng-container matTreeNodeOutlet></ng-container>`,
|
|
host: {
|
|
// The 'cdk-tree' class needs to be included here because classes set in the host in the
|
|
// parent class are not inherited with View Engine. The 'cdk-tree' class in CdkTreeNode has
|
|
// to be set in the host because:
|
|
// if it is set as a @HostBinding it is not set by the time the tree nodes try to read the
|
|
// class from it.
|
|
// the ElementRef is not available in the constructor so the class can't be applied directly
|
|
// without a breaking constructor change.
|
|
'class': 'mat-tree cdk-tree',
|
|
'role': 'tree'
|
|
},
|
|
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 }],
|
|
styles: [".mat-tree{display:block}.mat-tree-node{display:flex;align-items:center;flex:1;word-wrap:break-word}.mat-nested-tree-node{border-bottom-width:0}\n"]
|
|
}]
|
|
}], null, { _nodeOutlet: [{
|
|
type: ViewChild,
|
|
args: [MatTreeNodeOutlet, { static: true }]
|
|
}] }); })();
|
|
|
|
/**
|
|
* @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
|
|
*/
|
|
/**
|
|
* Wrapper for the CdkTree's toggle with Material design styles.
|
|
*/
|
|
// tslint:disable-next-line: coercion-types
|
|
class MatTreeNodeToggle extends CdkTreeNodeToggle {
|
|
get recursive() { return this._recursive; }
|
|
set recursive(value) {
|
|
// TODO: when we remove support for ViewEngine, change this setter to an input
|
|
// alias in the decorator metadata.
|
|
this._recursive = coerceBooleanProperty(value);
|
|
}
|
|
}
|
|
MatTreeNodeToggle.ɵfac = /*@__PURE__*/ function () { let ɵMatTreeNodeToggle_BaseFactory; return function MatTreeNodeToggle_Factory(t) { return (ɵMatTreeNodeToggle_BaseFactory || (ɵMatTreeNodeToggle_BaseFactory = ɵngcc0.ɵɵgetInheritedFactory(MatTreeNodeToggle)))(t || MatTreeNodeToggle); }; }();
|
|
MatTreeNodeToggle.ɵdir = /*@__PURE__*/ ɵngcc0.ɵɵdefineDirective({ type: MatTreeNodeToggle, selectors: [["", "matTreeNodeToggle", ""]], inputs: { recursive: ["matTreeNodeToggleRecursive", "recursive"] }, features: [ɵngcc0.ɵɵProvidersFeature([{ provide: CdkTreeNodeToggle, useExisting: MatTreeNodeToggle }]), ɵngcc0.ɵɵInheritDefinitionFeature] });
|
|
MatTreeNodeToggle.propDecorators = {
|
|
recursive: [{ type: Input, args: ['matTreeNodeToggleRecursive',] }]
|
|
};
|
|
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && ɵngcc0.ɵsetClassMetadata(MatTreeNodeToggle, [{
|
|
type: Directive,
|
|
args: [{
|
|
selector: '[matTreeNodeToggle]',
|
|
providers: [{ provide: CdkTreeNodeToggle, useExisting: MatTreeNodeToggle }]
|
|
}]
|
|
}], null, { recursive: [{
|
|
type: Input,
|
|
args: ['matTreeNodeToggleRecursive']
|
|
}] }); })();
|
|
|
|
/**
|
|
* @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
|
|
*/
|
|
const MAT_TREE_DIRECTIVES = [
|
|
MatNestedTreeNode,
|
|
MatTreeNodeDef,
|
|
MatTreeNodePadding,
|
|
MatTreeNodeToggle,
|
|
MatTree,
|
|
MatTreeNode,
|
|
MatTreeNodeOutlet
|
|
];
|
|
class MatTreeModule {
|
|
}
|
|
MatTreeModule.ɵfac = function MatTreeModule_Factory(t) { return new (t || MatTreeModule)(); };
|
|
MatTreeModule.ɵmod = /*@__PURE__*/ ɵngcc0.ɵɵdefineNgModule({ type: MatTreeModule });
|
|
MatTreeModule.ɵinj = /*@__PURE__*/ ɵngcc0.ɵɵdefineInjector({ imports: [[CdkTreeModule, MatCommonModule], MatCommonModule] });
|
|
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && ɵngcc0.ɵsetClassMetadata(MatTreeModule, [{
|
|
type: NgModule,
|
|
args: [{
|
|
imports: [CdkTreeModule, MatCommonModule],
|
|
exports: [MatCommonModule, MAT_TREE_DIRECTIVES],
|
|
declarations: MAT_TREE_DIRECTIVES
|
|
}]
|
|
}], null, null); })();
|
|
(function () { (typeof ngJitMode === "undefined" || ngJitMode) && ɵngcc0.ɵɵsetNgModuleScope(MatTreeModule, { declarations: function () { return [MatNestedTreeNode, MatTreeNodeDef, MatTreeNodePadding, MatTreeNodeToggle, MatTree, MatTreeNode, MatTreeNodeOutlet]; }, imports: function () { return [CdkTreeModule, MatCommonModule]; }, exports: function () { return [MatCommonModule, MatNestedTreeNode, MatTreeNodeDef, MatTreeNodePadding, MatTreeNodeToggle, MatTree, MatTreeNode, MatTreeNodeOutlet]; } }); })();
|
|
|
|
/**
|
|
* @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
|
|
*/
|
|
/**
|
|
* 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.
|
|
*/
|
|
class MatTreeFlattener {
|
|
constructor(transformFunction, getLevel, isExpandable, getChildren) {
|
|
this.transformFunction = transformFunction;
|
|
this.getLevel = getLevel;
|
|
this.isExpandable = isExpandable;
|
|
this.getChildren = getChildren;
|
|
}
|
|
_flattenNode(node, level, resultNodes, parentMap) {
|
|
const flatNode = this.transformFunction(node, level);
|
|
resultNodes.push(flatNode);
|
|
if (this.isExpandable(flatNode)) {
|
|
const childrenNodes = this.getChildren(node);
|
|
if (childrenNodes) {
|
|
if (Array.isArray(childrenNodes)) {
|
|
this._flattenChildren(childrenNodes, level, resultNodes, parentMap);
|
|
}
|
|
else {
|
|
childrenNodes.pipe(take(1)).subscribe(children => {
|
|
this._flattenChildren(children, level, resultNodes, parentMap);
|
|
});
|
|
}
|
|
}
|
|
}
|
|
return resultNodes;
|
|
}
|
|
_flattenChildren(children, level, resultNodes, parentMap) {
|
|
children.forEach((child, index) => {
|
|
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[]`.
|
|
*/
|
|
flattenNodes(structuredData) {
|
|
let resultNodes = [];
|
|
structuredData.forEach(node => this._flattenNode(node, 0, resultNodes, []));
|
|
return resultNodes;
|
|
}
|
|
/**
|
|
* Expand flattened node with current expansion status.
|
|
* The returned list may have different length.
|
|
*/
|
|
expandFlattenedNodes(nodes, treeControl) {
|
|
let results = [];
|
|
let currentExpand = [];
|
|
currentExpand[0] = true;
|
|
nodes.forEach(node => {
|
|
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.
|
|
*/
|
|
class MatTreeFlatDataSource extends DataSource {
|
|
constructor(_treeControl, _treeFlattener, initialData) {
|
|
super();
|
|
this._treeControl = _treeControl;
|
|
this._treeFlattener = _treeFlattener;
|
|
this._flattenedData = new BehaviorSubject([]);
|
|
this._expandedData = new BehaviorSubject([]);
|
|
this._data = new BehaviorSubject([]);
|
|
if (initialData) {
|
|
// Assign the data through the constructor to ensure that all of the logic is executed.
|
|
this.data = initialData;
|
|
}
|
|
}
|
|
get data() { return this._data.value; }
|
|
set data(value) {
|
|
this._data.next(value);
|
|
this._flattenedData.next(this._treeFlattener.flattenNodes(this.data));
|
|
this._treeControl.dataNodes = this._flattenedData.value;
|
|
}
|
|
connect(collectionViewer) {
|
|
return merge(collectionViewer.viewChange, this._treeControl.expansionModel.changed, this._flattenedData).pipe(map(() => {
|
|
this._expandedData.next(this._treeFlattener.expandFlattenedNodes(this._flattenedData.value, this._treeControl));
|
|
return this._expandedData.value;
|
|
}));
|
|
}
|
|
disconnect() {
|
|
// no op
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @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
|
|
*/
|
|
/**
|
|
* 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.
|
|
*/
|
|
class MatTreeNestedDataSource extends DataSource {
|
|
constructor() {
|
|
super(...arguments);
|
|
this._data = new BehaviorSubject([]);
|
|
}
|
|
/**
|
|
* Data for the nested tree
|
|
*/
|
|
get data() { return this._data.value; }
|
|
set data(value) { this._data.next(value); }
|
|
connect(collectionViewer) {
|
|
return merge(...[collectionViewer.viewChange, this._data])
|
|
.pipe(map(() => this.data));
|
|
}
|
|
disconnect() {
|
|
// no op
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @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
|
|
*/
|
|
|
|
/**
|
|
* Generated bundle index. Do not edit.
|
|
*/
|
|
|
|
export { MatNestedTreeNode, MatTree, MatTreeFlatDataSource, MatTreeFlattener, MatTreeModule, MatTreeNestedDataSource, MatTreeNode, MatTreeNodeDef, MatTreeNodeOutlet, MatTreeNodePadding, MatTreeNodeToggle };
|
|
|
|
//# sourceMappingURL=tree.js.map
|