@limble/limble-tree 1.0.0-alpha.1 → 1.0.0-alpha.2
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 +446 -17
- package/esm2020/lib/components/branch/branch.component.mjs +6 -14
- package/esm2020/lib/components/root/root.component.mjs +3 -4
- package/esm2020/lib/core/branch-options.interface.mjs +1 -1
- package/esm2020/lib/core/configuration/tree-options.interface.mjs +1 -1
- package/esm2020/lib/core/relationship.interface.mjs +1 -1
- package/esm2020/lib/core/tree-branch/branch-controller.mjs +99 -0
- package/esm2020/lib/core/tree-branch/tree-branch.mjs +81 -103
- package/esm2020/lib/core/tree-node-base.mjs +10 -9
- package/esm2020/lib/core/tree-root/root-controller.mjs +42 -0
- package/esm2020/lib/core/tree-root/tree-root.mjs +43 -27
- package/esm2020/lib/events/drag/drag-end-event.mjs +1 -1
- package/esm2020/lib/events/drag/drop-event.mjs +1 -1
- package/esm2020/lib/events/general/destruction-event.mjs +12 -0
- package/esm2020/lib/events/general/index.mjs +2 -0
- package/esm2020/lib/events/index.mjs +2 -1
- package/esm2020/lib/extras/collapse/collapse.mjs +2 -2
- package/esm2020/lib/extras/drag-and-drop/drag-and-drop.mjs +6 -10
- package/esm2020/lib/extras/drag-and-drop/draggable.directive.mjs +1 -1
- package/esm2020/lib/extras/drag-and-drop/dropzone-renderer.mjs +9 -7
- package/esm2020/lib/legacy/legacy-tree.mjs +28 -29
- package/esm2020/lib/structure/branchable.interface.mjs +1 -1
- package/esm2020/lib/structure/component-container.interface.mjs +2 -0
- package/esm2020/lib/structure/index.mjs +2 -4
- package/esm2020/lib/structure/tree-branch-node.interface.mjs +1 -1
- package/esm2020/lib/structure/tree-node.interface.mjs +1 -1
- package/fesm2015/limble-limble-tree.mjs +317 -193
- package/fesm2015/limble-limble-tree.mjs.map +1 -1
- package/fesm2020/limble-limble-tree.mjs +315 -189
- package/fesm2020/limble-limble-tree.mjs.map +1 -1
- package/lib/core/branch-options.interface.d.ts +1 -1
- package/lib/core/configuration/tree-options.interface.d.ts +23 -26
- package/lib/core/relationship.interface.d.ts +2 -3
- package/lib/core/tree-branch/branch-controller.d.ts +25 -0
- package/lib/core/tree-branch/tree-branch.d.ts +18 -18
- package/lib/core/tree-node-base.d.ts +4 -5
- package/lib/core/tree-root/root-controller.d.ts +19 -0
- package/lib/core/tree-root/tree-root.d.ts +11 -9
- package/lib/events/drag/drag-end-event.d.ts +5 -6
- package/lib/events/drag/drop-event.d.ts +3 -6
- package/lib/events/general/destruction-event.d.ts +8 -0
- package/lib/events/general/index.d.ts +1 -0
- package/lib/events/index.d.ts +1 -0
- package/lib/extras/drag-and-drop/drag-and-drop.d.ts +2 -3
- package/lib/extras/drag-and-drop/draggable.directive.d.ts +1 -1
- package/lib/structure/branchable.interface.d.ts +0 -1
- package/lib/structure/component-container.interface.d.ts +8 -0
- package/lib/structure/index.d.ts +1 -3
- package/lib/structure/tree-branch-node.interface.d.ts +2 -2
- package/lib/structure/tree-node.interface.d.ts +3 -1
- package/package.json +1 -1
- package/esm2020/lib/structure/container-tree-node.interface.mjs +0 -2
- package/esm2020/lib/structure/content-container.interface.mjs +0 -2
- package/esm2020/lib/structure/tree-root.node.interface.mjs +0 -2
- package/lib/structure/container-tree-node.interface.d.ts +0 -3
- package/lib/structure/content-container.interface.d.ts +0 -3
- package/lib/structure/tree-root.node.interface.d.ts +0 -2
package/README.md
CHANGED
|
@@ -8,35 +8,464 @@ An Angular library for building visual tree structures. Built and used by the te
|
|
|
8
8
|
|
|
9
9
|
Features:
|
|
10
10
|
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
11
|
+
- Allows any number of different components to be rendered in the same tree.
|
|
12
|
+
- Collapsible tree branches
|
|
13
|
+
- Move branches around both programmatically and with built-in drag-and-drop.
|
|
14
|
+
- Branches can be moved between trees.
|
|
15
|
+
- No limit on tree depth or size.
|
|
16
|
+
- Recently redesigned to allow better performance with large/complex trees.
|
|
15
17
|
|
|
16
18
|
## Installation
|
|
17
19
|
|
|
18
|
-
```
|
|
20
|
+
```bash
|
|
19
21
|
npm install @limble/limble-tree
|
|
20
22
|
```
|
|
21
23
|
|
|
22
24
|
## Basic Usage
|
|
23
25
|
|
|
24
|
-
|
|
26
|
+
A basic tree is very easy to set up.
|
|
27
|
+
|
|
28
|
+
### Step 1
|
|
29
|
+
|
|
30
|
+
Import the limble-tree module into your own Angular module or standalone component.
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
import { NgModule } from "@angular/core";
|
|
34
|
+
import { LimbleTreeModule } from "@limble/limble-tree";
|
|
35
|
+
|
|
36
|
+
@NgModule({
|
|
37
|
+
imports: [LimbleTreeModule]
|
|
38
|
+
})
|
|
39
|
+
export class AppModule {}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
or
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
import { Component } from "@angular/core";
|
|
46
|
+
import { LimbleTreeModule } from "@limble/limble-tree";
|
|
47
|
+
|
|
48
|
+
@Component({
|
|
49
|
+
standalone: true,
|
|
50
|
+
imports: [LimbleTreeModule],
|
|
51
|
+
template: `<div></div>`
|
|
52
|
+
})
|
|
53
|
+
export class MyComponent {}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Step 2
|
|
57
|
+
|
|
58
|
+
Add a template variable to the HTML element in which the tree should be rendered.
|
|
59
|
+
|
|
60
|
+
```html
|
|
61
|
+
<div #treeContainer></div>
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Step 3
|
|
65
|
+
|
|
66
|
+
Use `@ViewChild` to get the `ViewContainerRef` of that element.
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
@ViewChild("treeContainer", { read: ViewContainerRef }) treeContainer?: ViewContainerRef;
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Step 4
|
|
73
|
+
|
|
74
|
+
Inject TreeService into your component.
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
constructor(private readonly treeService: TreeService) {}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Step 5
|
|
81
|
+
|
|
82
|
+
In the `ngAfterViewInit` lifecycle hook, call `createEmptyTree()`, passing in the ViewContainerRef obtained in step 3.
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
protected tree?: TreeRoot<MyTreeContentComponent>;
|
|
86
|
+
|
|
87
|
+
public ngAfterViewInit(): void {
|
|
88
|
+
this.tree = this.treeService.createEmptyTree<MyTreeContentComponent>(this.treeContainer);
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Step 6
|
|
93
|
+
|
|
94
|
+
Render components in the tree by calling `grow()`.
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
//Renders four instances of the MyTreeContentComponent; the fourth is nested under the third.
|
|
98
|
+
const branch1 = this.tree.grow(MyTreeContentComponent);
|
|
99
|
+
const branch2 = this.tree.grow(MyTreeContentComponent);
|
|
100
|
+
const branch3 = this.tree.grow(MyTreeContentComponent);
|
|
101
|
+
const branch3a = branch3.grow(MyTreContentComponent);
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Step 7
|
|
105
|
+
|
|
106
|
+
That's it, you've built your first limble-tree. Here is the full component code we just built:
|
|
107
|
+
|
|
108
|
+
```typescript
|
|
109
|
+
import {
|
|
110
|
+
Component,
|
|
111
|
+
AfterViewInit,
|
|
112
|
+
ViewChild,
|
|
113
|
+
ViewContainerRef
|
|
114
|
+
} from "@angular/core";
|
|
115
|
+
import { LimbleTreeModule, TreeRoot } from "@limble/limble-tree";
|
|
116
|
+
import { MyTreeContentComponent } from "somewhere in your filesystem";
|
|
117
|
+
|
|
118
|
+
@Component({
|
|
119
|
+
standalone: true,
|
|
120
|
+
imports: [LimbleTreeModule],
|
|
121
|
+
template: `<div #treeContainer></div>`
|
|
122
|
+
})
|
|
123
|
+
export class MyComponent implements AfterViewInit {
|
|
124
|
+
@ViewChild("treeContainer", { read: ViewContainerRef })
|
|
125
|
+
treeContainer?: ViewContainerRef;
|
|
126
|
+
|
|
127
|
+
protected tree?: TreeRoot<MyTreeContentComponent>;
|
|
128
|
+
|
|
129
|
+
public constructor(private readonly treeService: TreeService) {}
|
|
130
|
+
|
|
131
|
+
public ngAfterViewInit(): void {
|
|
132
|
+
this.tree = this.treeService.createEmptyTree<MyTreeContentComponent>(
|
|
133
|
+
this.treeContainer
|
|
134
|
+
);
|
|
135
|
+
// Renders four instances of the MyTreeContentComponent;
|
|
136
|
+
// the fourth is nested under the third.
|
|
137
|
+
const branch1 = this.tree.grow(MyTreeContentComponent);
|
|
138
|
+
const branch2 = this.tree.grow(MyTreeContentComponent);
|
|
139
|
+
const branch3 = this.tree.grow(MyTreeContentComponent);
|
|
140
|
+
const branch3a = branch3.grow(MyTreContentComponent);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Communicating With Your Components
|
|
146
|
+
|
|
147
|
+
### Inputs and Outputs
|
|
148
|
+
|
|
149
|
+
If the components passed to `grow()` require inputs, or if you want to watch for output events, you can pass those things into the optional second parameter.
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
tree.grow(MyTreeContentComponent, {
|
|
153
|
+
inputBindings: { myInput1: "hello world", myInput2: 1000 },
|
|
154
|
+
outputBindings: {
|
|
155
|
+
myOutput: (event) => {
|
|
156
|
+
/* Do stuff */
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
The inputBindings object tells the tree to pass "hello world" into the component field named `myInput1`. Similarly, the tree will pass 1000 into the component field named "myInput2".
|
|
163
|
+
|
|
164
|
+
The outputBindings object works similarly, but instead of passing values, it registers callbacks to run when the specified outputs emit events. In the example, the arrow function will be run each time the field named `myOutput` emits a value.
|
|
165
|
+
|
|
166
|
+
### Special `treeBranch` Input
|
|
167
|
+
|
|
168
|
+
No matter what you decide to pass through inputs, if anything, the tree will always automatically pass a TreeBranch object into the component. That object can be accessed within the component by declaring a `treeBranch` Input property.
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
@Input() treeBranch?: TreeBranch<MyTreeContentComponent>;
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
This treeBranch object can be very useful for determining things like where the component lives in the tree, if it has any child branches, etc. It is also used for many of the more advanced features described elsewhere in this document.
|
|
175
|
+
|
|
176
|
+
### Passing Custom Data Through The `treeBranch` Input Using `meta`
|
|
177
|
+
|
|
178
|
+
If desired, you can add custom data to the treeBranch object associated with your rendered components. You can do this using another property of the second parameter of `grow()`, called `meta`.
|
|
179
|
+
|
|
180
|
+
```typescript
|
|
181
|
+
tree.grow(MyTreeContentComponent, {
|
|
182
|
+
meta: { myCustomDataField: "Hello World!" }
|
|
183
|
+
});
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
The value of `meta` can be accessed within your rendered component by calling `this.treeBranch.meta()`.
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
@Input() treeBranch?: TreeBranch<MyTreeContentComponent>;
|
|
190
|
+
|
|
191
|
+
public ngOnInit(): void {
|
|
192
|
+
console.log(this.treeBranch?.meta()) // outputs `{ myCustomDataField: "Hello World!" }`
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## Indentation
|
|
197
|
+
|
|
198
|
+
By default, each level of the tree beyond the first will be indented an additional 16px. This value is configurable:
|
|
199
|
+
|
|
200
|
+
```typescript
|
|
201
|
+
treeService.createEmptyTree(this.treeContainer, { indentation: 32 });
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## Collapsing Branches
|
|
205
|
+
|
|
206
|
+
Tree branches which have descendant branches can be collapsed, temporarily removing its descendants from the tree. The descendants can be grafted back into the tree later, as if they were never removed.
|
|
207
|
+
|
|
208
|
+
To collapse a branch, simply inject the TreeCollapseService into your component and call `collapse()`, passing in the branch to be collapsed. To restore the hidden branches, call `expand()`, passing in the same branch that was passed to `collapse()`
|
|
209
|
+
|
|
210
|
+
```typescript
|
|
211
|
+
constructor(private readonly collapseService: TreeCollapseService) {}
|
|
212
|
+
|
|
213
|
+
public ngAfterViewInit(): void {
|
|
214
|
+
this.tree = this.treeService.createEmptyTree<MyTreeContentComponent>(
|
|
215
|
+
this.treeContainer
|
|
216
|
+
);
|
|
217
|
+
// Renders four instances of the MyTreeContentComponent;
|
|
218
|
+
// the fourth is nested under the third.
|
|
219
|
+
const branch1 = this.tree.grow(MyTreeContentComponent);
|
|
220
|
+
const branch2 = this.tree.grow(MyTreeContentComponent);
|
|
221
|
+
const branch3 = this.tree.grow(MyTreeContentComponent);
|
|
222
|
+
const branch3a = branch3.grow(MyTreContentComponent);
|
|
223
|
+
|
|
224
|
+
//Hides the fourth branch
|
|
225
|
+
this.collapseService.collapse(branch3);
|
|
226
|
+
|
|
227
|
+
//restores the fourth branch to its original place after 2 seconds have passed.
|
|
228
|
+
setTimeout(() => {
|
|
229
|
+
this.collapseService.expand(branch3);
|
|
230
|
+
}, 2000);
|
|
231
|
+
}
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
A branch can be configured to be collapsed by default, which means that any children grown onto it will not be visible until `expand()` is called.
|
|
235
|
+
|
|
236
|
+
```typescript
|
|
237
|
+
constructor(private readonly collapseService: TreeCollapseService) {}
|
|
238
|
+
|
|
239
|
+
public ngAfterViewInit(): void {
|
|
240
|
+
this.tree = this.treeService.createEmptyTree<MyTreeContentComponent>(
|
|
241
|
+
this.treeContainer
|
|
242
|
+
);
|
|
243
|
+
// Renders four instances of the MyTreeContentComponent;
|
|
244
|
+
// the fourth is nested under the third.
|
|
245
|
+
const branch1 = this.tree.grow(MyTreeContentComponent);
|
|
246
|
+
const branch2 = this.tree.grow(MyTreeContentComponent);
|
|
247
|
+
const branch3 = this.tree.grow(MyTreeContentComponent, {defaultCollapsed: true});
|
|
248
|
+
const branch3a = branch3.grow(MyTreContentComponent); // this branch will be created but not rendered
|
|
249
|
+
|
|
250
|
+
//renders the fourth branch after 2 seconds have passed.
|
|
251
|
+
setTimeout(() => {
|
|
252
|
+
this.collapseService.expand(branch3);
|
|
253
|
+
}, 2000);
|
|
254
|
+
}
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
You can check if a branch can be expanded using the collapse service's `isCollapsed()` method.
|
|
258
|
+
|
|
259
|
+
## Moving Branches Programmatically
|
|
260
|
+
|
|
261
|
+
Branches can be moved around, both within a single tree and between different trees.
|
|
262
|
+
|
|
263
|
+
```typescript
|
|
264
|
+
public ngAfterViewInit(): void {
|
|
265
|
+
this.tree1 = this.treeService.createEmptyTree<MyTreeContentComponent>(
|
|
266
|
+
this.treeContainer1
|
|
267
|
+
);
|
|
268
|
+
// Renders four instances of the MyTreeContentComponent;
|
|
269
|
+
// the fourth is nested under the third.
|
|
270
|
+
const branch1 = this.tree1.grow(MyTreeContentComponent);
|
|
271
|
+
const branch2 = this.tree1.grow(MyTreeContentComponent);
|
|
272
|
+
const branch3 = this.tree1.grow(MyTreeContentComponent);
|
|
273
|
+
const branch3a = branch3.grow(MyTreContentComponent);
|
|
274
|
+
|
|
275
|
+
setTimeout(() => {
|
|
276
|
+
//moves branch1 so it is now the second child of branch3
|
|
277
|
+
branch1.graftTo(branch3);
|
|
278
|
+
}, 2000);
|
|
279
|
+
|
|
280
|
+
setTimeout(() => {
|
|
281
|
+
// moves branch1 back to its original position.
|
|
282
|
+
branch1.graftTo(this.tree1, 0);
|
|
283
|
+
}, 4000);
|
|
284
|
+
|
|
285
|
+
setTimeout(() => {
|
|
286
|
+
this.tree2 = this.treeService.createEmptyTree<MyTreeContentComponent>(
|
|
287
|
+
this.treeContainer2
|
|
288
|
+
);
|
|
289
|
+
// moves branch1 to a different tree
|
|
290
|
+
branch1.graftTo(this.tree2);
|
|
291
|
+
}, 8000);
|
|
292
|
+
}
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
A branch can also be removed from a tree without immediately grafting it to a new position.
|
|
296
|
+
|
|
297
|
+
```typescript
|
|
298
|
+
public ngAfterViewInit(): void {
|
|
299
|
+
this.tree = this.treeService.createEmptyTree<MyTreeContentComponent>(
|
|
300
|
+
this.treeContainer
|
|
301
|
+
);
|
|
302
|
+
// Renders four instances of the MyTreeContentComponent;
|
|
303
|
+
// the fourth is nested under the third.
|
|
304
|
+
const branch1 = this.tree.grow(MyTreeContentComponent);
|
|
305
|
+
const branch2 = this.tree.grow(MyTreeContentComponent);
|
|
306
|
+
const branch3 = this.tree.grow(MyTreeContentComponent);
|
|
307
|
+
const branch3a = branch3.grow(MyTreContentComponent);
|
|
308
|
+
|
|
309
|
+
//removes branch1 from the tree after 2 seconds
|
|
310
|
+
setTimeout(() => {
|
|
311
|
+
branch1.prune();
|
|
312
|
+
}, 2000);
|
|
313
|
+
|
|
314
|
+
//restores branch1 to its original position after an additional 2 seconds
|
|
315
|
+
setTimeout(() => {
|
|
316
|
+
branch1.graftTo(this.tree, 0);
|
|
317
|
+
}, 4000);
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
Both the `prune()` and `graftTo()` methods will include all of the children of the branch as well. For example, pruning a branch that has 3 child branches will remove the parent as well as all three children; grafting the parent back into a tree will also graft the children into that tree, retaining their position as children of the moved parent.
|
|
321
|
+
|
|
322
|
+
Note: use `destroy()` rather than `prune()` when you wish to completely delete a branch. See "Destroying Trees and Branches" below.
|
|
323
|
+
|
|
324
|
+
## Moving Branches With Drag-And-Drop
|
|
325
|
+
|
|
326
|
+
Drag and drop functionality is easy to use. Simply add the `[limbleTreeDraggable]` directive to an element of your rendered component, and pass it that component's associated TreeBranch. When the user clicks and drags the element, the branch will be pruned from the tree and dragged with the mouse.
|
|
327
|
+
|
|
328
|
+
```html
|
|
329
|
+
<div [limbleTreeDraggable]="treeBranch">Drag Me!</div>
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
As the user drags the branch over other branches of the tree, dropzones will appear to indicate where the dragged branch may be placed. Dropping into a dropzone will graft the dragged branch at that location.
|
|
333
|
+
|
|
334
|
+
### Configurable Restrictions For Drag-And-Drop
|
|
335
|
+
|
|
336
|
+
A tree can be configured to disallow certain branches from...
|
|
337
|
+
|
|
338
|
+
1. being dragged at all
|
|
339
|
+
2. being dropped at specific locations in the tree
|
|
340
|
+
|
|
341
|
+
When calling `createEmptyTree()`, there are three options that can be passed to the second parameter to control these restrictions. There are no restrictions by default.
|
|
342
|
+
|
|
343
|
+
```typescript
|
|
344
|
+
public ngAfterViewInit(): void {
|
|
345
|
+
this.tree = this.treeService.createEmptyTree<MyTreeContentComponent>(
|
|
346
|
+
this.treeContainer,
|
|
347
|
+
{
|
|
348
|
+
// Prevents dragging branches which have less than three children
|
|
349
|
+
allowDragging: (treeBranch) => treeBranch.branches().length < 3,
|
|
350
|
+
// Prevents drops on first-level branches
|
|
351
|
+
allowDrop: (source, parent, index) => parent.parent() !== undefined,
|
|
352
|
+
// Does not allow any branches to be dropped under a branch whose metaData property `noChildren` is set to `false`
|
|
353
|
+
allowNesting: (treeBranch) => treeBranch.meta().noChildren === false
|
|
354
|
+
}
|
|
355
|
+
);
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
These options only apply to drag-and-drop functionality. They do not restrict programmatic movement of branches, such as when using the `prune()` or `graftTo()` methods.
|
|
359
|
+
|
|
360
|
+
More details about these configuration options can be found in `tree-options.interface.ts`.
|
|
361
|
+
|
|
362
|
+
## Watching For Tree Events
|
|
363
|
+
|
|
364
|
+
Both the TreeBranch and TreeRoot objects will emit information when certain events occur. These events can be captured by subscribing to the observable returned by the `events()` method.
|
|
365
|
+
|
|
366
|
+
```typescript
|
|
367
|
+
public ngAfterViewInit(): void {
|
|
368
|
+
this.tree = this.treeService.createEmptyTree<MyTreeContentComponent>(
|
|
369
|
+
this.treeContainer
|
|
370
|
+
);
|
|
371
|
+
this.tree.events().subscribe((event) => {
|
|
372
|
+
console.log(event.type());
|
|
373
|
+
});
|
|
374
|
+
const branch1 = this.tree.grow(MyTreeContentComponent); // will output "graft"
|
|
375
|
+
const branch2 = this.tree.grow(MyTreeContentComponent); // will output "graft"
|
|
376
|
+
const branch3 = branch2.grow(MyTreeContentComponent); //will output "graft"
|
|
377
|
+
this.tree.destroy(); //will output "destruction" four times; one for each branch, and one for the root.
|
|
378
|
+
}
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
Events bubble up the tree. So subscribing to the root's `events()` observable will capture all tree events for that tree. Subscribing to the `events()` observable of a branch will capture all tree events for that branch and its descendants.
|
|
382
|
+
|
|
383
|
+
Below is a list of event types that are currently emitted by the tree.
|
|
384
|
+
|
|
385
|
+
- drag start
|
|
386
|
+
- drop
|
|
387
|
+
- drag end
|
|
388
|
+
- prune
|
|
389
|
+
- graft
|
|
390
|
+
- destruction
|
|
391
|
+
|
|
392
|
+
Each event contains applicable information about the event, such as the nodes involved, position in the tree, etc.
|
|
393
|
+
|
|
394
|
+
## Traversing The Tree
|
|
395
|
+
|
|
396
|
+
### Parents and Children
|
|
397
|
+
|
|
398
|
+
Trees are doubly-linked, meaning that each node in the tree holds a pointer to its parent and a pointer to each of its children. These pointers are accessed using the `parent()` and `branches()` methods, respectively. The order of child branches is maintained. The `getBranch()` method takes an index as an argument and returns the branch at that index. A branch's position relative to its siblings is obtained using the `index()` method.
|
|
399
|
+
|
|
400
|
+
Unlike TreeBranch instances, a TreeRoot does not have a `parent()` or `index()` method, but it does have a `branches()` and `getBranch()` methods.
|
|
401
|
+
|
|
402
|
+
TreeBranch instances have a method `root()`, which returns the root of their current tree. TreeRoot instances also have this method, and in that case it always returns itself.
|
|
403
|
+
|
|
404
|
+
```typescript
|
|
405
|
+
public ngAfterViewInit(): void {
|
|
406
|
+
this.tree = this.treeService.createEmptyTree<MyTreeContentComponent>(
|
|
407
|
+
this.treeContainer
|
|
408
|
+
);
|
|
409
|
+
this.tree.events().subscribe((event) => {
|
|
410
|
+
console.log(event.type());
|
|
411
|
+
});
|
|
412
|
+
const branch1 = this.tree.grow(MyTreeContentComponent);
|
|
413
|
+
const branch2 = this.tree.grow(MyTreeContentComponent);
|
|
414
|
+
const branch2a = branch2.grow(MyTreeContentComponent);
|
|
415
|
+
const branch2b = branch2.grow(MyTreeContentComponent);
|
|
416
|
+
const branch2a1 = branch2a.grow(MyTreeContentComponent);
|
|
417
|
+
const branch2a1 = branch2a.grow(MyTreeContentComponent);
|
|
418
|
+
|
|
419
|
+
//All of these expressions are true
|
|
420
|
+
assert(branch2b.parent() === branch2);
|
|
421
|
+
assert(branch2b.index() === 1);
|
|
422
|
+
assert(branch2.branches()[1] === branch2b);
|
|
423
|
+
assert(branch2a1.branches().length === 0);
|
|
424
|
+
assert(branch1.parent() === this.tree);
|
|
425
|
+
assert(this.tree.getBranch(2) === branch2);
|
|
426
|
+
assert(branch2a1.root() === this.tree);
|
|
427
|
+
}
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
### Traversal Utility Methods
|
|
431
|
+
|
|
432
|
+
There are a couple other methods used to traverse the tree.
|
|
433
|
+
|
|
434
|
+
- `traverse()` traverses the tree in [depth-first pre-order](https://en.wikipedia.org/wiki/Tree_traversal#Pre-order,_NLR) and executes a provided callback on each node.
|
|
435
|
+
- `plot()` traverses the tree and returns a many-dimensional [Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map)representing the shape of the tree.
|
|
436
|
+
|
|
437
|
+
### Get Branch's Current Location in the Tree
|
|
438
|
+
|
|
439
|
+
You can call `position()` on a TreeBranch to get an array of indexes, indicating the path from the root to that branch.
|
|
440
|
+
|
|
441
|
+
Example: If `position()` returns [2, 2, 4], that means the branch is a great-grandchild of the root (three elements == three levels deep), and the branch could be accessed like so:
|
|
442
|
+
|
|
443
|
+
```typescript
|
|
444
|
+
root.getBranch(2).getBranch(2).getBranch(4);
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
## Destroying Trees And Branches
|
|
448
|
+
|
|
449
|
+
The `destroy()` method must be called on a TreeRoot in order for its resources to be properly released. Failing to do so will cause memory leaks and other performance problems.
|
|
450
|
+
|
|
451
|
+
Branches also have a `destroy()` method. Calling `destroy()` on the TreeRoot will automatically call the `destroy()` method of each branch in the tree, including branches that have been collapsed.
|
|
25
452
|
|
|
26
|
-
|
|
453
|
+
Branches that have been otherwise pruned are not part of any tree; their `destroy()` method must be called manually in order to release their resources. Calling a branch's `destroy()` method will automatically call the `destroy()` method of each descendant branch, including descendants that are collapsed.
|
|
27
454
|
|
|
28
|
-
|
|
455
|
+
Destroyed roots and branches have very limited functionality. Many methods will simply throw an error if the instance has been previously destroyed. You can check if a node is destroyed with the `isDestroyed()` method.
|
|
29
456
|
|
|
30
|
-
##
|
|
457
|
+
## Accessing Underlying Structures
|
|
31
458
|
|
|
32
|
-
|
|
459
|
+
There are methods on TreeBranch and TreeRoot instances which grant access to underlying structures. We recommend only using these in advanced scenarios. They are not fully documented here at this time.
|
|
33
460
|
|
|
34
|
-
|
|
461
|
+
- detectChanges()
|
|
462
|
+
- dispatch()
|
|
463
|
+
- getBranchesContainer()
|
|
464
|
+
- getComponentInstance()
|
|
465
|
+
- getHostView()
|
|
466
|
+
- getNativeElement()
|
|
467
|
+
- getUserlandComponentRef()
|
|
35
468
|
|
|
36
|
-
|
|
469
|
+
## Development and Contributions
|
|
37
470
|
|
|
38
|
-
-
|
|
39
|
-
- Drop
|
|
40
|
-
- Drag End
|
|
41
|
-
- Prune
|
|
42
|
-
- Graft
|
|
471
|
+
See the readme in our [Github repository](https://github.com/LimbleCMMS/limble-tree).
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { CommonModule } from "@angular/common";
|
|
2
2
|
import { Component, EventEmitter, Input, NgZone, Output, ViewChild, ViewChildren, ViewContainerRef } from "@angular/core";
|
|
3
3
|
import { map, merge } from "rxjs";
|
|
4
|
-
import { TreeError } from "../../errors";
|
|
5
4
|
import { DropzoneComponent } from "../dropzone/dropzone.component";
|
|
6
5
|
import { DragoverNoChangeDetectDirective } from "../../extras/drag-and-drop/dragover-no-change-detect";
|
|
6
|
+
import { assert } from "../../../shared/assert";
|
|
7
7
|
import * as i0 from "@angular/core";
|
|
8
8
|
export class BranchComponent {
|
|
9
9
|
constructor(appRef) {
|
|
@@ -18,22 +18,14 @@ export class BranchComponent {
|
|
|
18
18
|
this.showLateralDropzone = false;
|
|
19
19
|
}
|
|
20
20
|
ngAfterViewInit() {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
if (this.contentToHost === undefined) {
|
|
25
|
-
throw new TreeError("'content' is a required input");
|
|
26
|
-
}
|
|
21
|
+
assert(this.contentContainer !== undefined);
|
|
22
|
+
assert(this.contentToHost !== undefined);
|
|
27
23
|
this.hostedContent = this.contentContainer.createComponent(this.contentToHost);
|
|
28
24
|
this.contentCreated.emit(this.hostedContent.instance);
|
|
29
|
-
|
|
30
|
-
throw new Error("querylist not defined");
|
|
31
|
-
}
|
|
25
|
+
assert(this.dropzones !== undefined);
|
|
32
26
|
const inner = this.dropzones.get(0);
|
|
33
27
|
const lateral = this.dropzones.get(1);
|
|
34
|
-
|
|
35
|
-
throw new Error("dropzones not defined");
|
|
36
|
-
}
|
|
28
|
+
assert(inner !== undefined && lateral !== undefined);
|
|
37
29
|
merge(inner.dropped.pipe(map(() => "inner")), lateral.dropped.pipe(map(() => "lateral"))).subscribe(this.dropped);
|
|
38
30
|
this.hostedContent.changeDetectorRef.detectChanges();
|
|
39
31
|
}
|
|
@@ -84,4 +76,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
|
|
|
84
76
|
}], dropped: [{
|
|
85
77
|
type: Output
|
|
86
78
|
}] } });
|
|
87
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
79
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnJhbmNoLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2xpbWJsZS10cmVlL3NyYy9saWIvY29tcG9uZW50cy9icmFuY2gvYnJhbmNoLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2xpbWJsZS10cmVlL3NyYy9saWIvY29tcG9uZW50cy9icmFuY2gvYnJhbmNoLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBR0osU0FBUyxFQUVULFlBQVksRUFDWixLQUFLLEVBQ0wsTUFBTSxFQUVOLE1BQU0sRUFHTixTQUFTLEVBQ1QsWUFBWSxFQUNaLGdCQUFnQixFQUNsQixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsR0FBRyxFQUFFLEtBQUssRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUNsQyxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUduRSxPQUFPLEVBQUUsK0JBQStCLEVBQUUsTUFBTSxzREFBc0QsQ0FBQztBQUN2RyxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7O0FBU2hELE1BQU0sT0FBTyxlQUFlO0lBc0J6QixZQUFvQyxNQUFzQjtRQUF0QixXQUFNLEdBQU4sTUFBTSxDQUFnQjtRQWxCMUQsc0JBQWlCLEdBQWlDLFNBQVMsQ0FBQztRQUU1RCxxQkFBZ0IsR0FBaUMsU0FBUyxDQUFDO1FBQzFCLGNBQVMsR0FFekIsU0FBUyxDQUFDO1FBSVIsbUJBQWMsR0FBRyxJQUFJLFlBQVksRUFBSyxDQUFDO1FBQ3ZDLGtCQUFhLEdBQUcsSUFBSSxZQUFZLEVBQXFCLENBQUM7UUFDdEQsWUFBTyxHQUFHLElBQUksWUFBWSxFQUF1QixDQUFDO1FBRTlELHNCQUFpQixHQUFZLEtBQUssQ0FB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L0IsTUFBTTtnQkFDWSxPQUFPO3NCQUF6QixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSBcIkBhbmd1bGFyL2NvbW1vblwiO1xuaW1wb3J0IHtcbiAgIEFmdGVyVmlld0luaXQsXG4gICBBcHBsaWNhdGlvblJlZixcbiAgIENvbXBvbmVudCxcbiAgIENvbXBvbmVudFJlZixcbiAgIEV2ZW50RW1pdHRlcixcbiAgIElucHV0LFxuICAgTmdab25lLFxuICAgT25EZXN0cm95LFxuICAgT3V0cHV0LFxuICAgUXVlcnlMaXN0LFxuICAgVHlwZSxcbiAgIFZpZXdDaGlsZCxcbiAgIFZpZXdDaGlsZHJlbixcbiAgIFZpZXdDb250YWluZXJSZWZcbn0gZnJvbSBcIkBhbmd1bGFyL2NvcmVcIjtcbmltcG9ydCB7IG1hcCwgbWVyZ2UgfSBmcm9tIFwicnhqc1wiO1xuaW1wb3J0IHsgRHJvcHpvbmVDb21wb25lbnQgfSBmcm9tIFwiLi4vZHJvcHpvbmUvZHJvcHpvbmUuY29tcG9uZW50XCI7XG5pbXBvcnQgeyBIb3N0Q29tcG9uZW50IH0gZnJvbSBcIi4uL2hvc3QtY29tcG9uZW50LmludGVyZmFjZVwiO1xuaW1wb3J0IHsgTm9kZUNvbXBvbmVudCB9IGZyb20gXCIuLi9ub2RlLWNvbXBvbmVudC5pbnRlcmZhY2VcIjtcbmltcG9ydCB7IERyYWdvdmVyTm9DaGFuZ2VEZXRlY3REaXJlY3RpdmUgfSBmcm9tIFwiLi4vLi4vZXh0cmFzL2RyYWctYW5kLWRyb3AvZHJhZ292ZXItbm8tY2hhbmdlLWRldGVjdFwiO1xuaW1wb3J0IHsgYXNzZXJ0IH0gZnJvbSBcIi4uLy4uLy4uL3NoYXJlZC9hc3NlcnRcIjtcblxuQENvbXBvbmVudCh7XG4gICBzdGFuZGFsb25lOiB0cnVlLFxuICAgc2VsZWN0b3I6IFwiYnJhbmNoXCIsXG4gICB0ZW1wbGF0ZVVybDogXCIuL2JyYW5jaC5jb21wb25lbnQuaHRtbFwiLFxuICAgc3R5bGVVcmxzOiBbXCIuL2JyYW5jaC5jb21wb25lbnQuc2Nzc1wiXSxcbiAgIGltcG9ydHM6IFtDb21tb25Nb2R1bGUsIERyb3B6b25lQ29tcG9uZW50LCBEcmFnb3Zlck5vQ2hhbmdlRGV0ZWN0RGlyZWN0aXZlXVxufSlcbmV4cG9ydCBjbGFzcyBCcmFuY2hDb21wb25lbnQ8VD5cbiAgIGltcGxlbWVudHMgTm9kZUNvbXBvbmVudCwgSG9zdENvbXBvbmVudDxUPiwgQWZ0ZXJWaWV3SW5pdCwgT25EZXN0cm95XG57XG4gICBAVmlld0NoaWxkKFwiYnJhbmNoZXNDb250YWluZXJcIiwgeyByZWFkOiBWaWV3Q29udGFpbmVyUmVmIH0pXG4gICBicmFuY2hlc0NvbnRhaW5lcjogVmlld0NvbnRhaW5lclJlZiB8IHVuZGVmaW5lZCA9IHVuZGVmaW5lZDtcbiAgIEBWaWV3Q2hpbGQoXCJjb250ZW50Q29udGFpbmVyXCIsIHsgcmVhZDogVmlld0NvbnRhaW5lclJlZiB9KVxuICAgY29udGVudENvbnRhaW5lcjogVmlld0NvbnRhaW5lclJlZiB8IHVuZGVmaW5lZCA9IHVuZGVmaW5lZDtcbiAgIEBWaWV3Q2hpbGRyZW4oRHJvcHpvbmVDb21wb25lbnQpIGRyb3B6b25lczpcbiAgICAgIHwgUXVlcnlMaXN0PERyb3B6b25lQ29tcG9uZW50PlxuICAgICAgfCB1bmRlZmluZWQgPSB1bmRlZmluZWQ7XG5cbiAgIEBJbnB1dCgpIGNvbnRlbnRUb0hvc3Q/OiBUeXBlPFQ+O1xuXG4gICBAT3V0cHV0KCkgcmVhZG9ubHkgY29udGVudENyZWF0ZWQgPSBuZXcgRXZlbnRFbWl0dGVyPFQ+KCk7XG4gICBAT3V0cHV0KCkgcmVhZG9ubHkgc2hvd0Ryb3B6b25lcyA9IG5ldyBFdmVudEVtaXR0ZXI8XCJ1cHBlclwiIHwgXCJsb3dlclwiPigpO1xuICAgQE91dHB1dCgpIHJlYWRvbmx5IGRyb3BwZWQgPSBuZXcgRXZlbnRFbWl0dGVyPFwiaW5uZXJcIiB8IFwibGF0ZXJhbFwiPigpO1xuXG4gICBwdWJsaWMgc2hvd0lubmVyRHJvcHpvbmU6IGJvb2xlYW4gPSBmYWxzZTtcbiAgIHB1YmxpYyBzaG93TGF0ZXJhbERyb3B6b25lOiBib29sZWFuID0gZmFsc2U7XG5cbiAgIHByaXZhdGUgaG9zdGVkQ29udGVudD86IENvbXBvbmVudFJlZjxUPjtcblxuICAgcHVibGljIGNvbnN0cnVjdG9yKHByaXZhdGUgcmVhZG9ubHkgYXBwUmVmOiBBcHBsaWNhdGlvblJlZikge31cblxuICAgcHVibGljIG5nQWZ0ZXJWaWV3SW5pdCgpOiB2b2lkIHtcbiAgICAgIGFzc2VydCh0aGlzLmNvbnRlbnRDb250YWluZXIgIT09IHVuZGVmaW5lZCk7XG4gICAgICBhc3NlcnQodGhpcy5jb250ZW50VG9Ib3N0ICE9PSB1bmRlZmluZWQpO1xuICAgICAgdGhpcy5ob3N0ZWRDb250ZW50ID0gdGhpcy5jb250ZW50Q29udGFpbmVyLmNyZWF0ZUNvbXBvbmVudChcbiAgICAgICAgIHRoaXMuY29udGVudFRvSG9zdFxuICAgICAgKTtcbiAgICAgIHRoaXMuY29udGVudENyZWF0ZWQuZW1pdCh0aGlzLmhvc3RlZENvbnRlbnQuaW5zdGFuY2UpO1xuICAgICAgYXNzZXJ0KHRoaXMuZHJvcHpvbmVzICE9PSB1bmRlZmluZWQpO1xuICAgICAgY29uc3QgaW5uZXIgPSB0aGlzLmRyb3B6b25lcy5nZXQoMCk7XG4gICAgICBjb25zdCBsYXRlcmFsID0gdGhpcy5kcm9wem9uZXMuZ2V0KDEpO1xuICAgICAgYXNzZXJ0KGlubmVyICE9PSB1bmRlZmluZWQgJiYgbGF0ZXJhbCAhPT0gdW5kZWZpbmVkKTtcbiAgICAgIG1lcmdlKFxuICAgICAgICAgaW5uZXIuZHJvcHBlZC5waXBlKG1hcCgoKSA9PiBcImlubmVyXCIgYXMgY29uc3QpKSxcbiAgICAgICAgIGxhdGVyYWwuZHJvcHBlZC5waXBlKG1hcCgoKSA9PiBcImxhdGVyYWxcIiBhcyBjb25zdCkpXG4gICAgICApLnN1YnNjcmliZSh0aGlzLmRyb3BwZWQpO1xuICAgICAgdGhpcy5ob3N0ZWRDb250ZW50LmNoYW5nZURldGVjdG9yUmVmLmRldGVjdENoYW5nZXMoKTtcbiAgIH1cblxuICAgcHVibGljIGdldEhvc3RlZENvbnRlbnQoKTogQ29tcG9uZW50UmVmPFQ+IHwgdW5kZWZpbmVkIHtcbiAgICAgIHJldHVybiB0aGlzLmhvc3RlZENvbnRlbnQ7XG4gICB9XG5cbiAgIHB1YmxpYyB0cmlnZ2VyQ2hhbmdlRGV0ZWN0aW9uKCk6IHZvaWQge1xuICAgICAgaWYgKCFOZ1pvbmUuaXNJbkFuZ3VsYXJab25lKCkpIHtcbiAgICAgICAgIHRoaXMuYXBwUmVmLnRpY2soKTtcbiAgICAgIH1cbiAgIH1cblxuICAgcHJvdGVjdGVkIGRyYWdvdmVySGFuZGxlcihldmVudDogRHJhZ0V2ZW50KTogdm9pZCB7XG4gICAgICBjb25zdCBlbGVtZW50SGVpZ2h0ID0gKFxuICAgICAgICAgZXZlbnQuY3VycmVudFRhcmdldCBhcyBIVE1MRWxlbWVudFxuICAgICAgKS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5oZWlnaHQ7XG4gICAgICBpZiAoZXZlbnQub2Zmc2V0WSA8IGVsZW1lbnRIZWlnaHQgLyAyKSB7XG4gICAgICAgICB0aGlzLnNob3dEcm9wem9uZXMuZW1pdChcInVwcGVyXCIpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgIHRoaXMuc2hvd0Ryb3B6b25lcy5lbWl0KFwibG93ZXJcIik7XG4gICAgICB9XG4gICB9XG5cbiAgIHB1YmxpYyBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICAgIC8vSSdtIG5vdCAxMDAlIHN1cmUgd2h5LCBidXQgd2UgaGF2ZSB0byByZW1vdmUgYW55IHJlZmVyZW5jZSB0byB0aGVcbiAgICAgIC8vY29tcG9uZW50UmVmIG90aGVyd2lzZSBBbmd1bGFyIHdpbGwgbmV2ZXIgcmVsZWFzZSBpdCBmb3IgZ2FyYmFnZVxuICAgICAgLy9jb2xsZWN0aW9uLlxuICAgICAgdGhpcy5ob3N0ZWRDb250ZW50ID0gdW5kZWZpbmVkO1xuICAgfVxufVxuIiwiPGRpdiBjbGFzcz1cImNvbnRlbnRcIiAoZHJhZ292ZXJOb0NoYW5nZURldGVjdCk9XCJkcmFnb3ZlckhhbmRsZXIoJGV2ZW50KVwiPlxuICAgPGRpdiAjY29udGVudENvbnRhaW5lcj48L2Rpdj5cbjwvZGl2PlxuPGRpdiBjbGFzcz1cImJyYW5jaGVzLWNvbnRhaW5lclwiPlxuICAgPGRyb3B6b25lIHBsYWNlbWVudD1cImlubmVyXCIgW2hpZGRlbl09XCIhc2hvd0lubmVyRHJvcHpvbmVcIj48L2Ryb3B6b25lPlxuICAgPGRpdiAjYnJhbmNoZXNDb250YWluZXI+PC9kaXY+XG48L2Rpdj5cbjxkcm9wem9uZSBwbGFjZW1lbnQ9XCJsYXRlcmFsXCIgW2hpZGRlbl09XCIhc2hvd0xhdGVyYWxEcm9wem9uZVwiPjwvZHJvcHpvbmU+XG4iXX0=
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { CommonModule } from "@angular/common";
|
|
2
2
|
import { Component, EventEmitter, Output, ViewChild, ViewContainerRef } from "@angular/core";
|
|
3
|
+
import { assert } from "../../../shared/assert";
|
|
3
4
|
import { DropzoneComponent } from "../dropzone/dropzone.component";
|
|
4
5
|
import * as i0 from "@angular/core";
|
|
5
6
|
export class RootComponent {
|
|
@@ -12,9 +13,7 @@ export class RootComponent {
|
|
|
12
13
|
}
|
|
13
14
|
ngAfterViewInit() {
|
|
14
15
|
this.afterViewInit.emit();
|
|
15
|
-
|
|
16
|
-
throw new Error("dropzone is not defined");
|
|
17
|
-
}
|
|
16
|
+
assert(this.dropzone !== undefined);
|
|
18
17
|
this.dropzone.dropped.subscribe(this.dropped);
|
|
19
18
|
}
|
|
20
19
|
}
|
|
@@ -34,4 +33,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
|
|
|
34
33
|
}], dropped: [{
|
|
35
34
|
type: Output
|
|
36
35
|
}] } });
|
|
37
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
36
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm9vdC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9saW1ibGUtdHJlZS9zcmMvbGliL2NvbXBvbmVudHMvcm9vdC9yb290LmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2xpbWJsZS10cmVlL3NyYy9saWIvY29tcG9uZW50cy9yb290L3Jvb3QuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQy9DLE9BQU8sRUFFSixTQUFTLEVBQ1QsWUFBWSxFQUNaLE1BQU0sRUFDTixTQUFTLEVBQ1QsZ0JBQWdCLEVBQ2xCLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUNoRCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQzs7QUFVbkUsTUFBTSxPQUFPLGFBQWE7SUFQMUI7UUFTRyxzQkFBaUIsR0FBaUMsU0FBUyxDQUFDO1FBQzlCLGFBQVEsR0FDbkMsU0FBUyxDQUFDO1FBRU0sa0JBQWEsR0FBRyxJQUFJLFlBQVksRUFBUSxDQUFDO1FBQ3pDLFlBQU8sR0FBRyxJQUFJLFlBQVksRUFBUSxDQUFDO1FBRS9DLHNCQUFpQixHQUFZLEtBQUssQ0FBQztLQU81QztJQUxTLGVBQWU7UUFDbkIsSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUMxQixNQUFNLENBQUMsSUFBSSxDQUFDLFFBQVEsS0FBSyxTQUFTLENBQUMsQ0FBQztRQUNwQyxJQUFJLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ2pELENBQUM7OzJHQWZTLGFBQWE7K0ZBQWIsYUFBYSxvT0FDaUIsZ0JBQWdCLHdEQUU3QyxpQkFBaUIsZ0RDdkIvQiwrSkFJQSw4RkRjYSxZQUFZLCtCQUFFLGlCQUFpQjs0RkFFL0IsYUFBYTtrQkFQekIsU0FBUztpQ0FDSyxJQUFJLFlBQ04sTUFBTSxXQUdQLENBQUMsWUFBWSxFQUFFLGlCQUFpQixDQUFDOzhCQUkxQyxpQkFBaUI7c0JBRGhCLFNBQVM7dUJBQUMsbUJBQW1CLEVBQUUsRUFBRSxJQUFJLEVBQUUsZ0JBQWdCLEVBQUU7Z0JBRTVCLFFBQVE7c0JBQXJDLFNBQVM7dUJBQUMsaUJBQWlCO2dCQUdULGFBQWE7c0JBQS9CLE1BQU07Z0JBQ1ksT0FBTztzQkFBekIsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gXCJAYW5ndWxhci9jb21tb25cIjtcbmltcG9ydCB7XG4gICBBZnRlclZpZXdJbml0LFxuICAgQ29tcG9uZW50LFxuICAgRXZlbnRFbWl0dGVyLFxuICAgT3V0cHV0LFxuICAgVmlld0NoaWxkLFxuICAgVmlld0NvbnRhaW5lclJlZlxufSBmcm9tIFwiQGFuZ3VsYXIvY29yZVwiO1xuaW1wb3J0IHsgYXNzZXJ0IH0gZnJvbSBcIi4uLy4uLy4uL3NoYXJlZC9hc3NlcnRcIjtcbmltcG9ydCB7IERyb3B6b25lQ29tcG9uZW50IH0gZnJvbSBcIi4uL2Ryb3B6b25lL2Ryb3B6b25lLmNvbXBvbmVudFwiO1xuaW1wb3J0IHsgTm9kZUNvbXBvbmVudCB9IGZyb20gXCIuLi9ub2RlLWNvbXBvbmVudC5pbnRlcmZhY2VcIjtcblxuQENvbXBvbmVudCh7XG4gICBzdGFuZGFsb25lOiB0cnVlLFxuICAgc2VsZWN0b3I6IFwicm9vdFwiLFxuICAgdGVtcGxhdGVVcmw6IFwiLi9yb290LmNvbXBvbmVudC5odG1sXCIsXG4gICBzdHlsZVVybHM6IFtcIi4vcm9vdC5jb21wb25lbnQuc2Nzc1wiXSxcbiAgIGltcG9ydHM6IFtDb21tb25Nb2R1bGUsIERyb3B6b25lQ29tcG9uZW50XVxufSlcbmV4cG9ydCBjbGFzcyBSb290Q29tcG9uZW50IGltcGxlbWVudHMgTm9kZUNvbXBvbmVudCwgQWZ0ZXJWaWV3SW5pdCB7XG4gICBAVmlld0NoaWxkKFwiYnJhbmNoZXNDb250YWluZXJcIiwgeyByZWFkOiBWaWV3Q29udGFpbmVyUmVmIH0pXG4gICBicmFuY2hlc0NvbnRhaW5lcjogVmlld0NvbnRhaW5lclJlZiB8IHVuZGVmaW5lZCA9IHVuZGVmaW5lZDtcbiAgIEBWaWV3Q2hpbGQoRHJvcHpvbmVDb21wb25lbnQpIGRyb3B6b25lOiBEcm9wem9uZUNvbXBvbmVudCB8IHVuZGVmaW5lZCA9XG4gICAgICB1bmRlZmluZWQ7XG5cbiAgIEBPdXRwdXQoKSByZWFkb25seSBhZnRlclZpZXdJbml0ID0gbmV3IEV2ZW50RW1pdHRlcjx2b2lkPigpO1xuICAgQE91dHB1dCgpIHJlYWRvbmx5IGRyb3BwZWQgPSBuZXcgRXZlbnRFbWl0dGVyPHZvaWQ+KCk7XG5cbiAgIHB1YmxpYyBzaG93SW5uZXJEcm9wem9uZTogYm9vbGVhbiA9IGZhbHNlO1xuXG4gICBwdWJsaWMgbmdBZnRlclZpZXdJbml0KCk6IHZvaWQge1xuICAgICAgdGhpcy5hZnRlclZpZXdJbml0LmVtaXQoKTtcbiAgICAgIGFzc2VydCh0aGlzLmRyb3B6b25lICE9PSB1bmRlZmluZWQpO1xuICAgICAgdGhpcy5kcm9wem9uZS5kcm9wcGVkLnN1YnNjcmliZSh0aGlzLmRyb3BwZWQpO1xuICAgfVxufVxuIiwiPGRpdiBjbGFzcz1cImJyYW5jaGVzLWNvbnRhaW5lclwiPlxuICAgPGRyb3B6b25lIHBsYWNlbWVudD1cImlubmVyXCIgW2hpZGRlbl09XCIhc2hvd0lubmVyRHJvcHpvbmVcIj48L2Ryb3B6b25lPlxuICAgPGRpdiAjYnJhbmNoZXNDb250YWluZXI+PC9kaXY+XG48L2Rpdj5cbiJdfQ==
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export {};
|
|
2
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnJhbmNoLW9wdGlvbnMuaW50ZXJmYWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbGltYmxlLXRyZWUvc3JjL2xpYi9jb3JlL2JyYW5jaC1vcHRpb25zLmludGVyZmFjZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRXZlbnRFbWl0dGVyLCBUeXBlIH0gZnJvbSBcIkBhbmd1bGFyL2NvcmVcIjtcblxuZXhwb3J0IGludGVyZmFjZSBCcmFuY2hPcHRpb25zPENvbXBvbmVudD4ge1xuICAgaW5wdXRCaW5kaW5ncz86IHtcbiAgICAgIFtLIGluIGtleW9mIENvbXBvbmVudF0/OiBDb21wb25lbnRbS107XG4gICB9O1xuICAgb3V0cHV0QmluZGluZ3M/OiB7XG4gICAgICBbSyBpbiBrZXlvZiBDb21wb25lbnRdPzogQ29tcG9uZW50W0tdIGV4dGVuZHMgRXZlbnRFbWl0dGVyPGluZmVyIFQ+XG4gICAgICAgICA/
|
|
2
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnJhbmNoLW9wdGlvbnMuaW50ZXJmYWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbGltYmxlLXRyZWUvc3JjL2xpYi9jb3JlL2JyYW5jaC1vcHRpb25zLmludGVyZmFjZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRXZlbnRFbWl0dGVyLCBUeXBlIH0gZnJvbSBcIkBhbmd1bGFyL2NvcmVcIjtcblxuZXhwb3J0IGludGVyZmFjZSBCcmFuY2hPcHRpb25zPENvbXBvbmVudD4ge1xuICAgaW5wdXRCaW5kaW5ncz86IHtcbiAgICAgIFtLIGluIGtleW9mIENvbXBvbmVudF0/OiBDb21wb25lbnRbS107XG4gICB9O1xuICAgb3V0cHV0QmluZGluZ3M/OiB7XG4gICAgICBbSyBpbiBrZXlvZiBDb21wb25lbnRdPzogQ29tcG9uZW50W0tdIGV4dGVuZHMgRXZlbnRFbWl0dGVyPGluZmVyIFQ+XG4gICAgICAgICA/ICh2YWx1ZTogVCkgPT4gdm9pZFxuICAgICAgICAgOiBuZXZlcjtcbiAgIH07XG4gICBkZWZhdWx0Q29sbGFwc2VkPzogYm9vbGVhbjtcbiAgIG1ldGE/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEZ1bGxCcmFuY2hPcHRpb25zPENvbXBvbmVudD4gZXh0ZW5kcyBCcmFuY2hPcHRpb25zPENvbXBvbmVudD4ge1xuICAgY29tcG9uZW50OiBUeXBlPENvbXBvbmVudD47XG59XG4iXX0=
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export {};
|
|
2
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
2
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJlZS1vcHRpb25zLmludGVyZmFjZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2xpbWJsZS10cmVlL3NyYy9saWIvY29yZS9jb25maWd1cmF0aW9uL3RyZWUtb3B0aW9ucy5pbnRlcmZhY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFRyZWVCcmFuY2ggfSBmcm9tIFwiLi4vdHJlZS1icmFuY2gvdHJlZS1icmFuY2hcIjtcbmltcG9ydCB7IFRyZWVSb290IH0gZnJvbSBcIi4uL3RyZWUtcm9vdC90cmVlLXJvb3RcIjtcblxuZXhwb3J0IGludGVyZmFjZSBUcmVlT3B0aW9ucyB7XG4gICBkcmFnQW5kRHJvcD86IHtcbiAgICAgIC8qKlxuICAgICAgICogQSBmdW5jdGlvbiB0byBpbmRpY2F0ZSB3aGV0aGVyIHRvIGFsbG93IGEgbm9kZSB0byBiZSBkcmFnZ2VkLiBUaGUgbm9kZSBpblxuICAgICAgICogcXVlc3Rpb24gaXMgcGFzc2VkIGluLiBEZWZhdWx0cyB0byBhIGZ1bmN0aW9uIHRoYXQgYWx3YXlzIHJldHVybnMgdHJ1ZS4gVGhpc1xuICAgICAgICogZnVuY3Rpb24gcnVucyB3aGVuIERyYWdBbmREcm9wU2VydmljZS5kcmFnU3RhcnQgcnVucywgYW5kIGJlZm9yZSB0aGUgYnJhbmNoXG4gICAgICAgKiBpcyBwcnVuZWQgZnJvbSB0aGUgdHJlZS5cbiAgICAgICAqL1xuICAgICAgYWxsb3dEcmFnZ2luZz86IDxUPih0cmVlQnJhbmNoOiBUcmVlQnJhbmNoPFQ+KSA9PiBib29sZWFuO1xuXG4gICAgICAvKipcbiAgICAgICAqIEEgZnVuY3Rpb24gdG8gZGV0ZXJtaW5lIHdoZXRoZXIgYSBzb3VyY2VOb2RlIGNhbiBiZSBkcm9wcGVkIGF0IGEgcGFydGljdWxhciBsb2NhdGlvbi5cbiAgICAgICAqIFRoZSBzb3VyY2VOb2RlLCB0aGUgbmV3IHByb3Bvc2VkUGFyZW50IGZvciB0aGUgc291cmNlTm9kZSwgYW5kIHRoZSBuZXcgcHJvcG9zZWRJbmRleFxuICAgICAgICogZm9yIHRoZSBzb3VyY2Ugbm9kZSBhcmUgcGFzc2VkIGluLiBUaGlzIGZ1bmN0aW9uIHJ1bnMganVzdCBiZWZvcmUgZGlzcGxheWluZyBhXG4gICAgICAgKiBmYW1pbHkgb2YgZHJvcHpvbmVzLlxuICAgICAgICovXG4gICAgICBhbGxvd0Ryb3A/OiA8VD4oXG4gICAgICAgICBzb3VyY2VOb2RlOiBUcmVlQnJhbmNoPFQ+LFxuICAgICAgICAgcHJvcG9zZWRQYXJlbnQ6IFRyZWVCcmFuY2g8VD4gfCBUcmVlUm9vdDxUPixcbiAgICAgICAgIHByb3Bvc2VkSW5kZXg6IG51bWJlclxuICAgICAgKSA9PiBib29sZWFuO1xuXG4gICAgICAvKipcbiAgICAgICAqIEEgZnVuY3Rpb24gdG8gaW5kaWNhdGUgd2hldGhlciB0byBhbGxvdyBcIm5lc3RpbmdcIiAocGxhY2luZyBhIGJyYW5jaCBvbmUgbGV2ZWxcbiAgICAgICAqIGRlZXBlciB0aGFuIGl0cyBwYXJlbnQpLiBUaGUgbm9kZSBpbiBxdWVzdGlvbiBpcyBwYXNzZWQgaW4uIERlZmF1bHRzIHRvIGEgZnVuY3Rpb25cbiAgICAgICAqIHRoYXQgYWx3YXlzIHJldHVybnMgdHJ1ZS4gVGhpcyBmdW5jdGlvbiBydW5zIGp1c3QgYmVmb3JlIGRpc3BsYXlpbmcgYSBmYW1pbHkgb2ZcbiAgICAgICAqIGRyb3B6b25lcy5cbiAgICAgICAqL1xuICAgICAgYWxsb3dOZXN0aW5nPzogPFQ+KHRyZWVCcmFuY2g6IFRyZWVCcmFuY2g8VD4pID0+IGJvb2xlYW47XG4gICB9O1xuXG4gICAvKipcbiAgICAqIFRoZSBudW1iZXIgb2YgcGl4ZWxzIGVhY2ggbGV2ZWwgb2YgdGhlIHRyZWUgd2lsbCBiZSBpbmRlbnRlZCByZWxhdGl2ZSB0b1xuICAgICogaXRzIHBhcmVudC4gRGVmYXVsdHMgdG8gMTYuXG4gICAgKi9cbiAgIGluZGVudGF0aW9uPzogbnVtYmVyO1xufVxuIl19
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export {};
|
|
2
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
2
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVsYXRpb25zaGlwLmludGVyZmFjZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2xpbWJsZS10cmVlL3NyYy9saWIvY29yZS9yZWxhdGlvbnNoaXAuaW50ZXJmYWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBOb2RlQ29tcG9uZW50IH0gZnJvbSBcIi4uL2NvbXBvbmVudHMvbm9kZS1jb21wb25lbnQuaW50ZXJmYWNlXCI7XG5pbXBvcnQgeyBUcmVlTm9kZSB9IGZyb20gXCIuLi9zdHJ1Y3R1cmVcIjtcbmltcG9ydCB7IFRyZWVSZWxhdGlvbnNoaXAgfSBmcm9tIFwiLi4vc3RydWN0dXJlL3RyZWUtcmVsYXRpb25zaGlwLmludGVyZmFjZVwiO1xuaW1wb3J0IHsgVHJlZUJyYW5jaCB9IGZyb20gXCIuL3RyZWUtYnJhbmNoL3RyZWUtYnJhbmNoXCI7XG5cbmV4cG9ydCB0eXBlIFJlbGF0aW9uc2hpcDxVc2VybGFuZENvbXBvbmVudD4gPSBUcmVlUmVsYXRpb25zaGlwPFxuICAgVHJlZU5vZGU8VHJlZUJyYW5jaDxVc2VybGFuZENvbXBvbmVudD4sIE5vZGVDb21wb25lbnQ+LFxuICAgVHJlZUJyYW5jaDxVc2VybGFuZENvbXBvbmVudD5cbj47XG4iXX0=
|