@progress/kendo-angular-treeview 5.4.3 → 6.0.0-dev.202112021059

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,7 +2,7 @@
2
2
  * Copyright © 2021 Progress Software Corporation. All rights reserved.
3
3
  * Licensed under commercial license. See LICENSE.md in the project root for more information
4
4
  *-------------------------------------------------------------------------------------------*/
5
- import { EventEmitter, OnDestroy } from '@angular/core';
5
+ import { EventEmitter, OnDestroy, OnChanges, SimpleChanges } from '@angular/core';
6
6
  import { TreeViewComponent } from '../treeview.component';
7
7
  import { SelectableSettings } from './selectable-settings';
8
8
  import { Subscription } from 'rxjs';
@@ -11,7 +11,7 @@ import { TreeItem } from '../treeitem.interface';
11
11
  * A directive which manages the in-memory selection state of the TreeView node
12
12
  * ([see example]({% slug selection_treeview %})).
13
13
  */
14
- export declare class SelectDirective implements OnDestroy {
14
+ export declare class SelectDirective implements OnDestroy, OnChanges {
15
15
  protected treeView: TreeViewComponent;
16
16
  /**
17
17
  * @hidden
@@ -39,8 +39,16 @@ export declare class SelectDirective implements OnDestroy {
39
39
  protected subscriptions: Subscription;
40
40
  private readonly options;
41
41
  private selectActions;
42
- private _selectedKeys;
42
+ /**
43
+ * Reflectes the internal `selectedKeys` state.
44
+ */
45
+ private state;
46
+ /**
47
+ * Holds the last emitted `selectedKeys` collection.
48
+ */
49
+ private lastChange;
43
50
  constructor(treeView: TreeViewComponent);
51
+ ngOnChanges(changes: SimpleChanges): void;
44
52
  ngOnDestroy(): void;
45
53
  protected itemKey(e: any): any;
46
54
  protected select(e: any): void;
@@ -7,6 +7,7 @@ import { Directive, EventEmitter, HostBinding, Input, Output } from '@angular/co
7
7
  import { TreeViewComponent } from '../treeview.component';
8
8
  import { isBoolean, isPresent, noop } from '../utils';
9
9
  import { Subscription } from 'rxjs';
10
+ import { isChanged } from '@progress/kendo-angular-common';
10
11
  /**
11
12
  * A directive which manages the in-memory selection state of the TreeView node
12
13
  * ([see example]({% slug selection_treeview %})).
@@ -23,9 +24,12 @@ let SelectDirective = class SelectDirective {
23
24
  'multiple': (e) => this.selectMultiple(e),
24
25
  'single': (e) => this.selectSingle(e)
25
26
  };
26
- this._selectedKeys = [];
27
+ /**
28
+ * Reflectes the internal `selectedKeys` state.
29
+ */
30
+ this.state = new Set();
27
31
  this.subscriptions.add(this.treeView.selectionChange.subscribe(this.select.bind(this)));
28
- this.treeView.isSelected = (dataItem, index) => (this.selectedKeys.indexOf(this.itemKey({ dataItem, index })) > -1);
32
+ this.treeView.isSelected = (dataItem, index) => (this.state.has(this.itemKey({ dataItem, index })));
29
33
  }
30
34
  /**
31
35
  * @hidden
@@ -33,16 +37,6 @@ let SelectDirective = class SelectDirective {
33
37
  set isSelected(value) {
34
38
  this.treeView.isSelected = value;
35
39
  }
36
- /**
37
- * Defines the collection that will store the selected keys
38
- * ([see example]({% slug selection_treeview %}#toc-selection-modes)).
39
- */
40
- get selectedKeys() {
41
- return this._selectedKeys;
42
- }
43
- set selectedKeys(keys) {
44
- this._selectedKeys = keys;
45
- }
46
40
  get getAriaMultiselectable() {
47
41
  return this.options.mode === 'multiple';
48
42
  }
@@ -57,6 +51,11 @@ let SelectDirective = class SelectDirective {
57
51
  const selectionSettings = isBoolean(this.selection) ? { enabled: this.selection } : this.selection;
58
52
  return Object.assign(defaultOptions, selectionSettings);
59
53
  }
54
+ ngOnChanges(changes) {
55
+ if (isChanged('selectedKeys', changes, false) && changes.selectedKeys.currentValue !== this.lastChange) {
56
+ this.state = new Set(changes.selectedKeys.currentValue);
57
+ }
58
+ }
60
59
  ngOnDestroy() {
61
60
  this.subscriptions.unsubscribe();
62
61
  }
@@ -81,29 +80,29 @@ let SelectDirective = class SelectDirective {
81
80
  }
82
81
  selectSingle(node) {
83
82
  const key = this.itemKey(node);
84
- if (this.selectedKeys[0] === key) {
85
- return;
83
+ if (!this.state.has(key)) {
84
+ this.state.clear();
85
+ this.state.add(key);
86
+ this.notify();
86
87
  }
87
- this.selectedKeys = [key];
88
- this.notify();
89
88
  }
90
89
  selectMultiple(node) {
91
90
  const key = this.itemKey(node);
92
- const idx = this.selectedKeys.indexOf(key);
93
- const isSelected = idx > -1;
91
+ const isSelected = this.state.has(key);
94
92
  if (!isPresent(key)) {
95
93
  return;
96
94
  }
97
95
  if (isSelected) {
98
- this.selectedKeys.splice(idx, 1);
96
+ this.state.delete(key);
99
97
  }
100
98
  else {
101
- this.selectedKeys.push(key);
99
+ this.state.add(key);
102
100
  }
103
101
  this.notify();
104
102
  }
105
103
  notify() {
106
- this.selectedKeysChange.emit(this.selectedKeys.slice());
104
+ this.lastChange = Array.from(this.state);
105
+ this.selectedKeysChange.emit(this.lastChange);
107
106
  }
108
107
  };
109
108
  tslib_1.__decorate([
@@ -121,9 +120,8 @@ tslib_1.__decorate([
121
120
  ], SelectDirective.prototype, "selection", void 0);
122
121
  tslib_1.__decorate([
123
122
  Input(),
124
- tslib_1.__metadata("design:type", Array),
125
- tslib_1.__metadata("design:paramtypes", [Array])
126
- ], SelectDirective.prototype, "selectedKeys", null);
123
+ tslib_1.__metadata("design:type", Array)
124
+ ], SelectDirective.prototype, "selectedKeys", void 0);
127
125
  tslib_1.__decorate([
128
126
  Output(),
129
127
  tslib_1.__metadata("design:type", EventEmitter)
@@ -125,9 +125,8 @@ export declare const fetchLoadedDescendants: (lookup: TreeItemLookup, filterExpr
125
125
  /**
126
126
  * @hidden
127
127
  *
128
- * Compares two arrays to determine whether all unique elements in one, are present in the other.
128
+ * Compares two Seets to determine whether all unique elements in one, are present in the other.
129
129
  * Important:
130
130
  * - it disregards the element order
131
- * - it disregards element repetitions - sameValues([1, 1, 2], [1, 2, 2]) will return true
132
131
  */
133
- export declare const sameValues: (a: any[], b: any[]) => boolean;
132
+ export declare const sameValues: (as: Set<any>, bs: Set<any>) => boolean;
@@ -282,16 +282,14 @@ export const fetchLoadedDescendants = (lookup, filterExpression) => {
282
282
  /**
283
283
  * @hidden
284
284
  *
285
- * Compares two arrays to determine whether all unique elements in one, are present in the other.
285
+ * Compares two Seets to determine whether all unique elements in one, are present in the other.
286
286
  * Important:
287
287
  * - it disregards the element order
288
- * - it disregards element repetitions - sameValues([1, 1, 2], [1, 2, 2]) will return true
289
288
  */
290
- export const sameValues = (a, b) => {
291
- if (a.length !== b.length) {
289
+ export const sameValues = (as, bs) => {
290
+ if (as.size !== bs.size) {
292
291
  return false;
293
292
  }
294
- const values = new Set(b);
295
- return a.every(v => values.has(v));
293
+ return Array.from(as).every(v => bs.has(v));
296
294
  };
297
295
  export { ɵ0, ɵ1, ɵ2, ɵ3, ɵ4, ɵ5, ɵ6, ɵ7, ɵ8, ɵ9 };
@@ -22,7 +22,7 @@ const packageMetadata = {
22
22
  name: '@progress/kendo-angular-treeview',
23
23
  productName: 'Kendo UI for Angular',
24
24
  productCodes: ['KENDOUIANGULAR', 'KENDOUICOMPLETE'],
25
- publishDate: 1638439762,
25
+ publishDate: 1638442548,
26
26
  version: '',
27
27
  licensingDocsUrl: 'https://www.telerik.com/kendo-angular-ui/my-license/?utm_medium=product&utm_source=kendoangular&utm_campaign=kendo-ui-angular-purchase-license-keys-warning'
28
28
  };
@@ -405,17 +405,15 @@ const fetchLoadedDescendants = (lookup, filterExpression) => {
405
405
  /**
406
406
  * @hidden
407
407
  *
408
- * Compares two arrays to determine whether all unique elements in one, are present in the other.
408
+ * Compares two Seets to determine whether all unique elements in one, are present in the other.
409
409
  * Important:
410
410
  * - it disregards the element order
411
- * - it disregards element repetitions - sameValues([1, 1, 2], [1, 2, 2]) will return true
412
411
  */
413
- const sameValues = (a, b) => {
414
- if (a.length !== b.length) {
412
+ const sameValues = (as, bs) => {
413
+ if (as.size !== bs.size) {
415
414
  return false;
416
415
  }
417
- const values = new Set(b);
418
- return a.every(v => values.has(v));
416
+ return Array.from(as).every(v => bs.has(v));
419
417
  };
420
418
 
421
419
  const safe = node => (node || {});
@@ -2299,7 +2297,10 @@ let CheckDirective = class CheckDirective {
2299
2297
  'multiple': (e) => this.checkMultiple(e),
2300
2298
  'single': (e) => this.checkSingle(e)
2301
2299
  };
2302
- this._checkedKeys = [];
2300
+ /**
2301
+ * Reflectes the internal `checkedKeys` state.
2302
+ */
2303
+ this.state = new Set();
2303
2304
  this.subscriptions.add(this.treeView.checkedChange
2304
2305
  .subscribe((e) => this.check(e)));
2305
2306
  let expandedItems = [];
@@ -2314,16 +2315,6 @@ let CheckDirective = class CheckDirective {
2314
2315
  set isChecked(value) {
2315
2316
  this.treeView.isChecked = value;
2316
2317
  }
2317
- /**
2318
- * Defines the collection that will store the checked keys
2319
- * ([see example]({% slug checkboxes_treeview %})).
2320
- */
2321
- get checkedKeys() {
2322
- return this._checkedKeys;
2323
- }
2324
- set checkedKeys(keys) {
2325
- this._checkedKeys = keys;
2326
- }
2327
2318
  get options() {
2328
2319
  const defaultOptions = {
2329
2320
  checkChildren: true,
@@ -2344,6 +2335,9 @@ let CheckDirective = class CheckDirective {
2344
2335
  this.treeView.checkboxes = this.options.enabled;
2345
2336
  this.toggleCheckOnClick();
2346
2337
  }
2338
+ if (isChanged('checkedKeys', changes, false) && changes.checkedKeys.currentValue !== this.lastChange) {
2339
+ this.state = new Set(changes.checkedKeys.currentValue);
2340
+ }
2347
2341
  }
2348
2342
  ngOnDestroy() {
2349
2343
  this.subscriptions.unsubscribe();
@@ -2353,11 +2347,11 @@ let CheckDirective = class CheckDirective {
2353
2347
  if (!this.checkKey) {
2354
2348
  return this.isIndexChecked(index);
2355
2349
  }
2356
- const keyIndex = this.checkedKeys.indexOf(this.itemKey({ dataItem, index }));
2357
- return keyIndex > -1 ? 'checked' : 'none';
2350
+ const hasKey = this.state.has(this.itemKey({ dataItem, index }));
2351
+ return hasKey ? 'checked' : 'none';
2358
2352
  }
2359
2353
  isIndexChecked(index) {
2360
- const checkedKeys = this.checkedKeys.filter(matchKey(index));
2354
+ const checkedKeys = Array.from(this.state).filter(matchKey(index));
2361
2355
  if (indexChecked(checkedKeys, index)) {
2362
2356
  return 'checked';
2363
2357
  }
@@ -2388,7 +2382,11 @@ let CheckDirective = class CheckDirective {
2388
2382
  }
2389
2383
  checkSingle(node) {
2390
2384
  const key = this.itemKey(node.item);
2391
- this.checkedKeys = this.checkedKeys[0] !== key ? [key] : [];
2385
+ const hasKey = this.state.has(key);
2386
+ this.state.clear();
2387
+ if (!hasKey) {
2388
+ this.state.add(key);
2389
+ }
2392
2390
  this.notify();
2393
2391
  }
2394
2392
  checkMultiple(node) {
@@ -2423,7 +2421,6 @@ let CheckDirective = class CheckDirective {
2423
2421
  if (!isPresent(currentKey)) {
2424
2422
  return;
2425
2423
  }
2426
- const checkedKeys = new Set(this.checkedKeys);
2427
2424
  const pendingCheck = [currentKey];
2428
2425
  if (this.options.checkChildren) {
2429
2426
  const descendants = fetchLoadedDescendants(node, ({ item }) => this.treeView.isVisible(item.dataItem, item.index) &&
@@ -2431,61 +2428,57 @@ let CheckDirective = class CheckDirective {
2431
2428
  .map(({ item }) => this.itemKey(item));
2432
2429
  pendingCheck.push(...descendants);
2433
2430
  }
2434
- const shouldCheck = !checkedKeys.has(currentKey);
2431
+ const shouldCheck = !this.state.has(currentKey);
2435
2432
  pendingCheck.forEach(key => {
2436
2433
  if (shouldCheck) {
2437
- checkedKeys.add(key);
2434
+ this.state.add(key);
2438
2435
  }
2439
2436
  else {
2440
- checkedKeys.delete(key);
2437
+ this.state.delete(key);
2441
2438
  }
2442
2439
  });
2443
- this.checkedKeys = Array.from(checkedKeys);
2444
2440
  }
2445
2441
  checkParents(parent) {
2446
2442
  if (!isPresent(parent)) {
2447
2443
  return;
2448
2444
  }
2449
- const checkedKeys = new Set(this.checkedKeys);
2450
2445
  let currentParent = parent;
2451
2446
  while (currentParent) {
2452
2447
  const parentKey = this.itemKey(currentParent.item);
2453
- const allChildrenSelected = currentParent.children.every(item => checkedKeys.has(this.itemKey(item)));
2448
+ const allChildrenSelected = currentParent.children.every(item => this.state.has(this.itemKey(item)));
2454
2449
  if (allChildrenSelected) {
2455
- checkedKeys.add(parentKey);
2450
+ this.state.add(parentKey);
2456
2451
  }
2457
2452
  else {
2458
- checkedKeys.delete(parentKey);
2453
+ this.state.delete(parentKey);
2459
2454
  }
2460
2455
  currentParent = currentParent.parent;
2461
2456
  }
2462
- this.checkedKeys = Array.from(checkedKeys);
2463
2457
  }
2464
2458
  notify() {
2465
- this.checkedKeysChange.emit(this.checkedKeys.slice());
2459
+ this.lastChange = Array.from(this.state);
2460
+ this.checkedKeysChange.emit(this.lastChange);
2466
2461
  }
2467
2462
  addCheckedItemsChildren(lookups) {
2468
2463
  if (!isPresent(lookups) || lookups.length === 0) {
2469
2464
  return;
2470
2465
  }
2471
- const initiallyCheckedItemsCount = this.checkedKeys.length;
2472
- const checkedKeys = new Set(this.checkedKeys);
2466
+ const initiallyCheckedItemsCount = this.state.size;
2473
2467
  lookups.forEach(lookup => {
2474
2468
  const itemKey = this.itemKey(lookup.item);
2475
- if (!checkedKeys.has(itemKey)) {
2469
+ if (!this.state.has(itemKey)) {
2476
2470
  return;
2477
2471
  }
2478
2472
  lookup.children.forEach(item => {
2479
2473
  // ensure both the parent item and each child node is enabled
2480
2474
  if (!this.treeView.isDisabled(lookup.item.dataItem, lookup.item.index) &&
2481
2475
  !this.treeView.isDisabled(item.dataItem, item.index)) {
2482
- checkedKeys.add(this.itemKey(item));
2476
+ this.state.add(this.itemKey(item));
2483
2477
  }
2484
2478
  });
2485
2479
  });
2486
- const hasNewlyCheckedItems = initiallyCheckedItemsCount !== checkedKeys.size;
2480
+ const hasNewlyCheckedItems = initiallyCheckedItemsCount !== this.state.size;
2487
2481
  if (hasNewlyCheckedItems) {
2488
- this.checkedKeys = Array.from(checkedKeys);
2489
2482
  this.zone.run(() => this.notify());
2490
2483
  }
2491
2484
  }
@@ -2501,9 +2494,8 @@ __decorate([
2501
2494
  ], CheckDirective.prototype, "checkKey", void 0);
2502
2495
  __decorate([
2503
2496
  Input(),
2504
- __metadata("design:type", Array),
2505
- __metadata("design:paramtypes", [Array])
2506
- ], CheckDirective.prototype, "checkedKeys", null);
2497
+ __metadata("design:type", Array)
2498
+ ], CheckDirective.prototype, "checkedKeys", void 0);
2507
2499
  __decorate([
2508
2500
  Input('kendoTreeViewCheckable'),
2509
2501
  __metadata("design:type", Object)
@@ -2598,8 +2590,11 @@ let ExpandDirective = class ExpandDirective {
2598
2590
  */
2599
2591
  this.expandedKeysChange = new EventEmitter();
2600
2592
  this.subscriptions = new Subscription();
2601
- this._expandedKeys = [];
2602
- this.originalExpandedKeys = [];
2593
+ /**
2594
+ * Reflectes the internal `expandedKeys` state.
2595
+ */
2596
+ this.state = new Set();
2597
+ this.originalExpandedKeys = new Set();
2603
2598
  this.isFiltered = false;
2604
2599
  /**
2605
2600
  * Fills array with the correct expand keys according to wrapper metadata.
@@ -2631,7 +2626,7 @@ let ExpandDirective = class ExpandDirective {
2631
2626
  if (this.component.filterStateChange) {
2632
2627
  this.subscriptions.add(this.component.filterStateChange.subscribe(this.handleAutoExpand.bind(this)));
2633
2628
  }
2634
- this.component.isExpanded = (dataItem, index) => this.expandedKeys.indexOf(this.itemKey({ dataItem, index })) > -1;
2629
+ this.component.isExpanded = (dataItem, index) => this.state.has(this.itemKey({ dataItem, index }));
2635
2630
  }
2636
2631
  /**
2637
2632
  * @hidden
@@ -2643,14 +2638,10 @@ let ExpandDirective = class ExpandDirective {
2643
2638
  const settings = isBoolean(this.expandOnFilter) ? { enabled: this.expandOnFilter } : Object.assign({}, this.expandOnFilter, { enabled: true });
2644
2639
  return Object.assign({}, DEFAULT_FILTER_EXPAND_SETTINGS, settings);
2645
2640
  }
2646
- /**
2647
- * Defines the collection that will store the expanded keys.
2648
- */
2649
- get expandedKeys() {
2650
- return this._expandedKeys;
2651
- }
2652
- set expandedKeys(keys) {
2653
- this._expandedKeys = keys;
2641
+ ngOnChanges(changes) {
2642
+ if (isChanged('expandedKeys', changes, false) && changes.expandedKeys.currentValue !== this.lastChange) {
2643
+ this.state = new Set(changes.expandedKeys.currentValue);
2644
+ }
2654
2645
  }
2655
2646
  ngOnDestroy() {
2656
2647
  this.subscriptions.unsubscribe();
@@ -2670,19 +2661,19 @@ let ExpandDirective = class ExpandDirective {
2670
2661
  return e.index;
2671
2662
  }
2672
2663
  toggleExpand({ index, dataItem, expand }) {
2673
- const item = this.itemKey({ index, dataItem });
2674
- const idx = this.expandedKeys.indexOf(item);
2664
+ const key = this.itemKey({ index, dataItem });
2665
+ const isExpanded = this.state.has(key);
2675
2666
  let notify = false;
2676
- if (idx > -1 && !expand) {
2677
- this.expandedKeys.splice(idx, 1);
2667
+ if (isExpanded && !expand) {
2668
+ this.state.delete(key);
2678
2669
  notify = true;
2679
2670
  }
2680
- else if (idx === -1 && expand) {
2681
- this.expandedKeys.push(item);
2671
+ else if (!isExpanded && expand) {
2672
+ this.state.add(key);
2682
2673
  notify = true;
2683
2674
  }
2684
2675
  if (notify) {
2685
- this.expandedKeysChange.emit(this.expandedKeys);
2676
+ this.notify();
2686
2677
  }
2687
2678
  }
2688
2679
  handleAutoExpand({ nodes, matchCount, term }) {
@@ -2691,7 +2682,7 @@ let ExpandDirective = class ExpandDirective {
2691
2682
  }
2692
2683
  const { maxAutoExpandResults, expandMatches: autoExpandMatches, expandedOnClear } = this.filterExpandSettings;
2693
2684
  if (!this.isFiltered) {
2694
- this.originalExpandedKeys = this.expandedKeys.slice();
2685
+ this.originalExpandedKeys = new Set(this.state);
2695
2686
  }
2696
2687
  const exitingFilteredState = this.isFiltered && !term;
2697
2688
  const maxExceeded = maxAutoExpandResults !== -1 && matchCount > maxAutoExpandResults;
@@ -2699,18 +2690,18 @@ let ExpandDirective = class ExpandDirective {
2699
2690
  if (exitAutoExpandedState) {
2700
2691
  switch (expandedOnClear) {
2701
2692
  case "initial": {
2702
- if (!sameValues(this.expandedKeys, this.originalExpandedKeys)) {
2703
- this.expandedKeys = this.originalExpandedKeys;
2704
- this.expandedKeysChange.emit(this.expandedKeys);
2693
+ if (!sameValues(this.state, this.originalExpandedKeys)) {
2694
+ this.state = this.originalExpandedKeys;
2695
+ this.notify();
2705
2696
  }
2706
2697
  break;
2707
2698
  }
2708
2699
  case "all": {
2709
- this.expandedKeys = nodes.reduce((acc, rootNode) => {
2700
+ this.state = new Set(nodes.reduce((acc, rootNode) => {
2710
2701
  this.getEveryExpandKey(acc, rootNode);
2711
2702
  return acc;
2712
- }, []);
2713
- this.expandedKeysChange.emit(this.expandedKeys);
2703
+ }, []));
2704
+ this.notify();
2714
2705
  break;
2715
2706
  }
2716
2707
  case "unchanged": {
@@ -2718,9 +2709,9 @@ let ExpandDirective = class ExpandDirective {
2718
2709
  }
2719
2710
  case "none":
2720
2711
  default: {
2721
- if (this.expandedKeys.length !== 0) {
2722
- this.expandedKeys = [];
2723
- this.expandedKeysChange.emit(this.expandedKeys);
2712
+ if (this.state.size !== 0) {
2713
+ this.state.clear();
2714
+ this.notify();
2724
2715
  }
2725
2716
  break;
2726
2717
  }
@@ -2728,16 +2719,20 @@ let ExpandDirective = class ExpandDirective {
2728
2719
  this.isFiltered = false;
2729
2720
  return;
2730
2721
  }
2731
- const indicesToExpand = nodes.reduce((acc, rootNode) => {
2722
+ const indicesToExpand = new Set(nodes.reduce((acc, rootNode) => {
2732
2723
  this.updateExpandedNodes(acc, rootNode, autoExpandMatches);
2733
2724
  return acc;
2734
- }, []);
2735
- if (!sameValues(this.expandedKeys, indicesToExpand)) {
2736
- this.expandedKeys = indicesToExpand;
2737
- this.expandedKeysChange.emit(this.expandedKeys);
2725
+ }, []));
2726
+ if (!sameValues(this.state, indicesToExpand)) {
2727
+ this.state = indicesToExpand;
2728
+ this.notify();
2738
2729
  }
2739
2730
  this.isFiltered = true;
2740
2731
  }
2732
+ notify() {
2733
+ this.lastChange = Array.from(this.state);
2734
+ this.expandedKeysChange.emit(this.lastChange);
2735
+ }
2741
2736
  };
2742
2737
  __decorate([
2743
2738
  Input(),
@@ -2758,9 +2753,8 @@ __decorate([
2758
2753
  ], ExpandDirective.prototype, "expandedKeysChange", void 0);
2759
2754
  __decorate([
2760
2755
  Input(),
2761
- __metadata("design:type", Array),
2762
- __metadata("design:paramtypes", [Array])
2763
- ], ExpandDirective.prototype, "expandedKeys", null);
2756
+ __metadata("design:type", Array)
2757
+ ], ExpandDirective.prototype, "expandedKeys", void 0);
2764
2758
  ExpandDirective = __decorate([
2765
2759
  Directive({ selector: '[kendoTreeViewExpandable]' }),
2766
2760
  __metadata("design:paramtypes", [ExpandableComponent])
@@ -2782,9 +2776,12 @@ let SelectDirective = class SelectDirective {
2782
2776
  'multiple': (e) => this.selectMultiple(e),
2783
2777
  'single': (e) => this.selectSingle(e)
2784
2778
  };
2785
- this._selectedKeys = [];
2779
+ /**
2780
+ * Reflectes the internal `selectedKeys` state.
2781
+ */
2782
+ this.state = new Set();
2786
2783
  this.subscriptions.add(this.treeView.selectionChange.subscribe(this.select.bind(this)));
2787
- this.treeView.isSelected = (dataItem, index) => (this.selectedKeys.indexOf(this.itemKey({ dataItem, index })) > -1);
2784
+ this.treeView.isSelected = (dataItem, index) => (this.state.has(this.itemKey({ dataItem, index })));
2788
2785
  }
2789
2786
  /**
2790
2787
  * @hidden
@@ -2792,16 +2789,6 @@ let SelectDirective = class SelectDirective {
2792
2789
  set isSelected(value) {
2793
2790
  this.treeView.isSelected = value;
2794
2791
  }
2795
- /**
2796
- * Defines the collection that will store the selected keys
2797
- * ([see example]({% slug selection_treeview %}#toc-selection-modes)).
2798
- */
2799
- get selectedKeys() {
2800
- return this._selectedKeys;
2801
- }
2802
- set selectedKeys(keys) {
2803
- this._selectedKeys = keys;
2804
- }
2805
2792
  get getAriaMultiselectable() {
2806
2793
  return this.options.mode === 'multiple';
2807
2794
  }
@@ -2816,6 +2803,11 @@ let SelectDirective = class SelectDirective {
2816
2803
  const selectionSettings = isBoolean(this.selection) ? { enabled: this.selection } : this.selection;
2817
2804
  return Object.assign(defaultOptions, selectionSettings);
2818
2805
  }
2806
+ ngOnChanges(changes) {
2807
+ if (isChanged('selectedKeys', changes, false) && changes.selectedKeys.currentValue !== this.lastChange) {
2808
+ this.state = new Set(changes.selectedKeys.currentValue);
2809
+ }
2810
+ }
2819
2811
  ngOnDestroy() {
2820
2812
  this.subscriptions.unsubscribe();
2821
2813
  }
@@ -2840,29 +2832,29 @@ let SelectDirective = class SelectDirective {
2840
2832
  }
2841
2833
  selectSingle(node) {
2842
2834
  const key = this.itemKey(node);
2843
- if (this.selectedKeys[0] === key) {
2844
- return;
2835
+ if (!this.state.has(key)) {
2836
+ this.state.clear();
2837
+ this.state.add(key);
2838
+ this.notify();
2845
2839
  }
2846
- this.selectedKeys = [key];
2847
- this.notify();
2848
2840
  }
2849
2841
  selectMultiple(node) {
2850
2842
  const key = this.itemKey(node);
2851
- const idx = this.selectedKeys.indexOf(key);
2852
- const isSelected = idx > -1;
2843
+ const isSelected = this.state.has(key);
2853
2844
  if (!isPresent(key)) {
2854
2845
  return;
2855
2846
  }
2856
2847
  if (isSelected) {
2857
- this.selectedKeys.splice(idx, 1);
2848
+ this.state.delete(key);
2858
2849
  }
2859
2850
  else {
2860
- this.selectedKeys.push(key);
2851
+ this.state.add(key);
2861
2852
  }
2862
2853
  this.notify();
2863
2854
  }
2864
2855
  notify() {
2865
- this.selectedKeysChange.emit(this.selectedKeys.slice());
2856
+ this.lastChange = Array.from(this.state);
2857
+ this.selectedKeysChange.emit(this.lastChange);
2866
2858
  }
2867
2859
  };
2868
2860
  __decorate([
@@ -2880,9 +2872,8 @@ __decorate([
2880
2872
  ], SelectDirective.prototype, "selection", void 0);
2881
2873
  __decorate([
2882
2874
  Input(),
2883
- __metadata("design:type", Array),
2884
- __metadata("design:paramtypes", [Array])
2885
- ], SelectDirective.prototype, "selectedKeys", null);
2875
+ __metadata("design:type", Array)
2876
+ ], SelectDirective.prototype, "selectedKeys", void 0);
2886
2877
  __decorate([
2887
2878
  Output(),
2888
2879
  __metadata("design:type", EventEmitter)