@progress/kendo-angular-treeview 21.4.1 → 22.0.0-develop.1
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.
- package/fesm2022/progress-kendo-angular-treeview.mjs +115 -115
- package/filtering-base.d.ts +1 -1
- package/localization/messages.d.ts +1 -1
- package/package.json +11 -19
- package/schematics/ngAdd/index.js +4 -4
- package/esm2022/check-mode.mjs +0 -5
- package/esm2022/check.directive.mjs +0 -334
- package/esm2022/checkable-settings.mjs +0 -5
- package/esm2022/checkbox/checked-state.mjs +0 -5
- package/esm2022/data-bound-component.mjs +0 -19
- package/esm2022/data-change-notification.service.mjs +0 -14
- package/esm2022/default-callbacks.mjs +0 -36
- package/esm2022/directives.mjs +0 -53
- package/esm2022/disable.directive.mjs +0 -83
- package/esm2022/drag-and-drop/drag-and-drop-editing.directive.mjs +0 -76
- package/esm2022/drag-and-drop/drag-and-drop-utils.mjs +0 -270
- package/esm2022/drag-and-drop/drag-and-drop.directive.mjs +0 -348
- package/esm2022/drag-and-drop/drag-clue/drag-clue-template.directive.mjs +0 -44
- package/esm2022/drag-and-drop/drag-clue/drag-clue.component.mjs +0 -132
- package/esm2022/drag-and-drop/drag-clue/drag-clue.service.mjs +0 -123
- package/esm2022/drag-and-drop/drop-hint/drop-hint-template.directive.mjs +0 -43
- package/esm2022/drag-and-drop/drop-hint/drop-hint.component.mjs +0 -102
- package/esm2022/drag-and-drop/drop-hint/drop-hint.service.mjs +0 -41
- package/esm2022/drag-and-drop/editing-services/drag-and-drop-asset.service.mjs +0 -48
- package/esm2022/drag-and-drop/editing-services/flat-editing.service.mjs +0 -141
- package/esm2022/drag-and-drop/editing-services/hierarchy-editing.service.mjs +0 -88
- package/esm2022/drag-and-drop/models/drop-action.mjs +0 -32
- package/esm2022/drag-and-drop/models/drop-position.mjs +0 -22
- package/esm2022/drag-and-drop/models/editing-service.mjs +0 -5
- package/esm2022/drag-and-drop/models/preventable-event.mjs +0 -25
- package/esm2022/drag-and-drop/models/scroll-direction.mjs +0 -12
- package/esm2022/drag-and-drop/models/scroll-settings.mjs +0 -5
- package/esm2022/drag-and-drop/models/tree-item-filter-state.mjs +0 -5
- package/esm2022/drag-and-drop/models/treeitem-add-remove-args.mjs +0 -5
- package/esm2022/drag-and-drop/models/treeitem-drag-event.mjs +0 -24
- package/esm2022/drag-and-drop/models/treeitem-drag-start-event.mjs +0 -25
- package/esm2022/drag-and-drop/models/treeitem-drop-event.mjs +0 -54
- package/esm2022/drag-and-drop/models.mjs +0 -14
- package/esm2022/expand-state.service.mjs +0 -24
- package/esm2022/expand.directive.mjs +0 -226
- package/esm2022/expandable-component.mjs +0 -19
- package/esm2022/filter-expand-settings.interface.mjs +0 -5
- package/esm2022/filter-state.interface.mjs +0 -5
- package/esm2022/filtering-base.mjs +0 -92
- package/esm2022/flat-binding.directive.mjs +0 -165
- package/esm2022/funcs.mjs +0 -9
- package/esm2022/hierarchy-binding.directive.mjs +0 -164
- package/esm2022/index-builder.service.mjs +0 -33
- package/esm2022/index.mjs +0 -31
- package/esm2022/load-more/load-more-button-template.directive.mjs +0 -41
- package/esm2022/load-more/load-more-request-args.mjs +0 -5
- package/esm2022/load-more/load-more-utils.mjs +0 -35
- package/esm2022/load-more/load-more.directive.mjs +0 -137
- package/esm2022/load-more/load-more.service.mjs +0 -5
- package/esm2022/loading-indicator.directive.mjs +0 -69
- package/esm2022/loading-notification.service.mjs +0 -21
- package/esm2022/localization/custom-messages.component.mjs +0 -54
- package/esm2022/localization/localized-messages.directive.mjs +0 -39
- package/esm2022/localization/messages.mjs +0 -27
- package/esm2022/navigation/navigation-item.interface.mjs +0 -5
- package/esm2022/navigation/navigation-model.mjs +0 -152
- package/esm2022/navigation/navigation-state.interface.mjs +0 -5
- package/esm2022/navigation/navigation.service.mjs +0 -248
- package/esm2022/node-children.service.mjs +0 -21
- package/esm2022/node-click-event.interface.mjs +0 -5
- package/esm2022/node-template.directive.mjs +0 -45
- package/esm2022/package-metadata.mjs +0 -16
- package/esm2022/progress-kendo-angular-treeview.mjs +0 -8
- package/esm2022/selection/select.directive.mjs +0 -174
- package/esm2022/selection/selectable-settings.mjs +0 -5
- package/esm2022/selection/selection-mode.mjs +0 -5
- package/esm2022/selection/selection.service.mjs +0 -33
- package/esm2022/size.mjs +0 -5
- package/esm2022/treeitem-lookup.interface.mjs +0 -5
- package/esm2022/treeitem.interface.mjs +0 -5
- package/esm2022/treeview-filter-settings.mjs +0 -12
- package/esm2022/treeview-group.component.mjs +0 -759
- package/esm2022/treeview-item-content.directive.mjs +0 -82
- package/esm2022/treeview-item.directive.mjs +0 -245
- package/esm2022/treeview-lookup.service.mjs +0 -89
- package/esm2022/treeview.component.mjs +0 -874
- package/esm2022/treeview.module.mjs +0 -74
- package/esm2022/utils.mjs +0 -301
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
/**-----------------------------------------------------------------------------------------
|
|
2
|
-
* Copyright © 2026 Progress Software Corporation. All rights reserved.
|
|
3
|
-
* Licensed under commercial license. See LICENSE.md in the project root for more information
|
|
4
|
-
*-------------------------------------------------------------------------------------------*/
|
|
5
|
-
import { Directive, Input } from '@angular/core';
|
|
6
|
-
import { Subscription } from 'rxjs';
|
|
7
|
-
import { TreeViewComponent } from '../treeview.component';
|
|
8
|
-
import { isPresent } from '../utils';
|
|
9
|
-
import * as i0 from "@angular/core";
|
|
10
|
-
import * as i1 from "../treeview.component";
|
|
11
|
-
/**
|
|
12
|
-
* Represents the directive that enables you to update the initially provided data array during drag-and-drop.
|
|
13
|
-
*
|
|
14
|
-
* Use this directive with one of the data-binding directives ([`kendoTreeViewHierarchyBinding`](slug:api_treeview_hierarchybindingdirective)
|
|
15
|
-
* or [`kendoTreeViewFlatDataBinding`](slug:api_treeview_flatdatabindingdirective)), which set their own edit handlers, or provide
|
|
16
|
-
* your own [`editService`](slug:api_treeview_editservice) to this directive.
|
|
17
|
-
*
|
|
18
|
-
* Providing a custom `editService` allows you to handle the
|
|
19
|
-
* [`addItem`](slug:api_treeview_treeviewcomponent#additem) and [`removeItem`](slug:api_treeview_treeviewcomponent#removeitem)
|
|
20
|
-
* events when they are triggered by the TreeView component.
|
|
21
|
-
*
|
|
22
|
-
* @example
|
|
23
|
-
* ```html
|
|
24
|
-
* <kendo-treeview
|
|
25
|
-
* kendoTreeViewDragAndDrop
|
|
26
|
-
* kendoTreeViewDragAndDropEditing
|
|
27
|
-
* [nodes]="nodes"
|
|
28
|
-
* textField="text">
|
|
29
|
-
* </kendo-treeview>
|
|
30
|
-
* ```
|
|
31
|
-
*
|
|
32
|
-
* @remarks
|
|
33
|
-
* Applied to: {@link TreeViewComponent}
|
|
34
|
-
*/
|
|
35
|
-
export class DragAndDropEditingDirective {
|
|
36
|
-
treeview;
|
|
37
|
-
/**
|
|
38
|
-
* Specifies the handlers called on drag-and-drop [`addItem`](slug:api_treeview_treeviewcomponent#additem)
|
|
39
|
-
* and [`removeItem`](slug:api_treeview_treeviewcomponent#removeitem) events.
|
|
40
|
-
*/
|
|
41
|
-
set editService(service) {
|
|
42
|
-
this.treeview.editService = service;
|
|
43
|
-
}
|
|
44
|
-
subscriptions = new Subscription();
|
|
45
|
-
constructor(treeview) {
|
|
46
|
-
this.treeview = treeview;
|
|
47
|
-
this.subscriptions.add(this.treeview.addItem.subscribe(this.handleAdd.bind(this)));
|
|
48
|
-
this.subscriptions.add(this.treeview.removeItem.subscribe(this.handleRemove.bind(this)));
|
|
49
|
-
}
|
|
50
|
-
ngOnDestroy() {
|
|
51
|
-
this.subscriptions.unsubscribe();
|
|
52
|
-
}
|
|
53
|
-
handleAdd(args) {
|
|
54
|
-
if (!isPresent(this.treeview.editService)) {
|
|
55
|
-
throw new Error('No `editService` provided. Either provide your own implementation or use this directive in combination with one of the data binding directives (`kendoTreeViewHierarchyBinding` or `kendoTreeViewFlatDataBinding`).');
|
|
56
|
-
}
|
|
57
|
-
this.treeview.editService.add(args);
|
|
58
|
-
}
|
|
59
|
-
handleRemove(args) {
|
|
60
|
-
if (!isPresent(this.treeview.editService)) {
|
|
61
|
-
throw new Error('No `editService` provided. Either provide your own implementation or use this directive in combination with one of the data binding directives (`kendoTreeViewHierarchyBinding` or `kendoTreeViewFlatDataBinding`).');
|
|
62
|
-
}
|
|
63
|
-
this.treeview.editService.remove(args);
|
|
64
|
-
}
|
|
65
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: DragAndDropEditingDirective, deps: [{ token: i1.TreeViewComponent }], target: i0.ɵɵFactoryTarget.Directive });
|
|
66
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.14", type: DragAndDropEditingDirective, isStandalone: true, selector: "[kendoTreeViewDragAndDropEditing]", inputs: { editService: "editService" }, ngImport: i0 });
|
|
67
|
-
}
|
|
68
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: DragAndDropEditingDirective, decorators: [{
|
|
69
|
-
type: Directive,
|
|
70
|
-
args: [{
|
|
71
|
-
selector: '[kendoTreeViewDragAndDropEditing]',
|
|
72
|
-
standalone: true
|
|
73
|
-
}]
|
|
74
|
-
}], ctorParameters: () => [{ type: i1.TreeViewComponent }], propDecorators: { editService: [{
|
|
75
|
-
type: Input
|
|
76
|
-
}] } });
|
|
@@ -1,270 +0,0 @@
|
|
|
1
|
-
/**-----------------------------------------------------------------------------------------
|
|
2
|
-
* Copyright © 2026 Progress Software Corporation. All rights reserved.
|
|
3
|
-
* Licensed under commercial license. See LICENSE.md in the project root for more information
|
|
4
|
-
*-------------------------------------------------------------------------------------------*/
|
|
5
|
-
import { isDocumentAvailable } from '@progress/kendo-angular-common';
|
|
6
|
-
import { isPresent, closestNode, closestWithMatch, hasParent, isContent, nodeId, getContentElement } from '../utils';
|
|
7
|
-
import { DropPosition, DropAction, ScrollDirection } from './models';
|
|
8
|
-
/**
|
|
9
|
-
* Checks if the browser supports relative stacking context.
|
|
10
|
-
* https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context
|
|
11
|
-
*/
|
|
12
|
-
const hasRelativeStackingContext = memoize(() => {
|
|
13
|
-
if (!(isDocumentAvailable() && isPresent(document.body))) {
|
|
14
|
-
return false;
|
|
15
|
-
}
|
|
16
|
-
const top = 10;
|
|
17
|
-
const parent = document.createElement("div");
|
|
18
|
-
parent.style.transform = "matrix(10, 0, 0, 10, 0, 0)";
|
|
19
|
-
const innerDiv = document.createElement('div');
|
|
20
|
-
innerDiv.innerText = 'child';
|
|
21
|
-
innerDiv.style.position = 'fixed';
|
|
22
|
-
innerDiv.style.top = `${top}px`;
|
|
23
|
-
parent.appendChild(innerDiv);
|
|
24
|
-
document.body.appendChild(parent);
|
|
25
|
-
const isDifferent = parent.children[0].getBoundingClientRect().top !== top;
|
|
26
|
-
document.body.removeChild(parent);
|
|
27
|
-
return isDifferent;
|
|
28
|
-
});
|
|
29
|
-
/**
|
|
30
|
-
* Stores the result of the passed function's first invokation and returns it instead of invoking it again afterwards.
|
|
31
|
-
*/
|
|
32
|
-
function memoize(fn) {
|
|
33
|
-
let result;
|
|
34
|
-
let called = false;
|
|
35
|
-
return (...args) => {
|
|
36
|
-
if (called) {
|
|
37
|
-
return result;
|
|
38
|
-
}
|
|
39
|
-
result = fn(...args);
|
|
40
|
-
called = true;
|
|
41
|
-
return result;
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* @hidden
|
|
46
|
-
*
|
|
47
|
-
* Gets the offset of the parent element if the latter has the `transform` CSS prop applied.
|
|
48
|
-
* Transformed parents create new stacking context and the `fixed` children must be position based on the transformed parent.
|
|
49
|
-
* https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context
|
|
50
|
-
*
|
|
51
|
-
* If no parent container is `transform`-ed the function will return `{ left: 0, top: 0 }`;
|
|
52
|
-
*/
|
|
53
|
-
export const getContainerOffset = (element) => {
|
|
54
|
-
if (!(element && hasRelativeStackingContext())) {
|
|
55
|
-
return { left: 0, top: 0 };
|
|
56
|
-
}
|
|
57
|
-
let offsetParent = element.parentElement;
|
|
58
|
-
while (offsetParent) {
|
|
59
|
-
if (window.getComputedStyle(offsetParent).transform !== 'none') {
|
|
60
|
-
break;
|
|
61
|
-
}
|
|
62
|
-
offsetParent = offsetParent.parentElement;
|
|
63
|
-
}
|
|
64
|
-
if (offsetParent) {
|
|
65
|
-
const rect = offsetParent.getBoundingClientRect();
|
|
66
|
-
return {
|
|
67
|
-
left: rect.left - offsetParent.scrollLeft,
|
|
68
|
-
top: rect.top - offsetParent.scrollTop
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
return { left: 0, top: 0 };
|
|
72
|
-
};
|
|
73
|
-
/**
|
|
74
|
-
* @hidden
|
|
75
|
-
*/
|
|
76
|
-
export const getDropAction = (dropPosition, dropTarget) => {
|
|
77
|
-
if (!(isPresent(dropPosition) && isPresent(dropTarget))) {
|
|
78
|
-
return DropAction.Invalid;
|
|
79
|
-
}
|
|
80
|
-
switch (dropPosition) {
|
|
81
|
-
case DropPosition.Over:
|
|
82
|
-
return DropAction.Add;
|
|
83
|
-
case DropPosition.Before:
|
|
84
|
-
return isPresent(closestNode(dropTarget).previousElementSibling) ? DropAction.InsertMiddle : DropAction.InsertTop;
|
|
85
|
-
case DropPosition.After:
|
|
86
|
-
return isPresent(closestNode(dropTarget).nextElementSibling) ? DropAction.InsertMiddle : DropAction.InsertBottom;
|
|
87
|
-
default:
|
|
88
|
-
return DropAction.Invalid;
|
|
89
|
-
}
|
|
90
|
-
};
|
|
91
|
-
/**
|
|
92
|
-
* @hidden
|
|
93
|
-
*/
|
|
94
|
-
export const getDropPosition = (draggedItem, target, clientY, targetTreeView, containerOffset) => {
|
|
95
|
-
if (!(isPresent(draggedItem) && isPresent(target) && isPresent(targetTreeView) && isPresent(containerOffset))) {
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
// the .k-treeview-mid element starts just after the checkbox/expand arrow and stretches till the end of the treeview on the right
|
|
99
|
-
const item = closestWithMatch(target, '.k-treeview-top, .k-treeview-mid, .k-treeview-bot');
|
|
100
|
-
if (!isPresent(item)) {
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
// the content element (.k-treeview-leaf:not(.k-treeview-load-more-button)) holds just the treeview item text
|
|
104
|
-
const content = getContentElement(item);
|
|
105
|
-
const targetChildOfDraggedItem = hasParent(item, closestNode(draggedItem));
|
|
106
|
-
if (!isPresent(content) || (content === draggedItem) || targetChildOfDraggedItem) {
|
|
107
|
-
return;
|
|
108
|
-
}
|
|
109
|
-
const itemViewPortCoords = content.getBoundingClientRect();
|
|
110
|
-
/*
|
|
111
|
-
if the user is hovering a treeview item, split the item height into four parts:
|
|
112
|
-
- dropping into the top quarter should insert the dragged item before the drop target
|
|
113
|
-
- dropping into the bottom quarter should insert the dragged item after the drop target
|
|
114
|
-
- dropping into the second or third quarter should add the item as child node of the drop target
|
|
115
|
-
|
|
116
|
-
if the user is NOT hovering a treeview item (he's dragging somewhere on the right), split the item height to just two parts:
|
|
117
|
-
- dropping should insert before or after
|
|
118
|
-
*/
|
|
119
|
-
const itemDivisionHeight = itemViewPortCoords.height / (isContent(target) ? 4 : 2);
|
|
120
|
-
// clear any possible container offset created by parent elements with `transform` css property set
|
|
121
|
-
const pointerPosition = clientY - containerOffset.top;
|
|
122
|
-
const itemTop = itemViewPortCoords.top - containerOffset.top;
|
|
123
|
-
if (pointerPosition < itemTop + itemDivisionHeight) {
|
|
124
|
-
return DropPosition.Before;
|
|
125
|
-
}
|
|
126
|
-
if (pointerPosition >= itemTop + itemViewPortCoords.height - itemDivisionHeight) {
|
|
127
|
-
return DropPosition.After;
|
|
128
|
-
}
|
|
129
|
-
return DropPosition.Over;
|
|
130
|
-
};
|
|
131
|
-
/**
|
|
132
|
-
* @hidden
|
|
133
|
-
*/
|
|
134
|
-
export const treeItemFromEventTarget = (treeView, dropTarget) => {
|
|
135
|
-
if (!(isPresent(treeView) && isPresent(dropTarget))) {
|
|
136
|
-
return null;
|
|
137
|
-
}
|
|
138
|
-
const node = closestNode(dropTarget);
|
|
139
|
-
const index = nodeId(node);
|
|
140
|
-
const lookup = treeView.itemLookup(index);
|
|
141
|
-
if (!(isPresent(lookup) && isPresent(lookup.item.dataItem))) {
|
|
142
|
-
return null;
|
|
143
|
-
}
|
|
144
|
-
return lookup;
|
|
145
|
-
};
|
|
146
|
-
/**
|
|
147
|
-
* @hidden
|
|
148
|
-
*
|
|
149
|
-
* Emits `collapse` on the specified TreeView node if the latter is left empty after its last child node was dragged out.
|
|
150
|
-
*/
|
|
151
|
-
export const collapseEmptyParent = (parent, parentNodes, treeview) => {
|
|
152
|
-
if (isPresent(parent) && parentNodes.length === 0 && treeview.isExpanded(parent.item.dataItem, parent.item.index)) {
|
|
153
|
-
treeview.collapseNode(parent.item.dataItem, parent.item.index);
|
|
154
|
-
}
|
|
155
|
-
};
|
|
156
|
-
/**
|
|
157
|
-
* @hidden
|
|
158
|
-
*
|
|
159
|
-
* Expands the node if it's dropped into and it's not yet expanded.
|
|
160
|
-
*/
|
|
161
|
-
export const expandDropTarget = (dropTarget, treeView) => {
|
|
162
|
-
if (!treeView.isExpanded(dropTarget.item.dataItem, dropTarget.item.index)) {
|
|
163
|
-
treeView.expandNode(dropTarget.item.dataItem, dropTarget.item.index);
|
|
164
|
-
}
|
|
165
|
-
};
|
|
166
|
-
/**
|
|
167
|
-
* @hidden
|
|
168
|
-
*
|
|
169
|
-
* Extracts the event target from the viewport coords. Required for touch devices
|
|
170
|
-
* where the `event.target` of a `pointermove` event is always the initially dragged item.
|
|
171
|
-
*/
|
|
172
|
-
export const getDropTarget = (event) => {
|
|
173
|
-
if (!(isDocumentAvailable() && isPresent(document.elementFromPoint))) {
|
|
174
|
-
return event.target;
|
|
175
|
-
}
|
|
176
|
-
return document.elementFromPoint(event.clientX, event.clientY);
|
|
177
|
-
};
|
|
178
|
-
/**
|
|
179
|
-
* @hidden
|
|
180
|
-
*
|
|
181
|
-
* Checks if the original index is before the new one and corrects the new one by decrementing the index for the level, where the original item stood.
|
|
182
|
-
*/
|
|
183
|
-
export const updateMovedItemIndex = (newIndex, originalIndex) => {
|
|
184
|
-
const movedItemNewIndexParts = newIndex.split('_');
|
|
185
|
-
const originalItemIndexParts = originalIndex.split('_');
|
|
186
|
-
// if the original item was moved from a deeper level, there's no need for index correction
|
|
187
|
-
// e.g. 4_0_1 is moved to 5_0 => removing 4_0_1 will not cause 5_0 to be moved
|
|
188
|
-
if (movedItemNewIndexParts.length < originalItemIndexParts.length) {
|
|
189
|
-
return newIndex;
|
|
190
|
-
}
|
|
191
|
-
// check if the parent item paths are the same - index correction is not required when the original item path differs from the path of the moved item - they belong to different hierarchies
|
|
192
|
-
// e.g. 4_1 is moved to 5_1 - the parent item paths are differen (4 compared to 5) => removing 4_1 will not cause 5_1 to be moved
|
|
193
|
-
// e.g 4_1 is moved to 4_3 - the parent paths are the same (both 4) => removing 4_1 will cause 4_3 to be moved
|
|
194
|
-
const originalItemParentPathLength = originalItemIndexParts.length - 1;
|
|
195
|
-
const originalItemParentPath = originalItemIndexParts.slice(0, originalItemParentPathLength).join('_');
|
|
196
|
-
const movedItemParentPath = movedItemNewIndexParts.slice(0, originalItemParentPathLength).join('_');
|
|
197
|
-
// check if the the index of the level where the original item is taken from is greater than the one of the moved item
|
|
198
|
-
// e.g. 4_5 is moved to 4_1 (comapre 5 and 1) => removing 4_5 will not cause 4_1 to be moved
|
|
199
|
-
// e.g. 4_1 is moved to 4_5 (comapre 1 and 5) => removing 4_1 will cause 4_5 to be moved
|
|
200
|
-
const originalItemIndexLevel = originalItemIndexParts.length - 1;
|
|
201
|
-
const originalItemLevelIndex = Number(originalItemIndexParts[originalItemIndexLevel]);
|
|
202
|
-
const movedItemLevelIndex = Number(movedItemNewIndexParts[originalItemIndexLevel]);
|
|
203
|
-
if ((originalItemParentPath === movedItemParentPath) && (movedItemLevelIndex > originalItemLevelIndex)) {
|
|
204
|
-
// if the removed item causes the dropped item to be moved a position up - decrement the index at that level
|
|
205
|
-
movedItemNewIndexParts[originalItemIndexLevel] = String(movedItemLevelIndex - 1);
|
|
206
|
-
return movedItemNewIndexParts.join('_');
|
|
207
|
-
}
|
|
208
|
-
return newIndex;
|
|
209
|
-
};
|
|
210
|
-
/**
|
|
211
|
-
* @hidden
|
|
212
|
-
*/
|
|
213
|
-
const SCROLLBAR_REG_EXP = new RegExp('(auto|scroll)');
|
|
214
|
-
/**
|
|
215
|
-
* @hidden
|
|
216
|
-
*
|
|
217
|
-
* Retrives the first scrollable element starting the search from the provided one, traversing to the top of the DOM tree.
|
|
218
|
-
*/
|
|
219
|
-
export const getScrollableContainer = (node) => {
|
|
220
|
-
while (isPresent(node) && node.nodeName !== 'HTML') {
|
|
221
|
-
const hasOverflow = node.scrollHeight > node.clientHeight;
|
|
222
|
-
const hasScrollbar = SCROLLBAR_REG_EXP.test(getComputedStyle(node).overflowY);
|
|
223
|
-
if (hasOverflow && hasScrollbar) {
|
|
224
|
-
return node;
|
|
225
|
-
}
|
|
226
|
-
node = node.parentNode;
|
|
227
|
-
}
|
|
228
|
-
return node;
|
|
229
|
-
};
|
|
230
|
-
/**
|
|
231
|
-
* @hidden
|
|
232
|
-
*
|
|
233
|
-
* Checks if the top of the scrollable element is reached.
|
|
234
|
-
* Floors the scrollTop value.
|
|
235
|
-
*/
|
|
236
|
-
const isTopReached = (element) => Math.floor(element.scrollTop) <= 0;
|
|
237
|
-
/**
|
|
238
|
-
* @hidden
|
|
239
|
-
*
|
|
240
|
-
* Checks if the bottom of the scrollable element is reached.
|
|
241
|
-
* Ceils the scrollTop value.
|
|
242
|
-
*/
|
|
243
|
-
const isBottomReached = (element) => Math.ceil(element.scrollTop) >= element.scrollHeight - element.clientHeight;
|
|
244
|
-
/**
|
|
245
|
-
* @hidden
|
|
246
|
-
*
|
|
247
|
-
* Scrolls the element in the given direction by the provided step.
|
|
248
|
-
*
|
|
249
|
-
* If the targeted scroll incrementation doesn't yield any result due to device pixel ratio issues (https://github.com/dimitar-pechev/RenderingIndependentScrollOffsets#readme),
|
|
250
|
-
* increments the step with 1px and again attempts to change the scrollTop of the element, until the content is actually scrolled.
|
|
251
|
-
*
|
|
252
|
-
* Cuts the operation short after 20 unsuccessful attempts to prevent infinite loops in possible corner-case scenarios.
|
|
253
|
-
*/
|
|
254
|
-
export const scrollElementBy = (element, step, direction) => {
|
|
255
|
-
if (!(isPresent(element) && isDocumentAvailable())) {
|
|
256
|
-
return;
|
|
257
|
-
}
|
|
258
|
-
const initialScrollTop = element.scrollTop;
|
|
259
|
-
let currentStep = step;
|
|
260
|
-
let iterations = 0;
|
|
261
|
-
while (initialScrollTop === element.scrollTop &&
|
|
262
|
-
!(direction === ScrollDirection.Up && isTopReached(element)) &&
|
|
263
|
-
!(direction === ScrollDirection.Down && isBottomReached(element)) &&
|
|
264
|
-
iterations < 20 // as the bulgarian saying goes - to ties our underpants
|
|
265
|
-
) {
|
|
266
|
-
element.scrollTop += (currentStep * direction);
|
|
267
|
-
currentStep += 1;
|
|
268
|
-
iterations += 1;
|
|
269
|
-
}
|
|
270
|
-
};
|