@limble/limble-tree 0.12.4 → 1.0.0-alpha.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/README.md +42 -149
- package/esm2020/lib/components/branch/branch.component.mjs +87 -0
- package/esm2020/lib/components/dropzone/dropzone.component.mjs +35 -0
- package/esm2020/lib/components/host-component.interface.mjs +2 -0
- package/esm2020/lib/components/node-component.interface.mjs +2 -0
- package/esm2020/lib/components/root/root.component.mjs +37 -0
- package/esm2020/lib/core/branch-options.interface.mjs +2 -0
- package/esm2020/lib/core/configuration/configuration.mjs +17 -0
- package/esm2020/lib/core/configuration/tree-options.interface.mjs +2 -0
- package/esm2020/lib/core/index.mjs +6 -0
- package/esm2020/lib/core/relationship.interface.mjs +2 -0
- package/esm2020/lib/core/tree-branch/tree-branch.mjs +246 -0
- package/esm2020/lib/core/tree-node-base.mjs +68 -0
- package/esm2020/lib/core/tree-root/tree-root.mjs +69 -0
- package/esm2020/lib/core/tree-service/tree.service.mjs +19 -0
- package/esm2020/lib/errors/index.mjs +2 -0
- package/esm2020/lib/errors/tree-error.mjs +3 -0
- package/esm2020/lib/events/drag/drag-end-event.mjs +28 -0
- package/esm2020/lib/events/drag/drag-start-event.mjs +12 -0
- package/esm2020/lib/events/drag/drop-event.mjs +20 -0
- package/esm2020/lib/events/drag/index.mjs +4 -0
- package/esm2020/lib/events/index.mjs +3 -0
- package/esm2020/lib/events/relational/graft-event.mjs +24 -0
- package/esm2020/lib/events/relational/index.mjs +4 -0
- package/esm2020/lib/events/relational/prune-event.mjs +24 -0
- package/esm2020/lib/events/relational/relational-tree-event.interface.mjs +2 -0
- package/esm2020/lib/extras/collapse/collapse.mjs +33 -0
- package/esm2020/lib/extras/collapse/collapse.module.mjs +15 -0
- package/esm2020/lib/extras/collapse/collapse.service.mjs +20 -0
- package/esm2020/lib/extras/collapse/index.mjs +3 -0
- package/esm2020/lib/extras/drag-and-drop/drag-and-drop.mjs +89 -0
- package/esm2020/lib/extras/drag-and-drop/drag-and-drop.module.mjs +19 -0
- package/esm2020/lib/extras/drag-and-drop/drag-and-drop.service.mjs +28 -0
- package/esm2020/lib/extras/drag-and-drop/drag-state.mjs +47 -0
- package/esm2020/lib/extras/drag-and-drop/draggable.directive.mjs +30 -0
- package/esm2020/lib/extras/drag-and-drop/dragover-no-change-detect.mjs +40 -0
- package/esm2020/lib/extras/drag-and-drop/dropzone-renderer.mjs +176 -0
- package/esm2020/lib/extras/drag-and-drop/index.mjs +5 -0
- package/esm2020/lib/legacy/index.mjs +7 -0
- package/esm2020/lib/legacy/legacy-component-obj.interface.mjs +2 -0
- package/esm2020/lib/legacy/legacy-tree-data.interface.mjs +2 -0
- package/esm2020/lib/legacy/legacy-tree-options.interface.mjs +2 -0
- package/esm2020/lib/legacy/legacy-tree.mjs +74 -0
- package/esm2020/lib/legacy/limble-tree-legacy.module.mjs +20 -0
- package/esm2020/lib/legacy/limble-tree-root/limble-tree-root.component.mjs +78 -0
- package/esm2020/lib/limble-tree.module.mjs +21 -0
- package/esm2020/lib/structure/branchable.interface.mjs +2 -0
- package/esm2020/lib/structure/container-tree-node.interface.mjs +2 -0
- package/esm2020/lib/structure/content-container.interface.mjs +2 -0
- package/esm2020/lib/structure/event-conduit.interface.mjs +2 -0
- package/esm2020/lib/structure/graftable.interface.mjs +2 -0
- package/esm2020/lib/structure/index.mjs +12 -0
- package/esm2020/lib/structure/tree-branch-node.interface.mjs +2 -0
- package/esm2020/lib/structure/tree-event.interface.mjs +2 -0
- package/esm2020/lib/structure/tree-node.interface.mjs +2 -0
- package/esm2020/lib/structure/tree-plot.mjs +2 -0
- package/esm2020/lib/structure/tree-relationship.interface.mjs +2 -0
- package/esm2020/lib/structure/tree-root.node.interface.mjs +2 -0
- package/{esm2015/limble-limble-tree.js → esm2020/limble-limble-tree.mjs} +4 -4
- package/esm2020/public-api.mjs +12 -0
- package/esm2020/shared/assert.mjs +7 -0
- package/fesm2015/limble-limble-tree.mjs +1310 -0
- package/fesm2015/limble-limble-tree.mjs.map +1 -0
- package/fesm2020/limble-limble-tree.mjs +1300 -0
- package/fesm2020/limble-limble-tree.mjs.map +1 -0
- package/{limble-limble-tree.d.ts → index.d.ts} +5 -5
- package/lib/components/branch/branch.component.d.ts +26 -0
- package/lib/components/dropzone/dropzone.component.d.ts +13 -0
- package/lib/components/host-component.interface.d.ts +6 -0
- package/lib/components/node-component.interface.d.ts +5 -0
- package/lib/components/root/root.component.d.ts +14 -0
- package/lib/core/branch-options.interface.d.ts +14 -0
- package/lib/core/configuration/configuration.d.ts +11 -0
- package/lib/core/configuration/tree-options.interface.d.ts +35 -0
- package/lib/core/index.d.ts +5 -0
- package/lib/core/relationship.interface.d.ts +6 -0
- package/lib/core/tree-branch/tree-branch.d.ts +44 -0
- package/lib/core/tree-node-base.d.ts +26 -0
- package/lib/core/tree-root/tree-root.d.ts +28 -0
- package/lib/core/tree-service/tree.service.d.ts +9 -0
- package/lib/errors/index.d.ts +1 -0
- package/lib/errors/tree-error.d.ts +2 -0
- package/lib/events/drag/drag-end-event.d.ts +25 -0
- package/lib/events/drag/drag-start-event.d.ts +8 -0
- package/lib/events/drag/drop-event.d.ts +16 -0
- package/lib/events/drag/index.d.ts +3 -0
- package/lib/events/index.d.ts +2 -0
- package/lib/events/relational/graft-event.d.ts +15 -0
- package/lib/events/relational/index.d.ts +3 -0
- package/lib/events/relational/prune-event.d.ts +15 -0
- package/lib/events/relational/relational-tree-event.interface.d.ts +6 -0
- package/lib/extras/collapse/collapse.d.ts +11 -0
- package/lib/extras/collapse/collapse.module.d.ts +6 -0
- package/lib/extras/collapse/collapse.service.d.ts +9 -0
- package/lib/extras/collapse/index.d.ts +2 -0
- package/lib/extras/drag-and-drop/drag-and-drop.d.ts +17 -0
- package/lib/extras/drag-and-drop/drag-and-drop.module.d.ts +8 -0
- package/lib/extras/drag-and-drop/drag-and-drop.service.d.ts +16 -0
- package/lib/extras/drag-and-drop/drag-state.d.ts +23 -0
- package/lib/extras/drag-and-drop/draggable.directive.d.ts +12 -0
- package/lib/{custom-event-bindings/dragover-no-change-detect.directive.d.ts → extras/drag-and-drop/dragover-no-change-detect.d.ts} +14 -14
- package/lib/extras/drag-and-drop/dropzone-renderer.d.ts +28 -0
- package/lib/extras/drag-and-drop/index.d.ts +4 -0
- package/lib/legacy/index.d.ts +6 -0
- package/lib/legacy/legacy-component-obj.interface.d.ts +13 -0
- package/lib/legacy/legacy-tree-data.interface.d.ts +18 -0
- package/lib/legacy/legacy-tree-options.interface.d.ts +34 -0
- package/lib/legacy/legacy-tree.d.ts +14 -0
- package/lib/legacy/limble-tree-legacy.module.d.ts +8 -0
- package/lib/legacy/limble-tree-root/limble-tree-root.component.d.ts +28 -0
- package/lib/limble-tree.module.d.ts +9 -14
- package/lib/structure/branchable.interface.d.ts +5 -0
- package/lib/structure/container-tree-node.interface.d.ts +3 -0
- package/lib/structure/content-container.interface.d.ts +3 -0
- package/lib/structure/event-conduit.interface.d.ts +6 -0
- package/lib/structure/graftable.interface.d.ts +6 -0
- package/lib/structure/index.d.ts +11 -0
- package/lib/structure/tree-branch-node.interface.d.ts +5 -0
- package/lib/structure/tree-event.interface.d.ts +5 -0
- package/lib/structure/tree-node.interface.d.ts +9 -0
- package/lib/structure/tree-plot.d.ts +1 -0
- package/lib/structure/tree-relationship.interface.d.ts +7 -0
- package/lib/structure/tree-root.node.interface.d.ts +2 -0
- package/package.json +24 -19
- package/public-api.d.ts +8 -3
- package/shared/assert.d.ts +1 -0
- package/bundles/limble-limble-tree.umd.js +0 -2910
- package/bundles/limble-limble-tree.umd.js.map +0 -1
- package/esm2015/lib/classes/Branch.js +0 -153
- package/esm2015/lib/classes/DropZone.js +0 -71
- package/esm2015/lib/classes/DropZoneLocation.js +0 -16
- package/esm2015/lib/custom-event-bindings/dragleave-no-change-detect.directive.js +0 -33
- package/esm2015/lib/custom-event-bindings/dragover-no-change-detect.directive.js +0 -39
- package/esm2015/lib/drop-zone/drop-zone.component.js +0 -81
- package/esm2015/lib/limble-tree-branch/limble-tree-branch.component.js +0 -116
- package/esm2015/lib/limble-tree-node/limble-tree-node.component.js +0 -484
- package/esm2015/lib/limble-tree-placeholder/limble-tree-placeholder.component.js +0 -75
- package/esm2015/lib/limble-tree-root/drop-zone.service.js +0 -377
- package/esm2015/lib/limble-tree-root/limble-tree-root.component.js +0 -178
- package/esm2015/lib/limble-tree-root/tree-construction-status.service.js +0 -33
- package/esm2015/lib/limble-tree-root/tree.service.js +0 -301
- package/esm2015/lib/limble-tree.module.js +0 -47
- package/esm2015/lib/singletons/component-creator.service.js +0 -19
- package/esm2015/lib/singletons/drag-state.service.js +0 -64
- package/esm2015/lib/singletons/global-events.service.js +0 -137
- package/esm2015/lib/util.js +0 -74
- package/esm2015/public-api.js +0 -6
- package/fesm2015/limble-limble-tree.js +0 -2209
- package/fesm2015/limble-limble-tree.js.map +0 -1
- package/lib/classes/Branch.d.ts +0 -26
- package/lib/classes/DropZone.d.ts +0 -27
- package/lib/classes/DropZoneLocation.d.ts +0 -9
- package/lib/custom-event-bindings/dragleave-no-change-detect.directive.d.ts +0 -13
- package/lib/drop-zone/drop-zone.component.d.ts +0 -18
- package/lib/limble-tree-branch/limble-tree-branch.component.d.ts +0 -28
- package/lib/limble-tree-node/limble-tree-node.component.d.ts +0 -53
- package/lib/limble-tree-placeholder/limble-tree-placeholder.component.d.ts +0 -21
- package/lib/limble-tree-root/drop-zone.service.d.ts +0 -62
- package/lib/limble-tree-root/limble-tree-root.component.d.ts +0 -37
- package/lib/limble-tree-root/tree-construction-status.service.d.ts +0 -15
- package/lib/limble-tree-root/tree.service.d.ts +0 -132
- package/lib/singletons/component-creator.service.d.ts +0 -9
- package/lib/singletons/drag-state.service.d.ts +0 -35
- package/lib/singletons/global-events.service.d.ts +0 -13
- package/lib/util.d.ts +0 -13
|
@@ -0,0 +1,1300 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { Injectable, NgModule, EventEmitter, Directive, Input, Output, Component, NgZone, ViewContainerRef, ViewChild, ViewChildren, createComponent, EnvironmentInjector, HostListener } from '@angular/core';
|
|
3
|
+
import { BehaviorSubject, Subject, fromEvent, merge, map, filter, first } from 'rxjs';
|
|
4
|
+
import * as i1 from '@angular/common';
|
|
5
|
+
import { CommonModule } from '@angular/common';
|
|
6
|
+
import { throttleTime } from 'rxjs/operators';
|
|
7
|
+
|
|
8
|
+
class TreeCollapser {
|
|
9
|
+
constructor() {
|
|
10
|
+
this.tempStorage = new Map();
|
|
11
|
+
}
|
|
12
|
+
collapse(treeBranch) {
|
|
13
|
+
if (treeBranch.branches().length === 0)
|
|
14
|
+
return;
|
|
15
|
+
const branches = [];
|
|
16
|
+
this.tempStorage.set(treeBranch, branches);
|
|
17
|
+
treeBranch.branches().forEach((branch) => {
|
|
18
|
+
branch.prune();
|
|
19
|
+
branches.push(branch);
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
expand(treeBranch) {
|
|
23
|
+
const branches = this.tempStorage.get(treeBranch);
|
|
24
|
+
if (branches === undefined)
|
|
25
|
+
return;
|
|
26
|
+
branches.forEach((branch) => {
|
|
27
|
+
branch.graftTo(treeBranch);
|
|
28
|
+
});
|
|
29
|
+
this.tempStorage.delete(treeBranch);
|
|
30
|
+
treeBranch.getContents().changeDetectorRef.detectChanges();
|
|
31
|
+
}
|
|
32
|
+
isCollapsed(treeBranch) {
|
|
33
|
+
return this.tempStorage.has(treeBranch);
|
|
34
|
+
}
|
|
35
|
+
storePrecollapsedNode(parent, branch) {
|
|
36
|
+
this.tempStorage.set(parent, (this.tempStorage.get(parent) ?? []).concat(branch));
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
const treeCollapser = new TreeCollapser();
|
|
40
|
+
|
|
41
|
+
class TreeCollapseService {
|
|
42
|
+
collapse(treeBranch) {
|
|
43
|
+
treeCollapser.collapse(treeBranch);
|
|
44
|
+
}
|
|
45
|
+
expand(treeBranch) {
|
|
46
|
+
treeCollapser.expand(treeBranch);
|
|
47
|
+
}
|
|
48
|
+
isCollapsed(treeBranch) {
|
|
49
|
+
return treeCollapser.isCollapsed(treeBranch);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
TreeCollapseService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: TreeCollapseService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
53
|
+
TreeCollapseService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: TreeCollapseService });
|
|
54
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: TreeCollapseService, decorators: [{
|
|
55
|
+
type: Injectable
|
|
56
|
+
}] });
|
|
57
|
+
|
|
58
|
+
class TreeCollapseModule {
|
|
59
|
+
}
|
|
60
|
+
TreeCollapseModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: TreeCollapseModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
61
|
+
TreeCollapseModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.2.12", ngImport: i0, type: TreeCollapseModule });
|
|
62
|
+
TreeCollapseModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: TreeCollapseModule, providers: [TreeCollapseService] });
|
|
63
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: TreeCollapseModule, decorators: [{
|
|
64
|
+
type: NgModule,
|
|
65
|
+
args: [{
|
|
66
|
+
providers: [TreeCollapseService]
|
|
67
|
+
}]
|
|
68
|
+
}] });
|
|
69
|
+
|
|
70
|
+
class Configuration {
|
|
71
|
+
constructor() {
|
|
72
|
+
this.configStorage = new Map();
|
|
73
|
+
this.configStorage = new Map();
|
|
74
|
+
}
|
|
75
|
+
setConfig(root, options) {
|
|
76
|
+
this.configStorage.set(root, options);
|
|
77
|
+
}
|
|
78
|
+
getConfig(root) {
|
|
79
|
+
return this.configStorage.get(root);
|
|
80
|
+
}
|
|
81
|
+
delete(root) {
|
|
82
|
+
this.configStorage.delete(root);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
const config = new Configuration();
|
|
86
|
+
|
|
87
|
+
class TreeError extends Error {
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
class DragEndEvent {
|
|
91
|
+
constructor(source, endpoints) {
|
|
92
|
+
this._source = source;
|
|
93
|
+
this._oldParent = endpoints.oldParent;
|
|
94
|
+
this._oldIndex = endpoints.oldIndex;
|
|
95
|
+
this._newParent = endpoints.newParent;
|
|
96
|
+
this._newIndex = endpoints.newIndex;
|
|
97
|
+
}
|
|
98
|
+
type() {
|
|
99
|
+
return "drag end";
|
|
100
|
+
}
|
|
101
|
+
source() {
|
|
102
|
+
return this._source;
|
|
103
|
+
}
|
|
104
|
+
newIndex() {
|
|
105
|
+
return this._newIndex;
|
|
106
|
+
}
|
|
107
|
+
newParent() {
|
|
108
|
+
return this._newParent;
|
|
109
|
+
}
|
|
110
|
+
oldIndex() {
|
|
111
|
+
return this._oldIndex;
|
|
112
|
+
}
|
|
113
|
+
oldParent() {
|
|
114
|
+
return this._oldParent;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
class DragStartEvent {
|
|
119
|
+
constructor(source) {
|
|
120
|
+
this._source = source;
|
|
121
|
+
}
|
|
122
|
+
type() {
|
|
123
|
+
return "drag start";
|
|
124
|
+
}
|
|
125
|
+
source() {
|
|
126
|
+
return this._source;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function assert(condition) {
|
|
131
|
+
if (condition) {
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
throw new Error("Assertion Failed!");
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
var DragStates;
|
|
138
|
+
(function (DragStates) {
|
|
139
|
+
DragStates[DragStates["Idle"] = 0] = "Idle";
|
|
140
|
+
DragStates[DragStates["Starting"] = 1] = "Starting";
|
|
141
|
+
DragStates[DragStates["Dragging"] = 2] = "Dragging";
|
|
142
|
+
DragStates[DragStates["Dropped"] = 3] = "Dropped";
|
|
143
|
+
})(DragStates || (DragStates = {}));
|
|
144
|
+
class DragState {
|
|
145
|
+
constructor() {
|
|
146
|
+
this._state = DragStates.Idle;
|
|
147
|
+
this.state$ = new BehaviorSubject(DragStates.Idle);
|
|
148
|
+
this.state$.subscribe((state) => {
|
|
149
|
+
this._state = state;
|
|
150
|
+
});
|
|
151
|
+
this.dragData = undefined;
|
|
152
|
+
}
|
|
153
|
+
getDragData() {
|
|
154
|
+
return this.dragData;
|
|
155
|
+
}
|
|
156
|
+
starting(treeBranch) {
|
|
157
|
+
assert(this._state === DragStates.Idle);
|
|
158
|
+
this.dragData = treeBranch;
|
|
159
|
+
this.state$.next(DragStates.Starting);
|
|
160
|
+
}
|
|
161
|
+
dragging() {
|
|
162
|
+
assert(this._state === DragStates.Starting);
|
|
163
|
+
this.state$.next(DragStates.Dragging);
|
|
164
|
+
}
|
|
165
|
+
dropped() {
|
|
166
|
+
assert(this._state === DragStates.Dragging);
|
|
167
|
+
this.state$.next(DragStates.Dropped);
|
|
168
|
+
}
|
|
169
|
+
restart() {
|
|
170
|
+
this.dragData = undefined;
|
|
171
|
+
this.state$.next(DragStates.Idle);
|
|
172
|
+
}
|
|
173
|
+
events() {
|
|
174
|
+
return this.state$;
|
|
175
|
+
}
|
|
176
|
+
state() {
|
|
177
|
+
return this._state;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
const dragState = new DragState();
|
|
181
|
+
|
|
182
|
+
class DropEvent {
|
|
183
|
+
constructor(source, parent, index) {
|
|
184
|
+
this._source = source;
|
|
185
|
+
this._parent = parent;
|
|
186
|
+
this._index = index;
|
|
187
|
+
}
|
|
188
|
+
type() {
|
|
189
|
+
return "drag end";
|
|
190
|
+
}
|
|
191
|
+
source() {
|
|
192
|
+
return this._source;
|
|
193
|
+
}
|
|
194
|
+
index() {
|
|
195
|
+
return this._index;
|
|
196
|
+
}
|
|
197
|
+
parent() {
|
|
198
|
+
return this._parent;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
class DragAndDrop {
|
|
203
|
+
constructor() {
|
|
204
|
+
this.dragAborted$ = new Subject();
|
|
205
|
+
}
|
|
206
|
+
dragStart(treeBranch, event) {
|
|
207
|
+
if (!this.draggingAllowed(treeBranch)) {
|
|
208
|
+
event.preventDefault();
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
treeBranch.dispatch(new DragStartEvent(treeBranch));
|
|
212
|
+
this.setDragEffects(treeBranch, event);
|
|
213
|
+
this.watchForDragend(treeBranch, event);
|
|
214
|
+
// We have to do a setTimeout because DOM changes are not allowed during a
|
|
215
|
+
// dragstart event.
|
|
216
|
+
setTimeout(() => {
|
|
217
|
+
dragState.starting(treeBranch);
|
|
218
|
+
treeBranch.prune();
|
|
219
|
+
dragState.dragging();
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
drop(parent, index) {
|
|
223
|
+
const treeBranch = dragState.getDragData();
|
|
224
|
+
if (treeBranch === undefined) {
|
|
225
|
+
throw new TreeError("Cannot get dragged branch");
|
|
226
|
+
}
|
|
227
|
+
this.graftDraggedBranch(treeBranch, parent, index);
|
|
228
|
+
treeBranch.dispatch(new DropEvent(treeBranch, parent, index));
|
|
229
|
+
}
|
|
230
|
+
getDragImageOffsets(event, element) {
|
|
231
|
+
const bounds = element.getBoundingClientRect();
|
|
232
|
+
const xOffset = event.clientX - bounds.left;
|
|
233
|
+
const yOffset = event.clientY - bounds.top;
|
|
234
|
+
return [xOffset, yOffset];
|
|
235
|
+
}
|
|
236
|
+
setDragEffects(treeBranch, event) {
|
|
237
|
+
const dataTransfer = event.dataTransfer;
|
|
238
|
+
if (!(dataTransfer instanceof DataTransfer)) {
|
|
239
|
+
throw new Error("bad drag event");
|
|
240
|
+
}
|
|
241
|
+
const nativeElement = treeBranch.getContents().location.nativeElement;
|
|
242
|
+
const [xOffset, yOffset] = this.getDragImageOffsets(event, nativeElement);
|
|
243
|
+
dataTransfer.setDragImage(nativeElement, xOffset, yOffset);
|
|
244
|
+
}
|
|
245
|
+
watchForDragend(treeBranch, event) {
|
|
246
|
+
const oldParent = treeBranch.parent();
|
|
247
|
+
const oldIndex = treeBranch.index();
|
|
248
|
+
if (oldParent === undefined || oldIndex === undefined) {
|
|
249
|
+
throw new Error("branch must have a parent");
|
|
250
|
+
}
|
|
251
|
+
event.target?.addEventListener("dragend", (dragend) => {
|
|
252
|
+
if (dragState.state() !== DragStates.Dropped) {
|
|
253
|
+
//The drag ended but a drop never occurred, so put the dragged branch back where it started.
|
|
254
|
+
this.dragAborted$.next(dragend);
|
|
255
|
+
this.graftDraggedBranch(treeBranch, oldParent, oldIndex);
|
|
256
|
+
}
|
|
257
|
+
dragState.restart();
|
|
258
|
+
const newParent = treeBranch.parent();
|
|
259
|
+
assert(newParent !== undefined);
|
|
260
|
+
const newIndex = treeBranch.index();
|
|
261
|
+
assert(newIndex !== undefined);
|
|
262
|
+
treeBranch.dispatch(new DragEndEvent(treeBranch, {
|
|
263
|
+
oldParent,
|
|
264
|
+
oldIndex,
|
|
265
|
+
newParent,
|
|
266
|
+
newIndex
|
|
267
|
+
}));
|
|
268
|
+
}, { once: true });
|
|
269
|
+
}
|
|
270
|
+
draggingAllowed(treeBranch) {
|
|
271
|
+
const allowDragging = config.getConfig(treeBranch.root())?.allowDragging ??
|
|
272
|
+
(() => true);
|
|
273
|
+
return allowDragging(treeBranch);
|
|
274
|
+
}
|
|
275
|
+
graftDraggedBranch(treeBranch, parent, index) {
|
|
276
|
+
treeBranch.graftTo(parent, index);
|
|
277
|
+
treeBranch.getContents().location.nativeElement.style.display = "block";
|
|
278
|
+
dragState.dropped();
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
const dragAndDrop = new DragAndDrop();
|
|
282
|
+
|
|
283
|
+
class DragoverNoChangeDetectDirective {
|
|
284
|
+
constructor(ngZone, el) {
|
|
285
|
+
this.ngZone = ngZone;
|
|
286
|
+
this.el = el;
|
|
287
|
+
this.dragoverNoChangeDetect = new EventEmitter();
|
|
288
|
+
this.dragoverEventThrottle = 25;
|
|
289
|
+
}
|
|
290
|
+
ngOnInit() {
|
|
291
|
+
this.ngZone.runOutsideAngular(() => {
|
|
292
|
+
this.eventSubscription = fromEvent(this.el.nativeElement, "dragover")
|
|
293
|
+
.pipe(throttleTime(this.dragoverEventThrottle))
|
|
294
|
+
.subscribe(($event) => {
|
|
295
|
+
this.dragoverNoChangeDetect.emit($event);
|
|
296
|
+
});
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
ngOnDestroy() {
|
|
300
|
+
if (this.eventSubscription !== undefined) {
|
|
301
|
+
this.eventSubscription.unsubscribe();
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
DragoverNoChangeDetectDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: DragoverNoChangeDetectDirective, deps: [{ token: i0.NgZone }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive });
|
|
306
|
+
DragoverNoChangeDetectDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.2.12", type: DragoverNoChangeDetectDirective, isStandalone: true, selector: "[dragoverNoChangeDetect]", inputs: { dragoverEventThrottle: "dragoverEventThrottle" }, outputs: { dragoverNoChangeDetect: "dragoverNoChangeDetect" }, ngImport: i0 });
|
|
307
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: DragoverNoChangeDetectDirective, decorators: [{
|
|
308
|
+
type: Directive,
|
|
309
|
+
args: [{
|
|
310
|
+
standalone: true,
|
|
311
|
+
selector: "[dragoverNoChangeDetect]"
|
|
312
|
+
}]
|
|
313
|
+
}], ctorParameters: function () { return [{ type: i0.NgZone }, { type: i0.ElementRef }]; }, propDecorators: { dragoverEventThrottle: [{
|
|
314
|
+
type: Input
|
|
315
|
+
}], dragoverNoChangeDetect: [{
|
|
316
|
+
type: Output
|
|
317
|
+
}] } });
|
|
318
|
+
|
|
319
|
+
class DropzoneComponent {
|
|
320
|
+
constructor() {
|
|
321
|
+
this.dropped = new EventEmitter();
|
|
322
|
+
this.active = false;
|
|
323
|
+
}
|
|
324
|
+
dragenterHandler() {
|
|
325
|
+
this.active = true;
|
|
326
|
+
}
|
|
327
|
+
dragleaveHandler() {
|
|
328
|
+
this.active = false;
|
|
329
|
+
}
|
|
330
|
+
dragoverHandler(event) {
|
|
331
|
+
event.preventDefault();
|
|
332
|
+
event.dataTransfer.dropEffect = "move";
|
|
333
|
+
}
|
|
334
|
+
dropHandler(event) {
|
|
335
|
+
this.dropped.emit(event);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
DropzoneComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: DropzoneComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
339
|
+
DropzoneComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.12", type: DropzoneComponent, isStandalone: true, selector: "dropzone", inputs: { placement: "placement" }, outputs: { dropped: "dropped" }, ngImport: i0, template: "<div\n class=\"dropzone\"\n [ngClass]=\"{ active: active }\"\n (dragenter)=\"dragenterHandler()\"\n (dragleave)=\"dragleaveHandler()\"\n (dragoverNoChangeDetect)=\"dragoverHandler($event)\"\n (drop)=\"dropHandler($event)\"\n></div>\n", styles: [".dropzone{border-radius:8px;border:1px dashed #727374;background-color:#ededed;height:20px;margin:8px 0;transition:height .2s ease-out;animation:animation .2s ease-out}.dropzone.active{border-color:#289e49;border-width:2px;background-color:#d0e8d6;height:48px}@keyframes animation{0%{height:0px;opacity:0}to{height:20px;opacity:1}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: DragoverNoChangeDetectDirective, selector: "[dragoverNoChangeDetect]", inputs: ["dragoverEventThrottle"], outputs: ["dragoverNoChangeDetect"] }] });
|
|
340
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: DropzoneComponent, decorators: [{
|
|
341
|
+
type: Component,
|
|
342
|
+
args: [{ standalone: true, selector: "dropzone", imports: [CommonModule, DragoverNoChangeDetectDirective], template: "<div\n class=\"dropzone\"\n [ngClass]=\"{ active: active }\"\n (dragenter)=\"dragenterHandler()\"\n (dragleave)=\"dragleaveHandler()\"\n (dragoverNoChangeDetect)=\"dragoverHandler($event)\"\n (drop)=\"dropHandler($event)\"\n></div>\n", styles: [".dropzone{border-radius:8px;border:1px dashed #727374;background-color:#ededed;height:20px;margin:8px 0;transition:height .2s ease-out;animation:animation .2s ease-out}.dropzone.active{border-color:#289e49;border-width:2px;background-color:#d0e8d6;height:48px}@keyframes animation{0%{height:0px;opacity:0}to{height:20px;opacity:1}}\n"] }]
|
|
343
|
+
}], propDecorators: { placement: [{
|
|
344
|
+
type: Input
|
|
345
|
+
}], dropped: [{
|
|
346
|
+
type: Output
|
|
347
|
+
}] } });
|
|
348
|
+
|
|
349
|
+
class BranchComponent {
|
|
350
|
+
constructor(appRef) {
|
|
351
|
+
this.appRef = appRef;
|
|
352
|
+
this.branchesContainer = undefined;
|
|
353
|
+
this.contentContainer = undefined;
|
|
354
|
+
this.dropzones = undefined;
|
|
355
|
+
this.contentCreated = new EventEmitter();
|
|
356
|
+
this.showDropzones = new EventEmitter();
|
|
357
|
+
this.dropped = new EventEmitter();
|
|
358
|
+
this.showInnerDropzone = false;
|
|
359
|
+
this.showLateralDropzone = false;
|
|
360
|
+
}
|
|
361
|
+
ngAfterViewInit() {
|
|
362
|
+
if (this.contentContainer === undefined) {
|
|
363
|
+
throw new TreeError("Cannot get contentContainer");
|
|
364
|
+
}
|
|
365
|
+
if (this.contentToHost === undefined) {
|
|
366
|
+
throw new TreeError("'content' is a required input");
|
|
367
|
+
}
|
|
368
|
+
this.hostedContent = this.contentContainer.createComponent(this.contentToHost);
|
|
369
|
+
this.contentCreated.emit(this.hostedContent.instance);
|
|
370
|
+
if (this.dropzones === undefined) {
|
|
371
|
+
throw new Error("querylist not defined");
|
|
372
|
+
}
|
|
373
|
+
const inner = this.dropzones.get(0);
|
|
374
|
+
const lateral = this.dropzones.get(1);
|
|
375
|
+
if (inner === undefined || lateral == undefined) {
|
|
376
|
+
throw new Error("dropzones not defined");
|
|
377
|
+
}
|
|
378
|
+
merge(inner.dropped.pipe(map(() => "inner")), lateral.dropped.pipe(map(() => "lateral"))).subscribe(this.dropped);
|
|
379
|
+
this.hostedContent.changeDetectorRef.detectChanges();
|
|
380
|
+
}
|
|
381
|
+
getHostedContent() {
|
|
382
|
+
return this.hostedContent;
|
|
383
|
+
}
|
|
384
|
+
triggerChangeDetection() {
|
|
385
|
+
if (!NgZone.isInAngularZone()) {
|
|
386
|
+
this.appRef.tick();
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
dragoverHandler(event) {
|
|
390
|
+
const elementHeight = event.currentTarget.getBoundingClientRect().height;
|
|
391
|
+
if (event.offsetY < elementHeight / 2) {
|
|
392
|
+
this.showDropzones.emit("upper");
|
|
393
|
+
}
|
|
394
|
+
else {
|
|
395
|
+
this.showDropzones.emit("lower");
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
ngOnDestroy() {
|
|
399
|
+
//I'm not 100% sure why, but we have to remove any reference to the
|
|
400
|
+
//componentRef otherwise Angular will never release it for garbage
|
|
401
|
+
//collection.
|
|
402
|
+
this.hostedContent = undefined;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
BranchComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: BranchComponent, deps: [{ token: i0.ApplicationRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
406
|
+
BranchComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.12", type: BranchComponent, isStandalone: true, selector: "branch", inputs: { contentToHost: "contentToHost" }, outputs: { contentCreated: "contentCreated", showDropzones: "showDropzones", dropped: "dropped" }, viewQueries: [{ propertyName: "branchesContainer", first: true, predicate: ["branchesContainer"], descendants: true, read: ViewContainerRef }, { propertyName: "contentContainer", first: true, predicate: ["contentContainer"], descendants: true, read: ViewContainerRef }, { propertyName: "dropzones", predicate: DropzoneComponent, descendants: true }], ngImport: i0, template: "<div class=\"content\" (dragoverNoChangeDetect)=\"dragoverHandler($event)\">\n <div #contentContainer></div>\n</div>\n<div class=\"branches-container\">\n <dropzone placement=\"inner\" [hidden]=\"!showInnerDropzone\"></dropzone>\n <div #branchesContainer></div>\n</div>\n<dropzone placement=\"lateral\" [hidden]=\"!showLateralDropzone\"></dropzone>\n", styles: [".branches-container{margin-left:16px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: DropzoneComponent, selector: "dropzone", inputs: ["placement"], outputs: ["dropped"] }, { kind: "directive", type: DragoverNoChangeDetectDirective, selector: "[dragoverNoChangeDetect]", inputs: ["dragoverEventThrottle"], outputs: ["dragoverNoChangeDetect"] }] });
|
|
407
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: BranchComponent, decorators: [{
|
|
408
|
+
type: Component,
|
|
409
|
+
args: [{ standalone: true, selector: "branch", imports: [CommonModule, DropzoneComponent, DragoverNoChangeDetectDirective], template: "<div class=\"content\" (dragoverNoChangeDetect)=\"dragoverHandler($event)\">\n <div #contentContainer></div>\n</div>\n<div class=\"branches-container\">\n <dropzone placement=\"inner\" [hidden]=\"!showInnerDropzone\"></dropzone>\n <div #branchesContainer></div>\n</div>\n<dropzone placement=\"lateral\" [hidden]=\"!showLateralDropzone\"></dropzone>\n", styles: [".branches-container{margin-left:16px}\n"] }]
|
|
410
|
+
}], ctorParameters: function () { return [{ type: i0.ApplicationRef }]; }, propDecorators: { branchesContainer: [{
|
|
411
|
+
type: ViewChild,
|
|
412
|
+
args: ["branchesContainer", { read: ViewContainerRef }]
|
|
413
|
+
}], contentContainer: [{
|
|
414
|
+
type: ViewChild,
|
|
415
|
+
args: ["contentContainer", { read: ViewContainerRef }]
|
|
416
|
+
}], dropzones: [{
|
|
417
|
+
type: ViewChildren,
|
|
418
|
+
args: [DropzoneComponent]
|
|
419
|
+
}], contentToHost: [{
|
|
420
|
+
type: Input
|
|
421
|
+
}], contentCreated: [{
|
|
422
|
+
type: Output
|
|
423
|
+
}], showDropzones: [{
|
|
424
|
+
type: Output
|
|
425
|
+
}], dropped: [{
|
|
426
|
+
type: Output
|
|
427
|
+
}] } });
|
|
428
|
+
|
|
429
|
+
class GraftEvent {
|
|
430
|
+
constructor(source, relationship) {
|
|
431
|
+
this._source = source;
|
|
432
|
+
this._child = relationship.child;
|
|
433
|
+
this._parent = relationship.parent;
|
|
434
|
+
this._index = relationship.index;
|
|
435
|
+
}
|
|
436
|
+
child() {
|
|
437
|
+
return this._child;
|
|
438
|
+
}
|
|
439
|
+
type() {
|
|
440
|
+
return "graft";
|
|
441
|
+
}
|
|
442
|
+
index() {
|
|
443
|
+
return this._index;
|
|
444
|
+
}
|
|
445
|
+
parent() {
|
|
446
|
+
return this._parent;
|
|
447
|
+
}
|
|
448
|
+
source() {
|
|
449
|
+
return this._source;
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
class PruneEvent {
|
|
454
|
+
constructor(source, relationship) {
|
|
455
|
+
this._source = source;
|
|
456
|
+
this._child = relationship.child;
|
|
457
|
+
this._parent = relationship.parent;
|
|
458
|
+
this._index = relationship.index;
|
|
459
|
+
}
|
|
460
|
+
child() {
|
|
461
|
+
return this._child;
|
|
462
|
+
}
|
|
463
|
+
type() {
|
|
464
|
+
return "prune";
|
|
465
|
+
}
|
|
466
|
+
index() {
|
|
467
|
+
return this._index;
|
|
468
|
+
}
|
|
469
|
+
parent() {
|
|
470
|
+
return this._parent;
|
|
471
|
+
}
|
|
472
|
+
source() {
|
|
473
|
+
return this._source;
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
class TreeNodeBase {
|
|
478
|
+
constructor() {
|
|
479
|
+
this._branches = [];
|
|
480
|
+
this.events$ = new Subject();
|
|
481
|
+
this.subscriptions = [
|
|
482
|
+
this.graftsToSelf().subscribe((event) => {
|
|
483
|
+
this.registerChildRelationship(event.child(), event.index());
|
|
484
|
+
}),
|
|
485
|
+
this.prunesToSelf().subscribe((event) => {
|
|
486
|
+
this.deregisterChildRelationship(event.child());
|
|
487
|
+
})
|
|
488
|
+
];
|
|
489
|
+
}
|
|
490
|
+
branches() {
|
|
491
|
+
return [...this._branches];
|
|
492
|
+
}
|
|
493
|
+
deleteBranch(index) {
|
|
494
|
+
if (index === undefined) {
|
|
495
|
+
this._branches.pop();
|
|
496
|
+
return;
|
|
497
|
+
}
|
|
498
|
+
this._branches.splice(index, 1);
|
|
499
|
+
}
|
|
500
|
+
destroy() {
|
|
501
|
+
this.subscriptions.forEach((sub) => {
|
|
502
|
+
sub.unsubscribe();
|
|
503
|
+
});
|
|
504
|
+
}
|
|
505
|
+
dispatch(event) {
|
|
506
|
+
this.events$.next(event);
|
|
507
|
+
}
|
|
508
|
+
events() {
|
|
509
|
+
return this.events$;
|
|
510
|
+
}
|
|
511
|
+
getBranch(index) {
|
|
512
|
+
return this._branches[index];
|
|
513
|
+
}
|
|
514
|
+
plot() {
|
|
515
|
+
return new Map(this.branches().map((branch, index) => [index, branch.plot()]));
|
|
516
|
+
}
|
|
517
|
+
traverse(callback) {
|
|
518
|
+
this.branches().forEach((branch) => {
|
|
519
|
+
branch.traverse(callback);
|
|
520
|
+
});
|
|
521
|
+
}
|
|
522
|
+
deregisterChildRelationship(child) {
|
|
523
|
+
const index = this.branches().findIndex((branch) => branch === child);
|
|
524
|
+
this.deleteBranch(index);
|
|
525
|
+
}
|
|
526
|
+
graftsToSelf() {
|
|
527
|
+
return this.events().pipe(filter((event) => event instanceof GraftEvent), filter((event) => event.parent().events() === this.events$));
|
|
528
|
+
}
|
|
529
|
+
prunesToSelf() {
|
|
530
|
+
return this.events().pipe(filter((event) => event instanceof PruneEvent), filter((event) => event.parent().events() === this.events$));
|
|
531
|
+
}
|
|
532
|
+
registerChildRelationship(child, index) {
|
|
533
|
+
const branches = this.branches();
|
|
534
|
+
if (index < 0 || index > branches.length) {
|
|
535
|
+
throw new TreeError(`Can't register child at index ${index}. Out of range.`);
|
|
536
|
+
}
|
|
537
|
+
this._branches.splice(index, 0, child);
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
class RootComponent {
|
|
542
|
+
constructor() {
|
|
543
|
+
this.branchesContainer = undefined;
|
|
544
|
+
this.dropzone = undefined;
|
|
545
|
+
this.afterViewInit = new EventEmitter();
|
|
546
|
+
this.dropped = new EventEmitter();
|
|
547
|
+
this.showInnerDropzone = false;
|
|
548
|
+
}
|
|
549
|
+
ngAfterViewInit() {
|
|
550
|
+
this.afterViewInit.emit();
|
|
551
|
+
if (this.dropzone === undefined) {
|
|
552
|
+
throw new Error("dropzone is not defined");
|
|
553
|
+
}
|
|
554
|
+
this.dropzone.dropped.subscribe(this.dropped);
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
RootComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: RootComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
558
|
+
RootComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.12", type: RootComponent, isStandalone: true, selector: "root", outputs: { afterViewInit: "afterViewInit", dropped: "dropped" }, viewQueries: [{ propertyName: "branchesContainer", first: true, predicate: ["branchesContainer"], descendants: true, read: ViewContainerRef }, { propertyName: "dropzone", first: true, predicate: DropzoneComponent, descendants: true }], ngImport: i0, template: "<div class=\"branches-container\">\n <dropzone placement=\"inner\" [hidden]=\"!showInnerDropzone\"></dropzone>\n <div #branchesContainer></div>\n</div>\n", styles: [".branches-container{min-width:64px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: DropzoneComponent, selector: "dropzone", inputs: ["placement"], outputs: ["dropped"] }] });
|
|
559
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: RootComponent, decorators: [{
|
|
560
|
+
type: Component,
|
|
561
|
+
args: [{ standalone: true, selector: "root", imports: [CommonModule, DropzoneComponent], template: "<div class=\"branches-container\">\n <dropzone placement=\"inner\" [hidden]=\"!showInnerDropzone\"></dropzone>\n <div #branchesContainer></div>\n</div>\n", styles: [".branches-container{min-width:64px}\n"] }]
|
|
562
|
+
}], propDecorators: { branchesContainer: [{
|
|
563
|
+
type: ViewChild,
|
|
564
|
+
args: ["branchesContainer", { read: ViewContainerRef }]
|
|
565
|
+
}], dropzone: [{
|
|
566
|
+
type: ViewChild,
|
|
567
|
+
args: [DropzoneComponent]
|
|
568
|
+
}], afterViewInit: [{
|
|
569
|
+
type: Output
|
|
570
|
+
}], dropped: [{
|
|
571
|
+
type: Output
|
|
572
|
+
}] } });
|
|
573
|
+
|
|
574
|
+
class TreeRoot {
|
|
575
|
+
constructor(viewContainerRef) {
|
|
576
|
+
this.viewContainerRef = viewContainerRef;
|
|
577
|
+
this.treeNodeBase = new TreeNodeBase();
|
|
578
|
+
this.rootComponentRef =
|
|
579
|
+
this.viewContainerRef.createComponent(RootComponent);
|
|
580
|
+
const viewInitSub = this.rootComponentRef.instance.afterViewInit.subscribe(() => {
|
|
581
|
+
const dropzone = this.rootComponentRef.instance.dropzone;
|
|
582
|
+
if (!dropzone) {
|
|
583
|
+
throw new Error("dropzone not defined");
|
|
584
|
+
}
|
|
585
|
+
dropzoneRenderer.registerDropzone(dropzone, this);
|
|
586
|
+
});
|
|
587
|
+
const droppedSub = this.rootComponentRef.instance.dropped.subscribe(() => {
|
|
588
|
+
dropzoneRenderer.handleDrop(this, "inner");
|
|
589
|
+
});
|
|
590
|
+
this.instanceSubscriptions = [viewInitSub, droppedSub];
|
|
591
|
+
this.rootComponentRef.changeDetectorRef.detectChanges();
|
|
592
|
+
}
|
|
593
|
+
branches() {
|
|
594
|
+
return this.treeNodeBase.branches();
|
|
595
|
+
}
|
|
596
|
+
deleteBranch(index) {
|
|
597
|
+
this.treeNodeBase.deleteBranch(index);
|
|
598
|
+
}
|
|
599
|
+
destroy() {
|
|
600
|
+
dropzoneRenderer.clearTreeFromRegistry(this);
|
|
601
|
+
this.branches().forEach((branch) => {
|
|
602
|
+
branch.destroy();
|
|
603
|
+
});
|
|
604
|
+
this.treeNodeBase.destroy();
|
|
605
|
+
this.instanceSubscriptions.forEach((sub) => {
|
|
606
|
+
sub.unsubscribe();
|
|
607
|
+
});
|
|
608
|
+
this.viewContainerRef.clear();
|
|
609
|
+
config.delete(this);
|
|
610
|
+
}
|
|
611
|
+
dispatch(event) {
|
|
612
|
+
this.treeNodeBase.dispatch(event);
|
|
613
|
+
}
|
|
614
|
+
events() {
|
|
615
|
+
return this.treeNodeBase.events();
|
|
616
|
+
}
|
|
617
|
+
getBranch(index) {
|
|
618
|
+
return this.treeNodeBase.getBranch(index);
|
|
619
|
+
}
|
|
620
|
+
getContents() {
|
|
621
|
+
return this.rootComponentRef;
|
|
622
|
+
}
|
|
623
|
+
grow(component, options) {
|
|
624
|
+
return new TreeBranch(this, { component, ...options });
|
|
625
|
+
}
|
|
626
|
+
plot() {
|
|
627
|
+
return this.treeNodeBase.plot();
|
|
628
|
+
}
|
|
629
|
+
root() {
|
|
630
|
+
return this;
|
|
631
|
+
}
|
|
632
|
+
traverse(callback) {
|
|
633
|
+
callback(this);
|
|
634
|
+
this.treeNodeBase.traverse(callback);
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
class TreeService {
|
|
639
|
+
createEmptyTree(container, options = {}) {
|
|
640
|
+
container.clear();
|
|
641
|
+
const root = new TreeRoot(container);
|
|
642
|
+
config.setConfig(root, options);
|
|
643
|
+
return root;
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
TreeService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: TreeService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
647
|
+
TreeService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: TreeService, providedIn: "root" });
|
|
648
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: TreeService, decorators: [{
|
|
649
|
+
type: Injectable,
|
|
650
|
+
args: [{ providedIn: "root" }]
|
|
651
|
+
}] });
|
|
652
|
+
|
|
653
|
+
class TreeBranch {
|
|
654
|
+
constructor(parent, branchOptions) {
|
|
655
|
+
this.branchOptions = branchOptions;
|
|
656
|
+
this.detachedView = null;
|
|
657
|
+
this.treeNodeBase = new TreeNodeBase();
|
|
658
|
+
this.userlandComponent = this.branchOptions.component;
|
|
659
|
+
const parentBranchesContainer = parent.getContents().instance.branchesContainer;
|
|
660
|
+
assert(parentBranchesContainer !== undefined);
|
|
661
|
+
this.contents = createComponent(BranchComponent, {
|
|
662
|
+
environmentInjector: parentBranchesContainer.injector.get(EnvironmentInjector)
|
|
663
|
+
});
|
|
664
|
+
this.contents.instance.contentToHost = this.userlandComponent;
|
|
665
|
+
this.setIndentation(parent);
|
|
666
|
+
this.outputBindingSubscriptions = [];
|
|
667
|
+
this.instanceSubscriptions = this.getInstanceSubscriptions();
|
|
668
|
+
if (parent instanceof TreeBranch &&
|
|
669
|
+
parent.branchOptions.startCollapsed === true) {
|
|
670
|
+
treeCollapser.storePrecollapsedNode(parent, this);
|
|
671
|
+
this.detachedView = this.contents.hostView;
|
|
672
|
+
}
|
|
673
|
+
else {
|
|
674
|
+
parentBranchesContainer.insert(this.contents.hostView);
|
|
675
|
+
this.contents.changeDetectorRef.detectChanges();
|
|
676
|
+
this._parent = parent;
|
|
677
|
+
this.dispatch(new GraftEvent(this, {
|
|
678
|
+
parent: this._parent,
|
|
679
|
+
child: this,
|
|
680
|
+
index: this._parent.branches().length
|
|
681
|
+
}));
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
branches() {
|
|
685
|
+
return this.treeNodeBase.branches();
|
|
686
|
+
}
|
|
687
|
+
deleteBranch(index) {
|
|
688
|
+
this.treeNodeBase.deleteBranch(index);
|
|
689
|
+
}
|
|
690
|
+
destroy() {
|
|
691
|
+
if (treeCollapser.isCollapsed(this)) {
|
|
692
|
+
treeCollapser.expand(this);
|
|
693
|
+
dropzoneRenderer.clearTreeFromRegistry(this);
|
|
694
|
+
}
|
|
695
|
+
this.branches().forEach((branch) => {
|
|
696
|
+
branch.destroy();
|
|
697
|
+
});
|
|
698
|
+
const parent = this._parent;
|
|
699
|
+
const index = this.index();
|
|
700
|
+
if (index !== undefined && parent !== undefined) {
|
|
701
|
+
const container = parent.getContents().instance.branchesContainer;
|
|
702
|
+
assert(container !== undefined);
|
|
703
|
+
container.remove(index);
|
|
704
|
+
parent.deleteBranch(index);
|
|
705
|
+
}
|
|
706
|
+
this.treeNodeBase.destroy();
|
|
707
|
+
this.instanceSubscriptions.forEach((sub) => {
|
|
708
|
+
sub.unsubscribe();
|
|
709
|
+
});
|
|
710
|
+
this.outputBindingSubscriptions.forEach((sub) => {
|
|
711
|
+
sub.unsubscribe();
|
|
712
|
+
});
|
|
713
|
+
}
|
|
714
|
+
dispatch(event) {
|
|
715
|
+
this.treeNodeBase.dispatch(event);
|
|
716
|
+
this._parent?.dispatch(event);
|
|
717
|
+
}
|
|
718
|
+
events() {
|
|
719
|
+
return this.treeNodeBase.events();
|
|
720
|
+
}
|
|
721
|
+
getBranch(index) {
|
|
722
|
+
return this.treeNodeBase.getBranch(index);
|
|
723
|
+
}
|
|
724
|
+
getContents() {
|
|
725
|
+
return this.contents;
|
|
726
|
+
}
|
|
727
|
+
graftTo(newParent, index) {
|
|
728
|
+
const ownIndex = this.index();
|
|
729
|
+
if (ownIndex !== undefined) {
|
|
730
|
+
this.prune();
|
|
731
|
+
}
|
|
732
|
+
this._parent = newParent;
|
|
733
|
+
const newIndex = index ?? newParent.branches().length;
|
|
734
|
+
this.reattachView(newIndex);
|
|
735
|
+
this.dispatch(new GraftEvent(this, {
|
|
736
|
+
parent: newParent,
|
|
737
|
+
child: this,
|
|
738
|
+
index: newIndex
|
|
739
|
+
}));
|
|
740
|
+
return newIndex;
|
|
741
|
+
}
|
|
742
|
+
grow(component, options) {
|
|
743
|
+
return new TreeBranch(this, { component, ...options });
|
|
744
|
+
}
|
|
745
|
+
index() {
|
|
746
|
+
if (!this._parent) {
|
|
747
|
+
return undefined;
|
|
748
|
+
}
|
|
749
|
+
const index = this._parent
|
|
750
|
+
.branches()
|
|
751
|
+
.findIndex((branch) => branch === this);
|
|
752
|
+
assert(index >= 0);
|
|
753
|
+
return index;
|
|
754
|
+
}
|
|
755
|
+
meta() {
|
|
756
|
+
return this.branchOptions.meta ?? {};
|
|
757
|
+
}
|
|
758
|
+
parent() {
|
|
759
|
+
return this._parent;
|
|
760
|
+
}
|
|
761
|
+
plot() {
|
|
762
|
+
return this.treeNodeBase.plot();
|
|
763
|
+
}
|
|
764
|
+
position() {
|
|
765
|
+
const index = this.index();
|
|
766
|
+
if (index === undefined) {
|
|
767
|
+
throw new TreeError("branch has no parent. Position cannot be determined.");
|
|
768
|
+
}
|
|
769
|
+
if (this._parent instanceof TreeBranch) {
|
|
770
|
+
const parentPosition = this._parent.position();
|
|
771
|
+
return [...parentPosition, index];
|
|
772
|
+
}
|
|
773
|
+
return [index];
|
|
774
|
+
}
|
|
775
|
+
prune() {
|
|
776
|
+
const parent = this._parent;
|
|
777
|
+
const index = this.index();
|
|
778
|
+
if (index === undefined || parent === undefined)
|
|
779
|
+
return;
|
|
780
|
+
const container = parent.getContents().instance.branchesContainer;
|
|
781
|
+
assert(container !== undefined);
|
|
782
|
+
this.detachedView = container.detach(index);
|
|
783
|
+
assert(this.detachedView !== null);
|
|
784
|
+
this.detachedView.detach();
|
|
785
|
+
this.dispatch(new PruneEvent(this, {
|
|
786
|
+
parent: parent,
|
|
787
|
+
child: this,
|
|
788
|
+
index: index
|
|
789
|
+
}));
|
|
790
|
+
this._parent = undefined;
|
|
791
|
+
return this;
|
|
792
|
+
}
|
|
793
|
+
root() {
|
|
794
|
+
const parent = this.parent();
|
|
795
|
+
if (parent === undefined) {
|
|
796
|
+
return undefined;
|
|
797
|
+
}
|
|
798
|
+
if (parent instanceof TreeBranch) {
|
|
799
|
+
return parent.root();
|
|
800
|
+
}
|
|
801
|
+
if (parent instanceof TreeRoot) {
|
|
802
|
+
return parent;
|
|
803
|
+
}
|
|
804
|
+
throw new Error("unexpected parent type");
|
|
805
|
+
}
|
|
806
|
+
traverse(callback) {
|
|
807
|
+
callback(this);
|
|
808
|
+
this.treeNodeBase.traverse(callback);
|
|
809
|
+
}
|
|
810
|
+
getContentCreatedSub() {
|
|
811
|
+
const instance = this.contents.instance;
|
|
812
|
+
return instance.contentCreated.subscribe((userlandComponentInstance) => {
|
|
813
|
+
for (const [key, value] of Object.entries(this.branchOptions.inputBindings ?? {})) {
|
|
814
|
+
userlandComponentInstance[key] = value;
|
|
815
|
+
}
|
|
816
|
+
for (const [key, value] of Object.entries(this.branchOptions.outputBindings ?? {})) {
|
|
817
|
+
this.outputBindingSubscriptions.push(userlandComponentInstance[key].subscribe(value));
|
|
818
|
+
}
|
|
819
|
+
userlandComponentInstance.treeBranch = this;
|
|
820
|
+
const dropzones = instance.dropzones;
|
|
821
|
+
if (!dropzones) {
|
|
822
|
+
throw new Error("dropzones not defined");
|
|
823
|
+
}
|
|
824
|
+
dropzoneRenderer.registerDropzones(dropzones, this);
|
|
825
|
+
});
|
|
826
|
+
}
|
|
827
|
+
getInstanceSubscriptions() {
|
|
828
|
+
const droppedSub = this.contents.instance.dropped.subscribe((placement) => {
|
|
829
|
+
dropzoneRenderer.handleDrop(this, placement);
|
|
830
|
+
});
|
|
831
|
+
return [
|
|
832
|
+
this.getContentCreatedSub(),
|
|
833
|
+
this.getShowLowerZonesSub(),
|
|
834
|
+
this.getShowUpperZonesSub(),
|
|
835
|
+
droppedSub
|
|
836
|
+
];
|
|
837
|
+
}
|
|
838
|
+
getShowLowerZonesSub() {
|
|
839
|
+
const instance = this.contents.instance;
|
|
840
|
+
return instance.showDropzones
|
|
841
|
+
.pipe(filter((direction) => direction === "lower"))
|
|
842
|
+
.subscribe(() => {
|
|
843
|
+
const currentDropzoneDisplayed = dropzoneRenderer.getCurrentDisplay();
|
|
844
|
+
if (currentDropzoneDisplayed?.treeBranch === this &&
|
|
845
|
+
currentDropzoneDisplayed.direction === "lower") {
|
|
846
|
+
return;
|
|
847
|
+
}
|
|
848
|
+
dropzoneRenderer.showLowerZones(this);
|
|
849
|
+
instance.triggerChangeDetection();
|
|
850
|
+
});
|
|
851
|
+
}
|
|
852
|
+
getShowUpperZonesSub() {
|
|
853
|
+
const instance = this.contents.instance;
|
|
854
|
+
return instance.showDropzones
|
|
855
|
+
.pipe(filter((direction) => direction === "upper"))
|
|
856
|
+
.subscribe(() => {
|
|
857
|
+
const currentDropzoneDisplayed = dropzoneRenderer.getCurrentDisplay();
|
|
858
|
+
if (currentDropzoneDisplayed?.treeBranch === this &&
|
|
859
|
+
currentDropzoneDisplayed.direction === "upper") {
|
|
860
|
+
return;
|
|
861
|
+
}
|
|
862
|
+
dropzoneRenderer.showUpperZones(this);
|
|
863
|
+
instance.triggerChangeDetection();
|
|
864
|
+
});
|
|
865
|
+
}
|
|
866
|
+
reattachView(index) {
|
|
867
|
+
assert(this._parent !== undefined);
|
|
868
|
+
assert(this.detachedView !== null);
|
|
869
|
+
const container = this._parent.getContents().instance.branchesContainer;
|
|
870
|
+
assert(container !== undefined);
|
|
871
|
+
this.detachedView.reattach();
|
|
872
|
+
container.insert(this.detachedView, index);
|
|
873
|
+
this.detachedView = null;
|
|
874
|
+
}
|
|
875
|
+
setIndentation(parent) {
|
|
876
|
+
const root = parent.root();
|
|
877
|
+
assert(root !== undefined);
|
|
878
|
+
const options = config.getConfig(root);
|
|
879
|
+
const branchesContainerEl = this.contents.location.nativeElement
|
|
880
|
+
.getElementsByClassName("branches-container")
|
|
881
|
+
.item(0);
|
|
882
|
+
assert(branchesContainerEl instanceof HTMLElement);
|
|
883
|
+
branchesContainerEl.style.marginLeft = `${options?.indentation ?? 16}px`;
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
class DropzoneRenderer {
|
|
888
|
+
constructor() {
|
|
889
|
+
this.registry = new Map();
|
|
890
|
+
this.currentDisplay = null;
|
|
891
|
+
dragAndDrop.dragAborted$.subscribe(() => {
|
|
892
|
+
this.clearCurrentDisplay();
|
|
893
|
+
});
|
|
894
|
+
dragState
|
|
895
|
+
.events()
|
|
896
|
+
.pipe(filter((event) => event === DragStates.Starting))
|
|
897
|
+
.subscribe(() => {
|
|
898
|
+
const branch = dragState.getDragData();
|
|
899
|
+
assert(branch !== undefined);
|
|
900
|
+
let cursor = branch.parent()?.getBranch((branch.index() ?? 0) - 1);
|
|
901
|
+
let final = branch.parent();
|
|
902
|
+
while (cursor !== undefined) {
|
|
903
|
+
final = cursor;
|
|
904
|
+
cursor = cursor.branches().at(-1);
|
|
905
|
+
}
|
|
906
|
+
branch
|
|
907
|
+
.events()
|
|
908
|
+
.pipe(filter((event) => event instanceof PruneEvent), first())
|
|
909
|
+
.subscribe(() => {
|
|
910
|
+
assert(final instanceof TreeBranch || final instanceof TreeRoot);
|
|
911
|
+
this.showLowerZones(final);
|
|
912
|
+
});
|
|
913
|
+
});
|
|
914
|
+
}
|
|
915
|
+
clearCurrentDisplay() {
|
|
916
|
+
if (this.currentDisplay === null)
|
|
917
|
+
return;
|
|
918
|
+
for (const branch of this.registry.values()) {
|
|
919
|
+
const instance = branch.getContents().instance;
|
|
920
|
+
instance.showInnerDropzone = false;
|
|
921
|
+
if (instance instanceof BranchComponent) {
|
|
922
|
+
instance.showLateralDropzone = false;
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
this.currentDisplay = null;
|
|
926
|
+
}
|
|
927
|
+
clearTreeFromRegistry(tree) {
|
|
928
|
+
const nodes = [];
|
|
929
|
+
tree.traverse((node) => nodes.push(node));
|
|
930
|
+
for (const [dropzoneComponent, treeNode] of this.registry) {
|
|
931
|
+
if (nodes.includes(treeNode)) {
|
|
932
|
+
this.registry.delete(dropzoneComponent);
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
}
|
|
936
|
+
getCurrentDisplay() {
|
|
937
|
+
if (this.currentDisplay === null)
|
|
938
|
+
return null;
|
|
939
|
+
return { ...this.currentDisplay };
|
|
940
|
+
}
|
|
941
|
+
getDropzoneLocation(dropzone) {
|
|
942
|
+
const branch = this.registry.get(dropzone);
|
|
943
|
+
const placement = dropzone.placement;
|
|
944
|
+
if (branch === undefined) {
|
|
945
|
+
throw new Error("dropzone not found in registry");
|
|
946
|
+
}
|
|
947
|
+
if (placement === undefined) {
|
|
948
|
+
throw new Error("dropzone has an undefined placement");
|
|
949
|
+
}
|
|
950
|
+
return [branch, placement];
|
|
951
|
+
}
|
|
952
|
+
handleDrop(treeNode, placement) {
|
|
953
|
+
if (placement === "inner") {
|
|
954
|
+
dragAndDrop.drop(treeNode, 0);
|
|
955
|
+
}
|
|
956
|
+
else if (treeNode instanceof TreeBranch && placement === "lateral") {
|
|
957
|
+
const currentParent = treeNode.parent();
|
|
958
|
+
const index = treeNode.index();
|
|
959
|
+
if (currentParent === undefined || index === undefined) {
|
|
960
|
+
throw new Error("branch must have a parent");
|
|
961
|
+
}
|
|
962
|
+
dragAndDrop.drop(currentParent, index + 1);
|
|
963
|
+
}
|
|
964
|
+
this.clearCurrentDisplay();
|
|
965
|
+
}
|
|
966
|
+
registerDropzone(dropzone, treeNode) {
|
|
967
|
+
this.registry.set(dropzone, treeNode);
|
|
968
|
+
}
|
|
969
|
+
registerDropzones(dropzones, treeBranch) {
|
|
970
|
+
for (const dropzone of dropzones) {
|
|
971
|
+
this.registry.set(dropzone, treeBranch);
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
showLowerZones(treeNode) {
|
|
975
|
+
this.clearCurrentDisplay();
|
|
976
|
+
this.showInnerZone(treeNode);
|
|
977
|
+
if (treeNode.branches().length === 0) {
|
|
978
|
+
this.loopThroughLowerZones(treeNode);
|
|
979
|
+
}
|
|
980
|
+
this.currentDisplay = { treeBranch: treeNode, direction: "lower" };
|
|
981
|
+
}
|
|
982
|
+
showUpperZones(treeBranch) {
|
|
983
|
+
this.clearCurrentDisplay();
|
|
984
|
+
this.loopThroughUpperZones(treeBranch);
|
|
985
|
+
this.currentDisplay = { treeBranch, direction: "upper" };
|
|
986
|
+
}
|
|
987
|
+
loopThroughLowerZones(treeNode) {
|
|
988
|
+
let cursor = treeNode;
|
|
989
|
+
while (cursor instanceof TreeBranch) {
|
|
990
|
+
this.showLateralZone(cursor);
|
|
991
|
+
const parent = cursor.parent();
|
|
992
|
+
const index = cursor.index();
|
|
993
|
+
assert(parent !== undefined && index !== undefined);
|
|
994
|
+
if (parent.branches().length > index + 1) {
|
|
995
|
+
return;
|
|
996
|
+
}
|
|
997
|
+
cursor = cursor.parent();
|
|
998
|
+
}
|
|
999
|
+
}
|
|
1000
|
+
loopThroughUpperZones(treeBranch) {
|
|
1001
|
+
let cursor = treeBranch
|
|
1002
|
+
.parent()
|
|
1003
|
+
?.getBranch((treeBranch.index() ?? 0) - 1);
|
|
1004
|
+
let final = treeBranch.parent();
|
|
1005
|
+
while (cursor !== undefined) {
|
|
1006
|
+
this.showLateralZone(cursor);
|
|
1007
|
+
final = cursor;
|
|
1008
|
+
cursor = cursor.branches().at(-1);
|
|
1009
|
+
}
|
|
1010
|
+
if (final !== undefined &&
|
|
1011
|
+
(final instanceof TreeRoot || final instanceof TreeBranch)) {
|
|
1012
|
+
this.showInnerZone(final);
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
nestingAllowed(treeNode) {
|
|
1016
|
+
if (treeNode instanceof TreeRoot) {
|
|
1017
|
+
return true;
|
|
1018
|
+
}
|
|
1019
|
+
if (treeNode instanceof TreeBranch) {
|
|
1020
|
+
const allowNesting = config.getConfig(treeNode.root())?.allowNesting ??
|
|
1021
|
+
(() => true);
|
|
1022
|
+
return allowNesting(treeNode);
|
|
1023
|
+
}
|
|
1024
|
+
throw new Error("unsupported treeNode type");
|
|
1025
|
+
}
|
|
1026
|
+
dropAllowed(parent, index) {
|
|
1027
|
+
const sourceNode = dragState.getDragData();
|
|
1028
|
+
assert(sourceNode instanceof TreeBranch);
|
|
1029
|
+
if (parent instanceof TreeRoot) {
|
|
1030
|
+
const allowDrop = config.getConfig(parent)?.allowDrop ?? (() => true);
|
|
1031
|
+
return allowDrop(sourceNode, parent, index);
|
|
1032
|
+
}
|
|
1033
|
+
if (parent instanceof TreeBranch) {
|
|
1034
|
+
const allowDrop = config.getConfig(parent.root())?.allowDrop ?? (() => true);
|
|
1035
|
+
return allowDrop(sourceNode, parent, index);
|
|
1036
|
+
}
|
|
1037
|
+
throw new Error("unsupported treeNode type");
|
|
1038
|
+
}
|
|
1039
|
+
showInnerZone(treeNode) {
|
|
1040
|
+
if (!this.nestingAllowed(treeNode) || !this.dropAllowed(treeNode, 0))
|
|
1041
|
+
return;
|
|
1042
|
+
treeNode.getContents().instance.showInnerDropzone = true;
|
|
1043
|
+
}
|
|
1044
|
+
showLateralZone(treeBranch) {
|
|
1045
|
+
const index = treeBranch.index();
|
|
1046
|
+
assert(index !== undefined);
|
|
1047
|
+
if (!this.dropAllowed(treeBranch.parent(), index + 1))
|
|
1048
|
+
return;
|
|
1049
|
+
treeBranch.getContents().instance.showLateralDropzone = true;
|
|
1050
|
+
}
|
|
1051
|
+
}
|
|
1052
|
+
const dropzoneRenderer = new DropzoneRenderer();
|
|
1053
|
+
|
|
1054
|
+
class TreeDragAndDropService {
|
|
1055
|
+
clearDropzones() {
|
|
1056
|
+
dropzoneRenderer.clearCurrentDisplay();
|
|
1057
|
+
}
|
|
1058
|
+
dragStart(treeBranch, event) {
|
|
1059
|
+
dragAndDrop.dragStart(treeBranch, event);
|
|
1060
|
+
}
|
|
1061
|
+
getCurrentlyDisplayedDropzoneFamily() {
|
|
1062
|
+
return dropzoneRenderer.getCurrentDisplay();
|
|
1063
|
+
}
|
|
1064
|
+
showRootDropzone(root) {
|
|
1065
|
+
dropzoneRenderer.showLowerZones(root);
|
|
1066
|
+
}
|
|
1067
|
+
state() {
|
|
1068
|
+
return dragState.events();
|
|
1069
|
+
}
|
|
1070
|
+
}
|
|
1071
|
+
TreeDragAndDropService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: TreeDragAndDropService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1072
|
+
TreeDragAndDropService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: TreeDragAndDropService });
|
|
1073
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: TreeDragAndDropService, decorators: [{
|
|
1074
|
+
type: Injectable
|
|
1075
|
+
}] });
|
|
1076
|
+
|
|
1077
|
+
class DraggableDirective {
|
|
1078
|
+
constructor(dragAndDropService, renderer, hostElement) {
|
|
1079
|
+
this.dragAndDropService = dragAndDropService;
|
|
1080
|
+
renderer.setAttribute(hostElement.nativeElement, "draggable", "true");
|
|
1081
|
+
renderer.setStyle(hostElement.nativeElement, "cursor", "grab");
|
|
1082
|
+
}
|
|
1083
|
+
onDragstart(event) {
|
|
1084
|
+
if (this.limbleTreeDraggable === undefined)
|
|
1085
|
+
return;
|
|
1086
|
+
this.dragAndDropService.dragStart(this.limbleTreeDraggable, event);
|
|
1087
|
+
}
|
|
1088
|
+
}
|
|
1089
|
+
DraggableDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: DraggableDirective, deps: [{ token: TreeDragAndDropService }, { token: i0.Renderer2 }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive });
|
|
1090
|
+
DraggableDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.2.12", type: DraggableDirective, isStandalone: true, selector: "[limbleTreeDraggable]", inputs: { limbleTreeDraggable: "limbleTreeDraggable" }, host: { listeners: { "dragstart": "onDragstart($event)" } }, ngImport: i0 });
|
|
1091
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: DraggableDirective, decorators: [{
|
|
1092
|
+
type: Directive,
|
|
1093
|
+
args: [{
|
|
1094
|
+
selector: "[limbleTreeDraggable]",
|
|
1095
|
+
standalone: true
|
|
1096
|
+
}]
|
|
1097
|
+
}], ctorParameters: function () { return [{ type: TreeDragAndDropService }, { type: i0.Renderer2 }, { type: i0.ElementRef }]; }, propDecorators: { limbleTreeDraggable: [{
|
|
1098
|
+
type: Input
|
|
1099
|
+
}], onDragstart: [{
|
|
1100
|
+
type: HostListener,
|
|
1101
|
+
args: ["dragstart", ["$event"]]
|
|
1102
|
+
}] } });
|
|
1103
|
+
|
|
1104
|
+
class TreeDragAndDropModule {
|
|
1105
|
+
}
|
|
1106
|
+
TreeDragAndDropModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: TreeDragAndDropModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
1107
|
+
TreeDragAndDropModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.2.12", ngImport: i0, type: TreeDragAndDropModule, imports: [DraggableDirective, DragoverNoChangeDetectDirective], exports: [DraggableDirective, DragoverNoChangeDetectDirective] });
|
|
1108
|
+
TreeDragAndDropModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: TreeDragAndDropModule, providers: [TreeDragAndDropService] });
|
|
1109
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: TreeDragAndDropModule, decorators: [{
|
|
1110
|
+
type: NgModule,
|
|
1111
|
+
args: [{
|
|
1112
|
+
imports: [DraggableDirective, DragoverNoChangeDetectDirective],
|
|
1113
|
+
providers: [TreeDragAndDropService],
|
|
1114
|
+
exports: [DraggableDirective, DragoverNoChangeDetectDirective]
|
|
1115
|
+
}]
|
|
1116
|
+
}] });
|
|
1117
|
+
|
|
1118
|
+
/**
|
|
1119
|
+
* A shim to help with the transition from v0 to v1.
|
|
1120
|
+
* @deprecated
|
|
1121
|
+
*/
|
|
1122
|
+
class LegacyTree {
|
|
1123
|
+
/** Creates a v1 tree structure from a v0 data array and v0 tree options. */
|
|
1124
|
+
createTreeFromLegacyArray(container, data, treeOptions = {}) {
|
|
1125
|
+
const root = new TreeRoot(container);
|
|
1126
|
+
config.setConfig(root, this.upgradeOptions(treeOptions));
|
|
1127
|
+
for (const node of data) {
|
|
1128
|
+
this.renderTreeNode(root, node, treeOptions);
|
|
1129
|
+
}
|
|
1130
|
+
return root;
|
|
1131
|
+
}
|
|
1132
|
+
upgradeOptions(legacyOptions) {
|
|
1133
|
+
return {
|
|
1134
|
+
indentation: legacyOptions.indent,
|
|
1135
|
+
allowNesting: (branch) => {
|
|
1136
|
+
if (legacyOptions.listMode === true) {
|
|
1137
|
+
return false;
|
|
1138
|
+
}
|
|
1139
|
+
if (legacyOptions.allowNesting === undefined) {
|
|
1140
|
+
return true;
|
|
1141
|
+
}
|
|
1142
|
+
if (typeof legacyOptions.allowNesting === "boolean") {
|
|
1143
|
+
return legacyOptions.allowNesting;
|
|
1144
|
+
}
|
|
1145
|
+
return legacyOptions.allowNesting(branch);
|
|
1146
|
+
},
|
|
1147
|
+
allowDragging: (branch) => {
|
|
1148
|
+
if (legacyOptions.allowDragging === undefined) {
|
|
1149
|
+
return true;
|
|
1150
|
+
}
|
|
1151
|
+
if (typeof legacyOptions.allowDragging === "boolean") {
|
|
1152
|
+
return legacyOptions.allowDragging;
|
|
1153
|
+
}
|
|
1154
|
+
return legacyOptions.allowDragging(branch);
|
|
1155
|
+
},
|
|
1156
|
+
allowDrop: (source, parent, index) => {
|
|
1157
|
+
if (legacyOptions.allowDrop === undefined) {
|
|
1158
|
+
return true;
|
|
1159
|
+
}
|
|
1160
|
+
return legacyOptions.allowDrop(source, parent, index);
|
|
1161
|
+
}
|
|
1162
|
+
};
|
|
1163
|
+
}
|
|
1164
|
+
renderTreeNode(parent, node, options) {
|
|
1165
|
+
const component = node.component?.class ?? options.defaultComponent?.class;
|
|
1166
|
+
if (component === undefined) {
|
|
1167
|
+
throw new TreeError("A component must be provided");
|
|
1168
|
+
}
|
|
1169
|
+
const bindings = (node.component?.bindings ??
|
|
1170
|
+
options.defaultComponent?.bindings ??
|
|
1171
|
+
{});
|
|
1172
|
+
const nodeData = node;
|
|
1173
|
+
delete nodeData.nodes;
|
|
1174
|
+
delete nodeData.collapsed;
|
|
1175
|
+
delete nodeData.component;
|
|
1176
|
+
const branch = parent.grow(component, {
|
|
1177
|
+
inputBindings: bindings,
|
|
1178
|
+
meta: { nodeData }
|
|
1179
|
+
});
|
|
1180
|
+
for (const childNode of node.nodes ?? []) {
|
|
1181
|
+
this.renderTreeNode(branch, childNode, options);
|
|
1182
|
+
}
|
|
1183
|
+
if (node.collapsed === true) {
|
|
1184
|
+
treeCollapser.collapse(branch);
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1187
|
+
}
|
|
1188
|
+
|
|
1189
|
+
/** @deprecated */
|
|
1190
|
+
class LimbleTreeRootComponent {
|
|
1191
|
+
constructor() {
|
|
1192
|
+
this.itemsPerPage = Infinity;
|
|
1193
|
+
this.page = 1;
|
|
1194
|
+
this.treeChange = new EventEmitter();
|
|
1195
|
+
this.treeDrop = new EventEmitter();
|
|
1196
|
+
this.legacyTree = new LegacyTree();
|
|
1197
|
+
}
|
|
1198
|
+
ngAfterViewInit() {
|
|
1199
|
+
this.update();
|
|
1200
|
+
}
|
|
1201
|
+
ngOnChanges() {
|
|
1202
|
+
if (this.host !== undefined && this.data !== undefined) {
|
|
1203
|
+
this.update();
|
|
1204
|
+
}
|
|
1205
|
+
}
|
|
1206
|
+
ngOnDestroy() {
|
|
1207
|
+
this.dropSubscription?.unsubscribe();
|
|
1208
|
+
this.root?.destroy();
|
|
1209
|
+
}
|
|
1210
|
+
getRoot() {
|
|
1211
|
+
return this.root;
|
|
1212
|
+
}
|
|
1213
|
+
update() {
|
|
1214
|
+
if (this.data === undefined) {
|
|
1215
|
+
throw new TreeError("LimbleTreeRootComponent's `data` input is required");
|
|
1216
|
+
}
|
|
1217
|
+
if (this.host === undefined) {
|
|
1218
|
+
throw new TreeError("LimbleTreeRootComponent's `host` property is not defined");
|
|
1219
|
+
}
|
|
1220
|
+
this.root?.destroy();
|
|
1221
|
+
this.dropSubscription?.unsubscribe();
|
|
1222
|
+
const dataSlice = this.paginatedData();
|
|
1223
|
+
this.root = this.legacyTree.createTreeFromLegacyArray(this.host, dataSlice, this.options);
|
|
1224
|
+
this.dropSubscription = this.root
|
|
1225
|
+
.events()
|
|
1226
|
+
.pipe(filter((event) => event instanceof DragEndEvent))
|
|
1227
|
+
.subscribe(this.treeDrop);
|
|
1228
|
+
this.treeChange.emit(this.root);
|
|
1229
|
+
}
|
|
1230
|
+
paginatedData() {
|
|
1231
|
+
assert(this.data !== undefined);
|
|
1232
|
+
if (this.options?.listMode !== true) {
|
|
1233
|
+
return this.data;
|
|
1234
|
+
}
|
|
1235
|
+
return this.data.slice((this.page - 1) * this.itemsPerPage, this.page * this.itemsPerPage);
|
|
1236
|
+
}
|
|
1237
|
+
}
|
|
1238
|
+
LimbleTreeRootComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: LimbleTreeRootComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1239
|
+
LimbleTreeRootComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.12", type: LimbleTreeRootComponent, isStandalone: true, selector: "limble-tree-root", inputs: { data: "data", options: "options", itemsPerPage: "itemsPerPage", page: "page" }, outputs: { treeChange: "treeChange", treeDrop: "treeDrop" }, viewQueries: [{ propertyName: "host", first: true, predicate: ["host"], descendants: true, read: ViewContainerRef }], usesOnChanges: true, ngImport: i0, template: "<div #host></div>\n" });
|
|
1240
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: LimbleTreeRootComponent, decorators: [{
|
|
1241
|
+
type: Component,
|
|
1242
|
+
args: [{ selector: "limble-tree-root", standalone: true, template: "<div #host></div>\n" }]
|
|
1243
|
+
}], ctorParameters: function () { return []; }, propDecorators: { data: [{
|
|
1244
|
+
type: Input
|
|
1245
|
+
}], options: [{
|
|
1246
|
+
type: Input
|
|
1247
|
+
}], itemsPerPage: [{
|
|
1248
|
+
type: Input
|
|
1249
|
+
}], page: [{
|
|
1250
|
+
type: Input
|
|
1251
|
+
}], host: [{
|
|
1252
|
+
type: ViewChild,
|
|
1253
|
+
args: ["host", { read: ViewContainerRef }]
|
|
1254
|
+
}], treeChange: [{
|
|
1255
|
+
type: Output
|
|
1256
|
+
}], treeDrop: [{
|
|
1257
|
+
type: Output
|
|
1258
|
+
}] } });
|
|
1259
|
+
|
|
1260
|
+
/** @deprecated */
|
|
1261
|
+
class LimbleTreeLegacyModule {
|
|
1262
|
+
}
|
|
1263
|
+
LimbleTreeLegacyModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: LimbleTreeLegacyModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
1264
|
+
LimbleTreeLegacyModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.2.12", ngImport: i0, type: LimbleTreeLegacyModule, imports: [LimbleTreeRootComponent], exports: [LimbleTreeRootComponent] });
|
|
1265
|
+
LimbleTreeLegacyModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: LimbleTreeLegacyModule, providers: [LegacyTree], imports: [LimbleTreeRootComponent] });
|
|
1266
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: LimbleTreeLegacyModule, decorators: [{
|
|
1267
|
+
type: NgModule,
|
|
1268
|
+
args: [{
|
|
1269
|
+
declarations: [],
|
|
1270
|
+
imports: [LimbleTreeRootComponent],
|
|
1271
|
+
providers: [LegacyTree],
|
|
1272
|
+
exports: [LimbleTreeRootComponent]
|
|
1273
|
+
}]
|
|
1274
|
+
}] });
|
|
1275
|
+
|
|
1276
|
+
class LimbleTreeModule {
|
|
1277
|
+
}
|
|
1278
|
+
LimbleTreeModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: LimbleTreeModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
1279
|
+
LimbleTreeModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.2.12", ngImport: i0, type: LimbleTreeModule, imports: [LimbleTreeLegacyModule, TreeCollapseModule, TreeDragAndDropModule], exports: [LimbleTreeLegacyModule, TreeCollapseModule, TreeDragAndDropModule] });
|
|
1280
|
+
LimbleTreeModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: LimbleTreeModule, providers: [TreeService], imports: [LimbleTreeLegacyModule, TreeCollapseModule, TreeDragAndDropModule, LimbleTreeLegacyModule, TreeCollapseModule, TreeDragAndDropModule] });
|
|
1281
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: LimbleTreeModule, decorators: [{
|
|
1282
|
+
type: NgModule,
|
|
1283
|
+
args: [{
|
|
1284
|
+
declarations: [],
|
|
1285
|
+
imports: [LimbleTreeLegacyModule, TreeCollapseModule, TreeDragAndDropModule],
|
|
1286
|
+
providers: [TreeService],
|
|
1287
|
+
exports: [LimbleTreeLegacyModule, TreeCollapseModule, TreeDragAndDropModule]
|
|
1288
|
+
}]
|
|
1289
|
+
}] });
|
|
1290
|
+
|
|
1291
|
+
/*
|
|
1292
|
+
* Public API Surface of limble-tree
|
|
1293
|
+
*/
|
|
1294
|
+
|
|
1295
|
+
/**
|
|
1296
|
+
* Generated bundle index. Do not edit.
|
|
1297
|
+
*/
|
|
1298
|
+
|
|
1299
|
+
export { DragEndEvent, DragStartEvent, DraggableDirective, DragoverNoChangeDetectDirective, DropEvent, GraftEvent, LegacyTree, LimbleTreeLegacyModule, LimbleTreeModule, LimbleTreeRootComponent, PruneEvent, TreeBranch, TreeCollapseModule, TreeCollapseService, TreeDragAndDropModule, TreeDragAndDropService, TreeError, TreeRoot, TreeService, config };
|
|
1300
|
+
//# sourceMappingURL=limble-limble-tree.mjs.map
|