@progress/kendo-angular-treelist 21.0.0-develop.9 → 21.0.0

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.
@@ -39,7 +39,7 @@ const decorate = (element) => {
39
39
  };
40
40
  const svgIconsMarkup = (viewBox, content, safeTitle) => `
41
41
  <span class="k-icon k-svg-icon k-drag-status k-svg-i-cancel">
42
- <svg
42
+ <svg
43
43
  xmlns="http://www.w3.org/2000/svg"
44
44
  xmlns:xlink="http://www.w3.org/1999/xlink"
45
45
  viewBox="${viewBox}"
@@ -95,7 +95,11 @@ export class DragHintService {
95
95
  remove() {
96
96
  if (this.dom && this.dom.parentNode) {
97
97
  (function (el) {
98
- setTimeout(() => document.body.removeChild(el));
98
+ setTimeout(() => {
99
+ if (isDocumentAvailable()) {
100
+ document.body.removeChild(el);
101
+ }
102
+ });
99
103
  })(this.dom); // hack for IE + pointer events!
100
104
  this.dom = null;
101
105
  }
@@ -20,6 +20,8 @@ import { closest, contains, findFocusableChild, isVisible, matchesNodeName } fro
20
20
  import { ScrollRequestService } from '../scrolling/scroll-request.service';
21
21
  import { SelectionService } from '../selection/selection.service';
22
22
  import { PagerContextService } from '@progress/kendo-angular-pager';
23
+ import { ContextService } from '../common/provider.service';
24
+ import { hasClasses } from '@progress/kendo-angular-common';
23
25
  import * as i0 from "@angular/core";
24
26
  import * as i1 from "../common/dom-events.service";
25
27
  import * as i2 from "@progress/kendo-angular-pager";
@@ -29,7 +31,8 @@ import * as i5 from "../editing/edit.service";
29
31
  import * as i6 from "@progress/kendo-angular-l10n";
30
32
  import * as i7 from "../expand-state/expand-state.service";
31
33
  import * as i8 from "../selection/selection.service";
32
- import * as i9 from "./focusable.directive";
34
+ import * as i9 from "../common/provider.service";
35
+ import * as i10 from "./focusable.directive";
33
36
  const isInSameTreeList = (element, treelistElement) => closest(element, matchesNodeName('kendo-treelist')) === treelistElement;
34
37
  const matchHeaderCell = matchesNodeName('th');
35
38
  const matchDataCell = matchesNodeName('td');
@@ -96,6 +99,7 @@ export class NavigationService {
96
99
  expandState;
97
100
  selectionService;
98
101
  changeDetector;
102
+ ctx;
99
103
  focusableParent;
100
104
  changes;
101
105
  cellKeydown = new EventEmitter();
@@ -136,7 +140,7 @@ export class NavigationService {
136
140
  get activeDataRow() {
137
141
  return Math.max(0, this.activeRowIndex - this.meta.headerRows);
138
142
  }
139
- constructor(zone, domEvents, pagerContextService, scrollRequestService, focusRoot, editService, localization, expandState, selectionService, changeDetector, focusableParent) {
143
+ constructor(zone, domEvents, pagerContextService, scrollRequestService, focusRoot, editService, localization, expandState, selectionService, changeDetector, ctx, focusableParent) {
140
144
  this.zone = zone;
141
145
  this.domEvents = domEvents;
142
146
  this.pagerContextService = pagerContextService;
@@ -147,6 +151,7 @@ export class NavigationService {
147
151
  this.expandState = expandState;
148
152
  this.selectionService = selectionService;
149
153
  this.changeDetector = changeDetector;
154
+ this.ctx = ctx;
150
155
  this.focusableParent = focusableParent;
151
156
  this.changes = this.cursor.changes;
152
157
  }
@@ -400,6 +405,13 @@ export class NavigationService {
400
405
  }
401
406
  // on some keyboards arrow keys, PageUp/Down, and Home/End are mapped to Numpad keys
402
407
  const code = normalizeNumpadKeys(args);
408
+ if ((args.ctrlKey || args.metaKey) && args.shiftKey && (code === Keys.ArrowUp || code === Keys.ArrowDown)) {
409
+ const row = this.cursor.row;
410
+ if (this.handleRowReorderKeyboard(args, code, row)) {
411
+ args.preventDefault();
412
+ return;
413
+ }
414
+ }
403
415
  const row = this.cursor.row;
404
416
  switch (code) {
405
417
  case Keys.Space:
@@ -414,13 +426,13 @@ export class NavigationService {
414
426
  break;
415
427
  case Keys.ArrowDown:
416
428
  preventDefault = this.cursor.moveDown(step);
417
- if (preventDefault && args.shiftKey) {
429
+ if (preventDefault && args.shiftKey && !modifier) {
418
430
  this.updateSelection(args);
419
431
  }
420
432
  break;
421
433
  case Keys.ArrowUp:
422
434
  preventDefault = this.cursor.moveUp(step);
423
- if (preventDefault && args.shiftKey) {
435
+ if (preventDefault && args.shiftKey && !modifier) {
424
436
  this.updateSelection(args);
425
437
  }
426
438
  break;
@@ -615,6 +627,45 @@ export class NavigationService {
615
627
  this.deactivateElements();
616
628
  this.cursor.announce();
617
629
  }
630
+ handleRowReorderKeyboard(args, code, row) {
631
+ if (!this.ctx.treelist?.rowReorderable || !this.activeCell) {
632
+ return false;
633
+ }
634
+ const cellElement = args.target;
635
+ if (!cellElement) {
636
+ return false;
637
+ }
638
+ const dragCell = closest(cellElement, (el) => hasClasses(el, 'k-drag-cell'));
639
+ if (!dragCell || row.dataRowIndex < 0 || !row.dataItem) {
640
+ return false;
641
+ }
642
+ const isUpArrow = code === Keys.ArrowUp;
643
+ const currentRowIndex = row.dataRowIndex;
644
+ const view = this.ctx.treelist.view;
645
+ if (!view || view.length === 0) {
646
+ return false;
647
+ }
648
+ const targetRowIndex = currentRowIndex + (isUpArrow ? -1 : 1);
649
+ if (targetRowIndex < 0 || targetRowIndex >= view.length) {
650
+ return false;
651
+ }
652
+ const dropPosition = isUpArrow ? 'before' : 'after';
653
+ this.zone.run(() => {
654
+ const rowReorderService = this.ctx.treelist.rowReorderService;
655
+ if (rowReorderService?.reorderViaKeyboard) {
656
+ // Convert ViewCollection to array for the reorder method
657
+ const viewArray = Array.from({ length: view.length }, (_, i) => view.at(i));
658
+ rowReorderService.reorderViaKeyboard(currentRowIndex, targetRowIndex, dropPosition, viewArray);
659
+ // Move focus to follow the reordered row
660
+ // After reordering, the row will be at the target position
661
+ this.zone.onStable.pipe(take(1)).subscribe(() => {
662
+ const newRowIndex = this.meta.headerRows + targetRowIndex;
663
+ this.cursor.reset(newRowIndex, this.activeCell.colIndex);
664
+ });
665
+ }
666
+ });
667
+ return true;
668
+ }
618
669
  onKeydown(args) {
619
670
  if (this.mode === 1 /* NavigationMode.Cursor */) {
620
671
  this.onCursorKeydown(args);
@@ -634,11 +685,11 @@ export class NavigationService {
634
685
  this.leaveCell();
635
686
  this.cursor.reset();
636
687
  }
637
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NavigationService, deps: [{ token: i0.NgZone }, { token: i1.DomEventsService }, { token: i2.PagerContextService }, { token: i3.ScrollRequestService }, { token: i4.FocusRoot }, { token: i5.EditService }, { token: i6.LocalizationService }, { token: i7.ExpandStateService }, { token: i8.SelectionService }, { token: i0.ChangeDetectorRef }, { token: i9.FocusableDirective, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
688
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NavigationService, deps: [{ token: i0.NgZone }, { token: i1.DomEventsService }, { token: i2.PagerContextService }, { token: i3.ScrollRequestService }, { token: i4.FocusRoot }, { token: i5.EditService }, { token: i6.LocalizationService }, { token: i7.ExpandStateService }, { token: i8.SelectionService }, { token: i0.ChangeDetectorRef }, { token: i9.ContextService }, { token: i10.FocusableDirective, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
638
689
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NavigationService });
639
690
  }
640
691
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NavigationService, decorators: [{
641
692
  type: Injectable
642
- }], ctorParameters: () => [{ type: i0.NgZone }, { type: i1.DomEventsService }, { type: i2.PagerContextService }, { type: i3.ScrollRequestService }, { type: i4.FocusRoot }, { type: i5.EditService }, { type: i6.LocalizationService }, { type: i7.ExpandStateService }, { type: i8.SelectionService }, { type: i0.ChangeDetectorRef }, { type: i9.FocusableDirective, decorators: [{
693
+ }], ctorParameters: () => [{ type: i0.NgZone }, { type: i1.DomEventsService }, { type: i2.PagerContextService }, { type: i3.ScrollRequestService }, { type: i4.FocusRoot }, { type: i5.EditService }, { type: i6.LocalizationService }, { type: i7.ExpandStateService }, { type: i8.SelectionService }, { type: i0.ChangeDetectorRef }, { type: i9.ContextService }, { type: i10.FocusableDirective, decorators: [{
643
694
  type: Optional
644
695
  }] }] });
@@ -10,7 +10,7 @@ export const packageMetadata = {
10
10
  productName: 'Kendo UI for Angular',
11
11
  productCode: 'KENDOUIANGULAR',
12
12
  productCodes: ['KENDOUIANGULAR'],
13
- publishDate: 1761910433,
14
- version: '21.0.0-develop.9',
13
+ publishDate: 1762934619,
14
+ version: '21.0.0',
15
15
  licensingDocsUrl: 'https://www.telerik.com/kendo-angular-ui/my-license/'
16
16
  };
@@ -104,6 +104,34 @@ export class RowReorderService {
104
104
  }
105
105
  isOverChild(_item) { return false; }
106
106
  reorderRows(_ev, _collection, _field) { }
107
+ /**
108
+ * Triggers row reordering programmatically via keyboard shortcut.
109
+ * @param dragRowIndex - The index of the row to move
110
+ * @param dropRowIndex - The index of the target row
111
+ * @param dropPosition - The position relative to the target row ('before' or 'after')
112
+ * @param data - The data array (view)
113
+ */
114
+ reorderViaKeyboard(dragRowIndex, dropRowIndex, dropPosition, data) {
115
+ if (dropPosition === 'forbidden') {
116
+ return;
117
+ }
118
+ const dragRow = this.createVirtualRowElement(dragRowIndex);
119
+ const dropRow = this.createVirtualRowElement(dropRowIndex);
120
+ this.lastDropPosition = dropPosition;
121
+ const rowReorderArgs = this.rowReorderArgs(dragRow, dropRow, data);
122
+ this.rowReorder.emit(rowReorderArgs);
123
+ }
124
+ createVirtualRowElement(rowIndex) {
125
+ const virtualElement = {
126
+ getAttribute: (attr) => {
127
+ if (attr === rowIndexAttr) {
128
+ return String(rowIndex);
129
+ }
130
+ return null;
131
+ }
132
+ };
133
+ return virtualElement;
134
+ }
107
135
  get parentIdField() {
108
136
  return this.bindingDirective.parentIdField;
109
137
  }
@@ -49,8 +49,8 @@ const packageMetadata = {
49
49
  productName: 'Kendo UI for Angular',
50
50
  productCode: 'KENDOUIANGULAR',
51
51
  productCodes: ['KENDOUIANGULAR'],
52
- publishDate: 1761910433,
53
- version: '21.0.0-develop.9',
52
+ publishDate: 1762934619,
53
+ version: '21.0.0',
54
54
  licensingDocsUrl: 'https://www.telerik.com/kendo-angular-ui/my-license/'
55
55
  };
56
56
 
@@ -3225,7 +3225,7 @@ const decorate = (element) => {
3225
3225
  };
3226
3226
  const svgIconsMarkup = (viewBox, content, safeTitle) => `
3227
3227
  <span class="k-icon k-svg-icon k-drag-status k-svg-i-cancel">
3228
- <svg
3228
+ <svg
3229
3229
  xmlns="http://www.w3.org/2000/svg"
3230
3230
  xmlns:xlink="http://www.w3.org/1999/xlink"
3231
3231
  viewBox="${viewBox}"
@@ -3281,7 +3281,11 @@ class DragHintService {
3281
3281
  remove() {
3282
3282
  if (this.dom && this.dom.parentNode) {
3283
3283
  (function (el) {
3284
- setTimeout(() => document.body.removeChild(el));
3284
+ setTimeout(() => {
3285
+ if (isDocumentAvailable()) {
3286
+ document.body.removeChild(el);
3287
+ }
3288
+ });
3285
3289
  })(this.dom); // hack for IE + pointer events!
3286
3290
  this.dom = null;
3287
3291
  }
@@ -4509,6 +4513,80 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
4509
4513
  type: Injectable
4510
4514
  }] });
4511
4515
 
4516
+ /**
4517
+ * @hidden
4518
+ */
4519
+ class TreeListToolbarNavigationService {
4520
+ renderer;
4521
+ navigableElements = [];
4522
+ currentActiveIndex = 0;
4523
+ defaultFocusableSelector = `
4524
+ [kendoTreeListToolbarFocusable],
4525
+ [kendoTreeListAddCommand],
4526
+ [kendoTreeListCancelCommand],
4527
+ [kendoTreeListEditCommand],
4528
+ [kendoTreeListRemoveCommand],
4529
+ [kendoTreeListSaveCommand],
4530
+ [kendoTreeListExcelCommand],
4531
+ [kendoTreeListPDFCommand]
4532
+ `;
4533
+ constructor(renderer) {
4534
+ this.renderer = renderer;
4535
+ }
4536
+ notify() {
4537
+ // ensure focusable elements are in the same order as in the DOM
4538
+ this.navigableElements = (this.navigableElements.length && this.navigableElements[0]?.parentElement) ? Array.from(this.navigableElements[0]?.parentElement?.querySelectorAll(this.defaultFocusableSelector) || []) : [];
4539
+ this.currentActiveIndex = 0;
4540
+ this.updateFocus();
4541
+ }
4542
+ focus() {
4543
+ this.navigableElements[this.currentActiveIndex]?.focus();
4544
+ }
4545
+ updateFocus() {
4546
+ if (!this.navigableElements.length) {
4547
+ return;
4548
+ }
4549
+ this.navigableElements.forEach(el => {
4550
+ this.renderer.setAttribute(el, 'tabindex', '-1');
4551
+ });
4552
+ this.renderer.setAttribute(this.navigableElements[this.currentActiveIndex], 'tabindex', '0');
4553
+ if (isDocumentAvailable() && document.activeElement.closest('.k-toolbar')) {
4554
+ this.navigableElements[this.currentActiveIndex].focus();
4555
+ }
4556
+ }
4557
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TreeListToolbarNavigationService, deps: [{ token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Injectable });
4558
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TreeListToolbarNavigationService });
4559
+ }
4560
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TreeListToolbarNavigationService, decorators: [{
4561
+ type: Injectable
4562
+ }], ctorParameters: () => [{ type: i0.Renderer2 }] });
4563
+
4564
+ /**
4565
+ * @hidden
4566
+ *
4567
+ * The Context service is used to provide common
4568
+ * services and DI tokens for a Grid instance.
4569
+ *
4570
+ * This keeps the constructor parameters stable
4571
+ * and a avoids dependency cycles between components.
4572
+ */
4573
+ class ContextService {
4574
+ localization;
4575
+ treelist;
4576
+ topToolbarNavigation;
4577
+ bottomToolbarNavigation;
4578
+ constructor(renderer, localization) {
4579
+ this.localization = localization;
4580
+ this.topToolbarNavigation = new TreeListToolbarNavigationService(renderer);
4581
+ this.bottomToolbarNavigation = new TreeListToolbarNavigationService(renderer);
4582
+ }
4583
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ContextService, deps: [{ token: i0.Renderer2 }, { token: i1$1.LocalizationService }], target: i0.ɵɵFactoryTarget.Injectable });
4584
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ContextService });
4585
+ }
4586
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ContextService, decorators: [{
4587
+ type: Injectable
4588
+ }], ctorParameters: () => [{ type: i0.Renderer2 }, { type: i1$1.LocalizationService }] });
4589
+
4512
4590
  const isInSameTreeList = (element, treelistElement) => closest(element, matchesNodeName('kendo-treelist')) === treelistElement;
4513
4591
  const matchHeaderCell = matchesNodeName('th');
4514
4592
  const matchDataCell = matchesNodeName('td');
@@ -4575,6 +4653,7 @@ class NavigationService {
4575
4653
  expandState;
4576
4654
  selectionService;
4577
4655
  changeDetector;
4656
+ ctx;
4578
4657
  focusableParent;
4579
4658
  changes;
4580
4659
  cellKeydown = new EventEmitter();
@@ -4615,7 +4694,7 @@ class NavigationService {
4615
4694
  get activeDataRow() {
4616
4695
  return Math.max(0, this.activeRowIndex - this.meta.headerRows);
4617
4696
  }
4618
- constructor(zone, domEvents, pagerContextService, scrollRequestService, focusRoot, editService, localization, expandState, selectionService, changeDetector, focusableParent) {
4697
+ constructor(zone, domEvents, pagerContextService, scrollRequestService, focusRoot, editService, localization, expandState, selectionService, changeDetector, ctx, focusableParent) {
4619
4698
  this.zone = zone;
4620
4699
  this.domEvents = domEvents;
4621
4700
  this.pagerContextService = pagerContextService;
@@ -4626,6 +4705,7 @@ class NavigationService {
4626
4705
  this.expandState = expandState;
4627
4706
  this.selectionService = selectionService;
4628
4707
  this.changeDetector = changeDetector;
4708
+ this.ctx = ctx;
4629
4709
  this.focusableParent = focusableParent;
4630
4710
  this.changes = this.cursor.changes;
4631
4711
  }
@@ -4879,6 +4959,13 @@ class NavigationService {
4879
4959
  }
4880
4960
  // on some keyboards arrow keys, PageUp/Down, and Home/End are mapped to Numpad keys
4881
4961
  const code = normalizeNumpadKeys(args);
4962
+ if ((args.ctrlKey || args.metaKey) && args.shiftKey && (code === Keys.ArrowUp || code === Keys.ArrowDown)) {
4963
+ const row = this.cursor.row;
4964
+ if (this.handleRowReorderKeyboard(args, code, row)) {
4965
+ args.preventDefault();
4966
+ return;
4967
+ }
4968
+ }
4882
4969
  const row = this.cursor.row;
4883
4970
  switch (code) {
4884
4971
  case Keys.Space:
@@ -4893,13 +4980,13 @@ class NavigationService {
4893
4980
  break;
4894
4981
  case Keys.ArrowDown:
4895
4982
  preventDefault = this.cursor.moveDown(step);
4896
- if (preventDefault && args.shiftKey) {
4983
+ if (preventDefault && args.shiftKey && !modifier) {
4897
4984
  this.updateSelection(args);
4898
4985
  }
4899
4986
  break;
4900
4987
  case Keys.ArrowUp:
4901
4988
  preventDefault = this.cursor.moveUp(step);
4902
- if (preventDefault && args.shiftKey) {
4989
+ if (preventDefault && args.shiftKey && !modifier) {
4903
4990
  this.updateSelection(args);
4904
4991
  }
4905
4992
  break;
@@ -5094,6 +5181,45 @@ class NavigationService {
5094
5181
  this.deactivateElements();
5095
5182
  this.cursor.announce();
5096
5183
  }
5184
+ handleRowReorderKeyboard(args, code, row) {
5185
+ if (!this.ctx.treelist?.rowReorderable || !this.activeCell) {
5186
+ return false;
5187
+ }
5188
+ const cellElement = args.target;
5189
+ if (!cellElement) {
5190
+ return false;
5191
+ }
5192
+ const dragCell = closest(cellElement, (el) => hasClasses$1(el, 'k-drag-cell'));
5193
+ if (!dragCell || row.dataRowIndex < 0 || !row.dataItem) {
5194
+ return false;
5195
+ }
5196
+ const isUpArrow = code === Keys.ArrowUp;
5197
+ const currentRowIndex = row.dataRowIndex;
5198
+ const view = this.ctx.treelist.view;
5199
+ if (!view || view.length === 0) {
5200
+ return false;
5201
+ }
5202
+ const targetRowIndex = currentRowIndex + (isUpArrow ? -1 : 1);
5203
+ if (targetRowIndex < 0 || targetRowIndex >= view.length) {
5204
+ return false;
5205
+ }
5206
+ const dropPosition = isUpArrow ? 'before' : 'after';
5207
+ this.zone.run(() => {
5208
+ const rowReorderService = this.ctx.treelist.rowReorderService;
5209
+ if (rowReorderService?.reorderViaKeyboard) {
5210
+ // Convert ViewCollection to array for the reorder method
5211
+ const viewArray = Array.from({ length: view.length }, (_, i) => view.at(i));
5212
+ rowReorderService.reorderViaKeyboard(currentRowIndex, targetRowIndex, dropPosition, viewArray);
5213
+ // Move focus to follow the reordered row
5214
+ // After reordering, the row will be at the target position
5215
+ this.zone.onStable.pipe(take(1)).subscribe(() => {
5216
+ const newRowIndex = this.meta.headerRows + targetRowIndex;
5217
+ this.cursor.reset(newRowIndex, this.activeCell.colIndex);
5218
+ });
5219
+ }
5220
+ });
5221
+ return true;
5222
+ }
5097
5223
  onKeydown(args) {
5098
5224
  if (this.mode === 1 /* NavigationMode.Cursor */) {
5099
5225
  this.onCursorKeydown(args);
@@ -5113,12 +5239,12 @@ class NavigationService {
5113
5239
  this.leaveCell();
5114
5240
  this.cursor.reset();
5115
5241
  }
5116
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NavigationService, deps: [{ token: i0.NgZone }, { token: DomEventsService }, { token: i107.PagerContextService }, { token: ScrollRequestService }, { token: FocusRoot }, { token: EditService }, { token: i1$1.LocalizationService }, { token: ExpandStateService }, { token: SelectionService }, { token: i0.ChangeDetectorRef }, { token: FocusableDirective, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
5242
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NavigationService, deps: [{ token: i0.NgZone }, { token: DomEventsService }, { token: i107.PagerContextService }, { token: ScrollRequestService }, { token: FocusRoot }, { token: EditService }, { token: i1$1.LocalizationService }, { token: ExpandStateService }, { token: SelectionService }, { token: i0.ChangeDetectorRef }, { token: ContextService }, { token: FocusableDirective, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
5117
5243
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NavigationService });
5118
5244
  }
5119
5245
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NavigationService, decorators: [{
5120
5246
  type: Injectable
5121
- }], ctorParameters: () => [{ type: i0.NgZone }, { type: DomEventsService }, { type: i107.PagerContextService }, { type: ScrollRequestService }, { type: FocusRoot }, { type: EditService }, { type: i1$1.LocalizationService }, { type: ExpandStateService }, { type: SelectionService }, { type: i0.ChangeDetectorRef }, { type: FocusableDirective, decorators: [{
5247
+ }], ctorParameters: () => [{ type: i0.NgZone }, { type: DomEventsService }, { type: i107.PagerContextService }, { type: ScrollRequestService }, { type: FocusRoot }, { type: EditService }, { type: i1$1.LocalizationService }, { type: ExpandStateService }, { type: SelectionService }, { type: i0.ChangeDetectorRef }, { type: ContextService }, { type: FocusableDirective, decorators: [{
5122
5248
  type: Optional
5123
5249
  }] }] });
5124
5250
 
@@ -5329,80 +5455,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
5329
5455
  type: Injectable
5330
5456
  }] });
5331
5457
 
5332
- /**
5333
- * @hidden
5334
- */
5335
- class TreeListToolbarNavigationService {
5336
- renderer;
5337
- navigableElements = [];
5338
- currentActiveIndex = 0;
5339
- defaultFocusableSelector = `
5340
- [kendoTreeListToolbarFocusable],
5341
- [kendoTreeListAddCommand],
5342
- [kendoTreeListCancelCommand],
5343
- [kendoTreeListEditCommand],
5344
- [kendoTreeListRemoveCommand],
5345
- [kendoTreeListSaveCommand],
5346
- [kendoTreeListExcelCommand],
5347
- [kendoTreeListPDFCommand]
5348
- `;
5349
- constructor(renderer) {
5350
- this.renderer = renderer;
5351
- }
5352
- notify() {
5353
- // ensure focusable elements are in the same order as in the DOM
5354
- this.navigableElements = (this.navigableElements.length && this.navigableElements[0]?.parentElement) ? Array.from(this.navigableElements[0]?.parentElement?.querySelectorAll(this.defaultFocusableSelector) || []) : [];
5355
- this.currentActiveIndex = 0;
5356
- this.updateFocus();
5357
- }
5358
- focus() {
5359
- this.navigableElements[this.currentActiveIndex]?.focus();
5360
- }
5361
- updateFocus() {
5362
- if (!this.navigableElements.length) {
5363
- return;
5364
- }
5365
- this.navigableElements.forEach(el => {
5366
- this.renderer.setAttribute(el, 'tabindex', '-1');
5367
- });
5368
- this.renderer.setAttribute(this.navigableElements[this.currentActiveIndex], 'tabindex', '0');
5369
- if (isDocumentAvailable() && document.activeElement.closest('.k-toolbar')) {
5370
- this.navigableElements[this.currentActiveIndex].focus();
5371
- }
5372
- }
5373
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TreeListToolbarNavigationService, deps: [{ token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Injectable });
5374
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TreeListToolbarNavigationService });
5375
- }
5376
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TreeListToolbarNavigationService, decorators: [{
5377
- type: Injectable
5378
- }], ctorParameters: () => [{ type: i0.Renderer2 }] });
5379
-
5380
- /**
5381
- * @hidden
5382
- *
5383
- * The Context service is used to provide common
5384
- * services and DI tokens for a Grid instance.
5385
- *
5386
- * This keeps the constructor parameters stable
5387
- * and a avoids dependency cycles between components.
5388
- */
5389
- class ContextService {
5390
- localization;
5391
- treelist;
5392
- topToolbarNavigation;
5393
- bottomToolbarNavigation;
5394
- constructor(renderer, localization) {
5395
- this.localization = localization;
5396
- this.topToolbarNavigation = new TreeListToolbarNavigationService(renderer);
5397
- this.bottomToolbarNavigation = new TreeListToolbarNavigationService(renderer);
5398
- }
5399
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ContextService, deps: [{ token: i0.Renderer2 }, { token: i1$1.LocalizationService }], target: i0.ɵɵFactoryTarget.Injectable });
5400
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ContextService });
5401
- }
5402
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ContextService, decorators: [{
5403
- type: Injectable
5404
- }], ctorParameters: () => [{ type: i0.Renderer2 }, { type: i1$1.LocalizationService }] });
5405
-
5406
5458
  /**
5407
5459
  * @hidden
5408
5460
  */
@@ -5625,6 +5677,34 @@ class RowReorderService {
5625
5677
  }
5626
5678
  isOverChild(_item) { return false; }
5627
5679
  reorderRows(_ev, _collection, _field) { }
5680
+ /**
5681
+ * Triggers row reordering programmatically via keyboard shortcut.
5682
+ * @param dragRowIndex - The index of the row to move
5683
+ * @param dropRowIndex - The index of the target row
5684
+ * @param dropPosition - The position relative to the target row ('before' or 'after')
5685
+ * @param data - The data array (view)
5686
+ */
5687
+ reorderViaKeyboard(dragRowIndex, dropRowIndex, dropPosition, data) {
5688
+ if (dropPosition === 'forbidden') {
5689
+ return;
5690
+ }
5691
+ const dragRow = this.createVirtualRowElement(dragRowIndex);
5692
+ const dropRow = this.createVirtualRowElement(dropRowIndex);
5693
+ this.lastDropPosition = dropPosition;
5694
+ const rowReorderArgs = this.rowReorderArgs(dragRow, dropRow, data);
5695
+ this.rowReorder.emit(rowReorderArgs);
5696
+ }
5697
+ createVirtualRowElement(rowIndex) {
5698
+ const virtualElement = {
5699
+ getAttribute: (attr) => {
5700
+ if (attr === rowIndexAttr) {
5701
+ return String(rowIndex);
5702
+ }
5703
+ return null;
5704
+ }
5705
+ };
5706
+ return virtualElement;
5707
+ }
5628
5708
  get parentIdField() {
5629
5709
  return this.bindingDirective.parentIdField;
5630
5710
  }
@@ -19,6 +19,7 @@ import { ExpandStateService } from '../expand-state/expand-state.service';
19
19
  import { ScrollRequestService } from '../scrolling/scroll-request.service';
20
20
  import { SelectionService } from '../selection/selection.service';
21
21
  import { PagerContextService } from '@progress/kendo-angular-pager';
22
+ import { ContextService } from '../common/provider.service';
22
23
  import * as i0 from "@angular/core";
23
24
  /**
24
25
  * @hidden
@@ -44,6 +45,7 @@ export declare class NavigationService implements OnDestroy {
44
45
  private expandState;
45
46
  private selectionService;
46
47
  private changeDetector;
48
+ private ctx;
47
49
  private focusableParent;
48
50
  readonly changes: Subject<NavigationChange>;
49
51
  readonly cellKeydown: EventEmitter<any>;
@@ -65,7 +67,7 @@ export declare class NavigationService implements OnDestroy {
65
67
  private pendingRowIndex;
66
68
  private virtualCell;
67
69
  private get activeDataRow();
68
- constructor(zone: NgZone, domEvents: DomEventsService, pagerContextService: PagerContextService, scrollRequestService: ScrollRequestService, focusRoot: FocusRoot, editService: EditService, localization: LocalizationService, expandState: ExpandStateService, selectionService: SelectionService, changeDetector: ChangeDetectorRef, focusableParent: FocusableDirective);
70
+ constructor(zone: NgZone, domEvents: DomEventsService, pagerContextService: PagerContextService, scrollRequestService: ScrollRequestService, focusRoot: FocusRoot, editService: EditService, localization: LocalizationService, expandState: ExpandStateService, selectionService: SelectionService, changeDetector: ChangeDetectorRef, ctx: ContextService, focusableParent: FocusableDirective);
69
71
  init(meta: NavigationMetadata): void;
70
72
  ngOnDestroy(): void;
71
73
  registerCell(cell: LogicalCell): void;
@@ -102,8 +104,9 @@ export declare class NavigationService implements OnDestroy {
102
104
  private onCursorChanges;
103
105
  private onFocusOut;
104
106
  private onWindowBlur;
107
+ private handleRowReorderKeyboard;
105
108
  private onKeydown;
106
109
  private onTabout;
107
- static ɵfac: i0.ɵɵFactoryDeclaration<NavigationService, [null, null, null, null, null, null, null, null, null, null, { optional: true; }]>;
110
+ static ɵfac: i0.ɵɵFactoryDeclaration<NavigationService, [null, null, null, null, null, null, null, null, null, null, null, { optional: true; }]>;
108
111
  static ɵprov: i0.ɵɵInjectableDeclaration<NavigationService>;
109
112
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@progress/kendo-angular-treelist",
3
- "version": "21.0.0-develop.9",
3
+ "version": "21.0.0",
4
4
  "description": "Kendo UI TreeList for Angular - Display hierarchical data in an Angular tree grid view that supports sorting, filtering, paging, and much more.",
5
5
  "license": "SEE LICENSE IN LICENSE.md",
6
6
  "author": "Progress",
@@ -24,7 +24,7 @@
24
24
  "package": {
25
25
  "productName": "Kendo UI for Angular",
26
26
  "productCode": "KENDOUIANGULAR",
27
- "publishDate": 1761910433,
27
+ "publishDate": 1762934619,
28
28
  "licensingDocsUrl": "https://www.telerik.com/kendo-angular-ui/my-license/"
29
29
  }
30
30
  },
@@ -37,26 +37,26 @@
37
37
  "@progress/kendo-data-query": "^1.0.0",
38
38
  "@progress/kendo-drawing": "^1.21.0",
39
39
  "@progress/kendo-licensing": "^1.7.0",
40
- "@progress/kendo-angular-buttons": "21.0.0-develop.9",
41
- "@progress/kendo-angular-common": "21.0.0-develop.9",
42
- "@progress/kendo-angular-dateinputs": "21.0.0-develop.9",
43
- "@progress/kendo-angular-dropdowns": "21.0.0-develop.9",
44
- "@progress/kendo-angular-excel-export": "21.0.0-develop.9",
45
- "@progress/kendo-angular-icons": "21.0.0-develop.9",
46
- "@progress/kendo-angular-inputs": "21.0.0-develop.9",
47
- "@progress/kendo-angular-intl": "21.0.0-develop.9",
48
- "@progress/kendo-angular-l10n": "21.0.0-develop.9",
49
- "@progress/kendo-angular-label": "21.0.0-develop.9",
50
- "@progress/kendo-angular-pager": "21.0.0-develop.9",
51
- "@progress/kendo-angular-pdf-export": "21.0.0-develop.9",
52
- "@progress/kendo-angular-popup": "21.0.0-develop.9",
53
- "@progress/kendo-angular-toolbar": "21.0.0-develop.9",
54
- "@progress/kendo-angular-utils": "21.0.0-develop.9",
40
+ "@progress/kendo-angular-buttons": "21.0.0",
41
+ "@progress/kendo-angular-common": "21.0.0",
42
+ "@progress/kendo-angular-dateinputs": "21.0.0",
43
+ "@progress/kendo-angular-dropdowns": "21.0.0",
44
+ "@progress/kendo-angular-excel-export": "21.0.0",
45
+ "@progress/kendo-angular-icons": "21.0.0",
46
+ "@progress/kendo-angular-inputs": "21.0.0",
47
+ "@progress/kendo-angular-intl": "21.0.0",
48
+ "@progress/kendo-angular-l10n": "21.0.0",
49
+ "@progress/kendo-angular-label": "21.0.0",
50
+ "@progress/kendo-angular-pager": "21.0.0",
51
+ "@progress/kendo-angular-pdf-export": "21.0.0",
52
+ "@progress/kendo-angular-popup": "21.0.0",
53
+ "@progress/kendo-angular-toolbar": "21.0.0",
54
+ "@progress/kendo-angular-utils": "21.0.0",
55
55
  "rxjs": "^6.5.3 || ^7.0.0"
56
56
  },
57
57
  "dependencies": {
58
58
  "tslib": "^2.3.1",
59
- "@progress/kendo-angular-schematics": "21.0.0-develop.9",
59
+ "@progress/kendo-angular-schematics": "21.0.0",
60
60
  "@progress/kendo-common": "^1.0.1",
61
61
  "@progress/kendo-file-saver": "^1.0.0"
62
62
  },
@@ -4,7 +4,7 @@
4
4
  *-------------------------------------------------------------------------------------------*/
5
5
  import { DragTargetPressEvent, DragTargetDragEvent, DropTargetEvent } from '@progress/kendo-angular-utils';
6
6
  import { EventEmitter, Renderer2 } from '@angular/core';
7
- import { RowReorderEvent } from './types';
7
+ import { DropPosition, RowReorderEvent } from './types';
8
8
  import { SVGIcon } from '@progress/kendo-svg-icons';
9
9
  import { ColumnList } from '../columns/column-list';
10
10
  import * as i0 from "@angular/core";
@@ -42,6 +42,15 @@ export declare class RowReorderService {
42
42
  rowReorderArgs(dragRow: HTMLElement, dropRow: HTMLElement, data: Array<any>): RowReorderEvent;
43
43
  isOverChild(_item: any): boolean;
44
44
  reorderRows(_ev: RowReorderEvent, _collection: Array<any>, _field?: string): void;
45
+ /**
46
+ * Triggers row reordering programmatically via keyboard shortcut.
47
+ * @param dragRowIndex - The index of the row to move
48
+ * @param dropRowIndex - The index of the target row
49
+ * @param dropPosition - The position relative to the target row ('before' or 'after')
50
+ * @param data - The data array (view)
51
+ */
52
+ reorderViaKeyboard(dragRowIndex: number, dropRowIndex: number, dropPosition: DropPosition, data: Array<any>): void;
53
+ private createVirtualRowElement;
45
54
  get parentIdField(): string;
46
55
  get idField(): string;
47
56
  get childrenField(): string;
@@ -5,13 +5,13 @@ const schematics_1 = require("@angular-devkit/schematics");
5
5
  function default_1(options) {
6
6
  const finalOptions = Object.assign(Object.assign({}, options), { mainNgModule: 'TreeListModule', package: 'treelist', peerDependencies: {
7
7
  // peer dep of the dropdowns
8
- '@progress/kendo-angular-treeview': '21.0.0-develop.9',
8
+ '@progress/kendo-angular-treeview': '21.0.0',
9
9
  // peer dependency of kendo-angular-inputs
10
- '@progress/kendo-angular-dialog': '21.0.0-develop.9',
10
+ '@progress/kendo-angular-dialog': '21.0.0',
11
11
  // peer dependency of kendo-angular-icons
12
12
  '@progress/kendo-svg-icons': '^4.0.0',
13
13
  // peer dependency of kendo-angular-dateinputs
14
- '@progress/kendo-angular-navigation': '21.0.0-develop.9',
14
+ '@progress/kendo-angular-navigation': '21.0.0',
15
15
  } });
16
16
  return (0, schematics_1.externalSchematic)('@progress/kendo-angular-schematics', 'ng-add', finalOptions);
17
17
  }