@cluetec/ngcx-tree 0.1.0-angular-15

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/CHANGELOG.md ADDED
@@ -0,0 +1,4 @@
1
+ <a name="0.1.0"></a>
2
+
3
+ - initial release
4
+ - cdk tree combined with cdk drag and drop
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 cluetec GmbH
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,318 @@
1
+ A reusable tree component for Angular based on the CDK Tree and the CDK Drag n
2
+ Drop features.
3
+
4
+ <br>
5
+ Status is beta - feedback welcome :)
6
+
7
+ # Table of Content
8
+
9
+ - [Table of Content](#table-of-content)
10
+ - [Getting Started](#getting-started)
11
+ - [Inputs](#inputs)
12
+ - [Outputs](#outputs)
13
+ - [Model](#model)
14
+ - [NgcxTreeConfig](#ngcxtreeconfig)
15
+ - [NgcxTreeNode](#ngcxtreenode)
16
+ - [NgcxTreeNodeWrapper](#ngcxtreenodewrapper)
17
+ - [NgcxTreeNodeMovedEvent](#ngcxtreenodemovedevent)
18
+ - [NgcxCustomComponent](#ngcxcustomcomponent)
19
+ - [Input](#input)
20
+ - [Output](#output)
21
+ - [Api](#api)
22
+ - [treeControl](#treecontrol)
23
+ - [Helper methods](#helper-methods)
24
+ - [selectNodeById](#selectnodebyid)
25
+ - [findNodeById](#findnodebyid)
26
+ - [Styling](#styling)
27
+ - [Include Styles](#include-styles)
28
+ - [Common styling](#common-styling)
29
+ - [Dotted tree lines](#dotted-tree-lines)
30
+ - [Selection highlighting](#selection-highlighting)
31
+ - [Icon color](#icon-color)
32
+ - [Font Awesome](#font-awesome)
33
+ - [Selection](#selection)
34
+ - [Simple Sample](#simple-sample)
35
+ - [Contributions](#contributions)
36
+
37
+ # Getting Started
38
+
39
+ 1. Install the library:
40
+
41
+ ```
42
+ npm install @cluetec/ngcx-tree
43
+ ```
44
+
45
+ 2. Import the component. Since it is standalone, either add it directly to
46
+ another standlone component or import it into your existing `NgModule`:
47
+
48
+ ```
49
+ import { NgcxTreeComponent } from '@cluetec/ngcx-tree';
50
+
51
+ @Component({
52
+ standalone: true,
53
+ imports: [NgcxTreeComponent],
54
+ })
55
+ ```
56
+
57
+ ```
58
+ import { NgcxTreeComponent } from '@cluetec/ngcx-tree';
59
+
60
+ @NgModule({
61
+ declarations: [AppComponent],
62
+ imports: [NgcxTreeComponent],
63
+ bootstrap: [AppComponent]
64
+ })
65
+ export class AppModule {}
66
+ ```
67
+
68
+ <br><br>
69
+
70
+ # Inputs
71
+
72
+ | Property | Type | required | Description |
73
+ | -------- | --------------------------------- | -------- | ------------------------------------------------------------------- |
74
+ | nodes | [NgcxTreeNode](#NgcxTreeNode)[] | no | list of nodes to show in the tree |
75
+ | config | [NgcxTreeConfig](#NgcxTreeConfig) | no | used to render the node when no custom template or component is set |
76
+
77
+ # Outputs
78
+
79
+ | Property | event content type | Description |
80
+ | ----------- | ---------------------- | ----------------------------------------------------------------------------------------- |
81
+ | nodeMoved | NgcxTreeNodeMovedEvent | fired when a node is moved |
82
+ | customEvent | any | may be fired by your own custom component |
83
+ | clickEvent | NgcxTreeNodeWrapper | fired when node is clicked |
84
+ | selectEvent | NgcxTreeNodeWrapper | fired when node is selected or un-selected. Clicking a selected node un-selects the node. |
85
+
86
+ # Model
87
+
88
+ ## NgcxTreeConfig
89
+
90
+ The component includes a model called `NgcxTreeConfig` with some basic optional
91
+ settings.
92
+
93
+ - `allowDrag` method that decides if a node can be dragged:
94
+ `(node: NgcxTreeNodeWrapper<T>) => boolean` - all nodes are draggable by
95
+ default<br><br>
96
+ - `allowDrop` method that decides if node can be dropped into another node
97
+ `(node: NgcxTreeNodeWrapper<T>, intoNode?: NgcxTreeNodeWrapper<T>) => boolean ` -
98
+ every node may be draggable everywhere by default<br><br>
99
+ - `allowSelection` method that decides if node can be selected
100
+ `(node: NgcxTreeNodeWrapper<T>) => boolean ` - nodes are not selectable by
101
+ default<br><br>
102
+ - `treeNodeContentTemplate` Angular TemplateRef that will be used to render a
103
+ node<br><br> `let-nodeWrapper="nodeWrapper"` may be used to access the node
104
+ wrapper to render the node
105
+ - `treeNodeContentComponent` Angular Component that will be used to render a
106
+ node. (use `treeNodeContentComponent` or `treeNodeContentTemplate`, but not
107
+ both). see [NgcxCustomComponent<T>](#NgcxCustomComponent)
108
+
109
+ <br><br>
110
+
111
+ ## NgcxTreeNode
112
+
113
+ If no data is passed to the component, it will simply display some mock data.
114
+ Data is provided to the tree in the following format:
115
+
116
+ | Property | Type | required | Description |
117
+ | -------- | -------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
118
+ | id | string | yes | necessary unique id of the node |
119
+ | title | string | no | used to render the node when no custom template or component is set |
120
+ | faIcon | string | no | font awesome icon used to render the node when no custom template or component is set. You must include fontawesome on your own if you want |
121
+ | children | NgcxTreeNode[] | no | children of the node |
122
+
123
+ ## NgcxTreeNodeWrapper<T>
124
+
125
+ Generic T is the same as the elements of the input `nodes`.
126
+
127
+ | Property | Type | Description |
128
+ | ------------ | ----------------------------------- | ------------------------------------------------------------------------------------------ |
129
+ | id | string | same as NgcxTreeNode.id |
130
+ | data | T | data of the input nodes `nodes` |
131
+ | depth | number | depth in the tree starting with 0 |
132
+ | index | number | index of the node in it's parent |
133
+ | isSelectable | boolean | if the node is selectable. Depending on the config.allowSelection method. (default: false) |
134
+ | isFirstChild | boolean | is first node from the same parent |
135
+ | isLastChild | boolean | is last node from the same parent |
136
+ | children | NgcxTreeNodeWrapper<T>[] | list of children wrappers around the original nodes |
137
+ | parent | NgcxTreeNodeWrapper<T> \| undefined | parent node |
138
+ | next | NgcxTreeNodeWrapper<T> \| undefined | node after this node in same parent, if one exists. |
139
+ | previous | NgcxTreeNodeWrapper<T> \| undefined | node before this node in same parent, if one exists. |
140
+
141
+ ## NgcxTreeNodeMovedEvent
142
+
143
+ | Property | Type | Description |
144
+ | ---------- | ----------------------------------- | ---------------------------------- |
145
+ | node | NgcxTreeNodeWrapper<T> | the moved node |
146
+ | parent | NgcxTreeNodeWrapper<T> \| undefined | moved into this parent node |
147
+ | afterNode | NgcxTreeNodeWrapper<T> \| undefined | moved to position after this node |
148
+ | beforeNode | NgcxTreeNodeWrapper<T> \| undefined | moved to position before this node |
149
+
150
+ ## NgcxCustomComponent<T>
151
+
152
+ Your component can implement this interface and can be set as
153
+ `Type<NgcxCustomComponent<T>>` in the config.treeNodeContentComponent input.
154
+
155
+ ### Input
156
+
157
+ `nodeWrapper` the input to render the node. Type: NgcxTreeNodeWrapper<T>
158
+
159
+ ### Output
160
+
161
+ `customEvent` `EventEmitter<any>` can be used to trigger the output
162
+ 'customEvent'
163
+
164
+ # Api
165
+
166
+ ## treeControl
167
+
168
+ the treeControl (`NestedTreeControl<NgcxTreeNodeWrapper<T>, string>`) of Angular
169
+ CDK can be mainly used to expand and collapse nodes.
170
+
171
+ ## Helper methods
172
+
173
+ ### selectNodeById
174
+
175
+ Can be called to select a node by id. the selectEvent event is fired afterwards.
176
+
177
+ ### findNodeById
178
+
179
+ Can be used to get the `NgcxTreeNodeWrapper<T>` for an id. returns `undefined`
180
+ if no node is available for the id.
181
+
182
+ # Styling
183
+
184
+ ## Include Styles
185
+
186
+ Or All styles from below:
187
+
188
+ ```scss
189
+ @import '@cluetec/ngcx-tree/styles/styles';
190
+ ```
191
+
192
+ ## Common styling
193
+
194
+ you should set the width of cdk-drop-list to 100%, otherwise, the node content
195
+ may be on wrong place:
196
+
197
+ ```css
198
+ .ngcx-tree .cdk-drop-list {
199
+ width: 100%;
200
+ }
201
+ ```
202
+
203
+ Or Include this:
204
+
205
+ ```scss
206
+ @import '@cluetec/ngcx-tree/styles/ngcx-common';
207
+ ```
208
+
209
+ ### Dotted tree lines
210
+
211
+ Import or copy the scss to show tree lines:
212
+
213
+ ```scss
214
+ @import '@cluetec/ngcx-tree/styles/ngcx-doted-tree-line';
215
+ ```
216
+
217
+ ### Selection highlighting
218
+
219
+ Import or copy the scss to show some selection styling:
220
+
221
+ ```scss
222
+ @import '@cluetec/ngcx-tree/styles/ngcx-selection';
223
+ ```
224
+
225
+ ### Icon color
226
+
227
+ Import or copy the scss to set the color of the node icon:
228
+
229
+ ```scss
230
+ @import '@cluetec/ngcx-tree/styles/ngcx-icon-color';
231
+ ```
232
+
233
+ ## Font Awesome
234
+
235
+ Font Awesome is not referenced included here, but to show icons for the nodes
236
+ you must include font-awesome on your own and may use the `node.faIcon` property
237
+ to set the icon.
238
+
239
+ Include like this:
240
+ [projects/ngcx-tree/stories/styles/styles.scss](projects/ngcx-tree/stories/styles/styles.scss)
241
+
242
+ ## Selection
243
+
244
+ Selected node can be styled like this:
245
+
246
+ ```css
247
+ .tree-node-content-container.selected .tree-node-content {
248
+ background-color: #555;
249
+ padding-left: 5px;
250
+ }
251
+ ```
252
+
253
+ Hover effect on selectable node:
254
+
255
+ ```css
256
+ .ngcx-tree:not(.dragging)
257
+ .tree-node-content-container.is-selectable:hover
258
+ .tree-node-content {
259
+ background-color: #fbfbfb;
260
+ }
261
+ ```
262
+
263
+ Remove Selection css on dragging element:
264
+
265
+ ```css
266
+ .cdk-drag-preview .tree-node-content-container.selected .tree-node-content {
267
+ background-color: inherit;
268
+ }
269
+ ```
270
+
271
+ # Simple Sample
272
+
273
+ ```ts
274
+ import { DragDropModule } from '@angular/cdk/drag-drop';
275
+ import { CdkTreeModule } from '@angular/cdk/tree';
276
+ import { Component } from '@angular/core';
277
+ import { NgcxTreeComponent } from '@cluetec/ngcx-tree';
278
+
279
+ @Component({
280
+ selector: 'app-simple-tree-sample',
281
+ template: '<ngcx-tree [nodes]="data"></ngcx-tree>',
282
+ standalone: true,
283
+ imports: [CdkTreeModule, DragDropModule, NgcxTreeComponent],
284
+ })
285
+ export class SimpleTreeSampleComponent {
286
+ data = [
287
+ {
288
+ id: 'fru',
289
+ title: 'Fruit',
290
+ children: [
291
+ {
292
+ id: 'app',
293
+ title: 'Apple',
294
+ },
295
+ {
296
+ id: 'ban',
297
+ title: 'Banana',
298
+ },
299
+ ],
300
+ },
301
+ {
302
+ id: 'fish',
303
+ title: 'Fish',
304
+ },
305
+ ];
306
+ }
307
+ ```
308
+
309
+ <br><br>
310
+
311
+ # Contributions
312
+
313
+ Contributions and improvement suggestions are always welcome!
314
+
315
+ ##Samples
316
+
317
+ For samples see the storybook stories. run `npm run storybook` to see the
318
+ samples.
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Generated bundle index. Do not edit.
3
+ */
4
+ export * from './public-api';
5
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2x1ZXRlYy1uZ2N4LXRyZWUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9wcm9qZWN0cy9uZ2N4LXRyZWUvc3JjL2NsdWV0ZWMtbmdjeC10cmVlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBRUgsY0FBYyxjQUFjLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEdlbmVyYXRlZCBidW5kbGUgaW5kZXguIERvIG5vdCBlZGl0LlxuICovXG5cbmV4cG9ydCAqIGZyb20gJy4vcHVibGljLWFwaSc7XG4iXX0=
@@ -0,0 +1,16 @@
1
+ import { DataSource } from '@angular/cdk/collections';
2
+ import { BehaviorSubject } from 'rxjs';
3
+ export class NgcxTreeDataSource extends DataSource {
4
+ constructor(data) {
5
+ super();
6
+ this.data$ = new BehaviorSubject(data);
7
+ }
8
+ connect() {
9
+ return this.data$.asObservable();
10
+ }
11
+ disconnect() { }
12
+ update(data) {
13
+ this.data$.next([...data]);
14
+ }
15
+ }
16
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmdjeC10cmVlLWRhdGEuc291cmNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmdjeC10cmVlL3NyYy9saWIvbmdjeC10cmVlL25nY3gtdHJlZS1kYXRhLnNvdXJjZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDdEQsT0FBTyxFQUFFLGVBQWUsRUFBYyxNQUFNLE1BQU0sQ0FBQztBQUVuRCxNQUFNLE9BQU8sa0JBQXNCLFNBQVEsVUFBYTtJQUd0RCxZQUFZLElBQVM7UUFDbkIsS0FBSyxFQUFFLENBQUM7UUFDUixJQUFJLENBQUMsS0FBSyxHQUFHLElBQUksZUFBZSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3pDLENBQUM7SUFFRCxPQUFPO1FBQ0wsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLFlBQVksRUFBRSxDQUFDO0lBQ25DLENBQUM7SUFDRCxVQUFVLEtBQVUsQ0FBQztJQUVyQixNQUFNLENBQUMsSUFBUztRQUNkLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQzdCLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IERhdGFTb3VyY2UgfSBmcm9tICdAYW5ndWxhci9jZGsvY29sbGVjdGlvbnMnO1xuaW1wb3J0IHsgQmVoYXZpb3JTdWJqZWN0LCBPYnNlcnZhYmxlIH0gZnJvbSAncnhqcyc7XG5cbmV4cG9ydCBjbGFzcyBOZ2N4VHJlZURhdGFTb3VyY2U8VD4gZXh0ZW5kcyBEYXRhU291cmNlPFQ+IHtcbiAgZGF0YSQ6IEJlaGF2aW9yU3ViamVjdDxUW10+O1xuXG4gIGNvbnN0cnVjdG9yKGRhdGE6IFRbXSkge1xuICAgIHN1cGVyKCk7XG4gICAgdGhpcy5kYXRhJCA9IG5ldyBCZWhhdmlvclN1YmplY3QoZGF0YSk7XG4gIH1cblxuICBjb25uZWN0KCk6IE9ic2VydmFibGU8cmVhZG9ubHkgVFtdPiB7XG4gICAgcmV0dXJuIHRoaXMuZGF0YSQuYXNPYnNlcnZhYmxlKCk7XG4gIH1cbiAgZGlzY29ubmVjdCgpOiB2b2lkIHt9XG5cbiAgdXBkYXRlKGRhdGE6IFRbXSkge1xuICAgIHRoaXMuZGF0YSQubmV4dChbLi4uZGF0YV0pO1xuICB9XG59XG4iXX0=
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmdjeC10cmVlLW1vZGVscy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25nY3gtdHJlZS9zcmMvbGliL25nY3gtdHJlZS9uZ2N4LXRyZWUtbW9kZWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBOZXN0ZWRUcmVlQ29udHJvbCB9IGZyb20gJ0Bhbmd1bGFyL2Nkay90cmVlJztcbmltcG9ydCB7IEV2ZW50RW1pdHRlciwgVGVtcGxhdGVSZWYsIFR5cGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuZXhwb3J0IGludGVyZmFjZSBOZ2N4VHJlZUNvbmZpZzxUPiB7XG4gIHRyZWVOb2RlQ29udGVudENvbXBvbmVudD86IFR5cGU8TmdjeEN1c3RvbUNvbXBvbmVudDxUPj47XG4gIHRyZWVOb2RlQ29udGVudFRlbXBsYXRlPzogVGVtcGxhdGVSZWY8YW55PjtcblxuICBhbGxvd0Ryb3A/OiAoXG4gICAgbm9kZTogTmdjeFRyZWVOb2RlV3JhcHBlcjxUPixcbiAgICBpbnRvTm9kZT86IE5nY3hUcmVlTm9kZVdyYXBwZXI8VD5cbiAgKSA9PiBib29sZWFuO1xuICBhbGxvd0RyYWc/OiAobm9kZTogTmdjeFRyZWVOb2RlV3JhcHBlcjxUPikgPT4gYm9vbGVhbjtcbiAgYWxsb3dTZWxlY3Rpb24/OiAobm9kZTogTmdjeFRyZWVOb2RlV3JhcHBlcjxUPikgPT4gYm9vbGVhbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBOZ2N4Q3VzdG9tQ29tcG9uZW50PFQ+IHtcbiAgbm9kZVdyYXBwZXI/OiBOZ2N4VHJlZU5vZGVXcmFwcGVyPFQ+O1xuICBjdXN0b21FdmVudD86IEV2ZW50RW1pdHRlcjxhbnk+O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIE5nY3hUcmVlTm9kZSB7XG4gIGlkOiBzdHJpbmc7XG4gIHRpdGxlPzogYW55O1xuICBmYUljb24/OiBzdHJpbmc7XG4gIGNoaWxkcmVuPzogTmdjeFRyZWVOb2RlW107XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgTmdjeFRyZWVOb2RlV3JhcHBlcjxUPiB7XG4gIGlkOiBzdHJpbmc7XG4gIGRhdGE6IFQ7XG4gIGRlcHRoOiBudW1iZXI7XG4gIGluZGV4OiBudW1iZXI7XG4gIGlzU2VsZWN0YWJsZT86IGJvb2xlYW47XG4gIGlzRmlyc3RDaGlsZDogYm9vbGVhbjtcbiAgaXNMYXN0Q2hpbGQ6IGJvb2xlYW47XG4gIGNoaWxkcmVuOiBOZ2N4VHJlZU5vZGVXcmFwcGVyPFQ+W107XG4gIHBhcmVudD86IE5nY3hUcmVlTm9kZVdyYXBwZXI8VD47XG4gIG5leHQ/OiBOZ2N4VHJlZU5vZGVXcmFwcGVyPFQ+O1xuICBwcmV2aW91cz86IE5nY3hUcmVlTm9kZVdyYXBwZXI8VD47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgTmdjeFRyZWVOb2RlQ29tcG9uZW50PFQ+IHtcbiAgbm9kZVdyYXBwZXI/OiBOZ2N4VHJlZU5vZGVXcmFwcGVyPFQ+O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIE5nY3hUcmVlTm9kZU1vdmVkRXZlbnQ8VD4ge1xuICBub2RlOiBOZ2N4VHJlZU5vZGVXcmFwcGVyPFQ+O1xuICBwYXJlbnQ/OiBOZ2N4VHJlZU5vZGVXcmFwcGVyPFQ+O1xuICBhZnRlck5vZGU/OiBOZ2N4VHJlZU5vZGVXcmFwcGVyPFQ+O1xuICBiZWZvcmVOb2RlPzogTmdjeFRyZWVOb2RlV3JhcHBlcjxUPjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBOZ2N4VHJlZUFwaTxUPiB7XG4gIHNlbGVjdE5vZGVCeUlkKGlkOiBzdHJpbmcpOiB2b2lkO1xuICBmaW5kTm9kZUJ5SWQoaWQ6IHN0cmluZyk6IE5nY3hUcmVlTm9kZVdyYXBwZXI8VD4gfCB1bmRlZmluZWQ7XG5cbiAgZ2V0IHRyZWVDb250cm9sKCk6IE5lc3RlZFRyZWVDb250cm9sPE5nY3hUcmVlTm9kZVdyYXBwZXI8YW55Piwgc3RyaW5nPjtcbn1cbiJdfQ==
@@ -0,0 +1,49 @@
1
+ import { CdkTreeModule } from '@angular/cdk/tree';
2
+ import { Component, EventEmitter, Input, Output, ViewChild, ViewContainerRef, } from '@angular/core';
3
+ import { NgIf, NgTemplateOutlet } from '@angular/common';
4
+ import { Subject, takeUntil } from 'rxjs';
5
+ import * as i0 from "@angular/core";
6
+ import * as i1 from "@angular/cdk/tree";
7
+ export class NgcxTreeNodeComponent {
8
+ constructor() {
9
+ this.isSelected = false;
10
+ this.customEvent = new EventEmitter();
11
+ this.clickEvent = new EventEmitter();
12
+ this.ngUnsubscribe = new Subject();
13
+ }
14
+ ngOnInit() {
15
+ if (this.vcRef && this.treeConfig?.treeNodeContentComponent) {
16
+ const nodeComponent = this.vcRef.createComponent(this.treeConfig.treeNodeContentComponent);
17
+ nodeComponent.instance.nodeWrapper = this.nodeWrapper;
18
+ nodeComponent.instance.customEvent
19
+ ?.pipe(takeUntil(this.ngUnsubscribe))
20
+ .subscribe((value) => this.customEvent.emit(value));
21
+ }
22
+ }
23
+ ngOnDestroy() {
24
+ this.ngUnsubscribe.next(undefined);
25
+ this.ngUnsubscribe.complete();
26
+ }
27
+ }
28
+ NgcxTreeNodeComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: NgcxTreeNodeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
29
+ NgcxTreeNodeComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: NgcxTreeNodeComponent, isStandalone: true, selector: "ngcx-tree-node", inputs: { nodeWrapper: "nodeWrapper", treeControl: "treeControl", treeConfig: "treeConfig", isSelected: "isSelected" }, outputs: { customEvent: "customEvent", clickEvent: "clickEvent" }, viewQueries: [{ propertyName: "vcRef", first: true, predicate: ["ref"], descendants: true, read: ViewContainerRef, static: true }], ngImport: i0, template: "<div\n class=\"tree-node-content-container\"\n [class.selected]=\"isSelected\"\n [class.first]=\"nodeWrapper.isFirstChild\"\n [class.last]=\"nodeWrapper.isLastChild\"\n [class.is-selectable]=\"nodeWrapper.isSelectable\"\n (click)=\"clickEvent.emit()\">\n <div class=\"tree-node-expand-container\">\n <button\n *ngIf=\"nodeWrapper.children.length > 0\"\n class=\"tree-node-expand\"\n cdkTreeNodeToggle\n [attr.aria-label]=\"'Toggle ' + nodeWrapper.data.title\"\n (click)=\"$event.preventDefault()\">\n <div class=\"chevron\" [class.rotate]=\"treeControl.isExpanded(nodeWrapper)\">\n <svg id=\"a\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 9 9\">\n <path\n d=\"m2.83.09l4.2,4.2c.05.05.09.14.09.21s-.04.15-.09.21l-4.2,4.2c-.05.05-.14.09-.21.09s-.15-.04-.21-.09l-.45-.45c-.05-.05-.09-.13-.09-.21,0-.07.04-.15.09-.21l3.54-3.54L1.97.96c-.05-.05-.09-.14-.09-.21s.04-.15.09-.21l.45-.45c.05-.05.14-.09.21-.09s.15.04.21.09Z\"\n style=\"fill: var(--icon-color, #333); stroke-width: 0px\" />\n </svg>\n </div>\n </button>\n </div>\n <div class=\"small-horizontal-tree-line\"></div>\n <div class=\"tree-node-icon-container\" *ngIf=\"nodeWrapper.data.faIcon\">\n <i class=\"fa\" [class]=\"nodeWrapper.data.faIcon\"></i>\n </div>\n <div class=\"tree-node-content\">\n <span\n *ngIf=\"\n !treeConfig?.treeNodeContentComponent &&\n !treeConfig?.treeNodeContentTemplate\n \">\n {{ nodeWrapper.data.title }}\n </span>\n <ng-container #ref></ng-container>\n <ng-container *ngIf=\"treeConfig?.treeNodeContentTemplate as template\">\n <ng-container\n *ngTemplateOutlet=\"\n template;\n context: {\n nodeWrapper: nodeWrapper\n }\n \"></ng-container>\n </ng-container>\n </div>\n</div>\n", styles: [".tree-node-content-container{display:flex;flex-direction:row;justify-content:flex-start;align-items:center;width:100%}.tree-node-content-container.is-selectable{cursor:pointer}.tree-node-content-container .tree-node-expand-container{display:flex;flex-direction:row;justify-content:center;align-items:center;width:30px;height:30px;margin-right:5px}.tree-node-content-container .tree-node-expand-container>.tree-node-expand{color:#2587be;background:none;border:none;font:inherit;cursor:pointer;outline:inherit;width:30px;height:30px;display:flex;justify-content:center;align-items:center}.tree-node-content-container .tree-node-expand-container>.tree-node-expand .chevron{width:10px;transition:transform .1s ease-in-out}.tree-node-content-container .tree-node-expand-container>.tree-node-expand .chevron.rotate{transform:rotate(90deg)}.tree-node-content-container .tree-node-icon-container{margin-right:7px;color:#2587be}\n"], dependencies: [{ kind: "ngmodule", type: CdkTreeModule }, { kind: "directive", type: i1.CdkTreeNodeToggle, selector: "[cdkTreeNodeToggle]", inputs: ["cdkTreeNodeToggleRecursive"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
30
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: NgcxTreeNodeComponent, decorators: [{
31
+ type: Component,
32
+ args: [{ selector: 'ngcx-tree-node', standalone: true, imports: [CdkTreeModule, NgTemplateOutlet, NgIf], template: "<div\n class=\"tree-node-content-container\"\n [class.selected]=\"isSelected\"\n [class.first]=\"nodeWrapper.isFirstChild\"\n [class.last]=\"nodeWrapper.isLastChild\"\n [class.is-selectable]=\"nodeWrapper.isSelectable\"\n (click)=\"clickEvent.emit()\">\n <div class=\"tree-node-expand-container\">\n <button\n *ngIf=\"nodeWrapper.children.length > 0\"\n class=\"tree-node-expand\"\n cdkTreeNodeToggle\n [attr.aria-label]=\"'Toggle ' + nodeWrapper.data.title\"\n (click)=\"$event.preventDefault()\">\n <div class=\"chevron\" [class.rotate]=\"treeControl.isExpanded(nodeWrapper)\">\n <svg id=\"a\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 9 9\">\n <path\n d=\"m2.83.09l4.2,4.2c.05.05.09.14.09.21s-.04.15-.09.21l-4.2,4.2c-.05.05-.14.09-.21.09s-.15-.04-.21-.09l-.45-.45c-.05-.05-.09-.13-.09-.21,0-.07.04-.15.09-.21l3.54-3.54L1.97.96c-.05-.05-.09-.14-.09-.21s.04-.15.09-.21l.45-.45c.05-.05.14-.09.21-.09s.15.04.21.09Z\"\n style=\"fill: var(--icon-color, #333); stroke-width: 0px\" />\n </svg>\n </div>\n </button>\n </div>\n <div class=\"small-horizontal-tree-line\"></div>\n <div class=\"tree-node-icon-container\" *ngIf=\"nodeWrapper.data.faIcon\">\n <i class=\"fa\" [class]=\"nodeWrapper.data.faIcon\"></i>\n </div>\n <div class=\"tree-node-content\">\n <span\n *ngIf=\"\n !treeConfig?.treeNodeContentComponent &&\n !treeConfig?.treeNodeContentTemplate\n \">\n {{ nodeWrapper.data.title }}\n </span>\n <ng-container #ref></ng-container>\n <ng-container *ngIf=\"treeConfig?.treeNodeContentTemplate as template\">\n <ng-container\n *ngTemplateOutlet=\"\n template;\n context: {\n nodeWrapper: nodeWrapper\n }\n \"></ng-container>\n </ng-container>\n </div>\n</div>\n", styles: [".tree-node-content-container{display:flex;flex-direction:row;justify-content:flex-start;align-items:center;width:100%}.tree-node-content-container.is-selectable{cursor:pointer}.tree-node-content-container .tree-node-expand-container{display:flex;flex-direction:row;justify-content:center;align-items:center;width:30px;height:30px;margin-right:5px}.tree-node-content-container .tree-node-expand-container>.tree-node-expand{color:#2587be;background:none;border:none;font:inherit;cursor:pointer;outline:inherit;width:30px;height:30px;display:flex;justify-content:center;align-items:center}.tree-node-content-container .tree-node-expand-container>.tree-node-expand .chevron{width:10px;transition:transform .1s ease-in-out}.tree-node-content-container .tree-node-expand-container>.tree-node-expand .chevron.rotate{transform:rotate(90deg)}.tree-node-content-container .tree-node-icon-container{margin-right:7px;color:#2587be}\n"] }]
33
+ }], propDecorators: { nodeWrapper: [{
34
+ type: Input
35
+ }], treeControl: [{
36
+ type: Input
37
+ }], treeConfig: [{
38
+ type: Input
39
+ }], isSelected: [{
40
+ type: Input
41
+ }], customEvent: [{
42
+ type: Output
43
+ }], clickEvent: [{
44
+ type: Output
45
+ }], vcRef: [{
46
+ type: ViewChild,
47
+ args: ['ref', { read: ViewContainerRef, static: true }]
48
+ }] } });
49
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmdjeC10cmVlLW5vZGUuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmdjeC10cmVlL3NyYy9saWIvbmdjeC10cmVlL25nY3gtdHJlZS1ub2RlL25nY3gtdHJlZS1ub2RlLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25nY3gtdHJlZS9zcmMvbGliL25nY3gtdHJlZS9uZ2N4LXRyZWUtbm9kZS9uZ2N4LXRyZWUtbm9kZS5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsYUFBYSxFQUFxQixNQUFNLG1CQUFtQixDQUFDO0FBQ3JFLE9BQU8sRUFDTCxTQUFTLEVBQ1QsWUFBWSxFQUNaLEtBQUssRUFHTCxNQUFNLEVBQ04sU0FBUyxFQUNULGdCQUFnQixHQUNqQixNQUFNLGVBQWUsQ0FBQztBQUd2QixPQUFPLEVBQUUsSUFBSSxFQUFFLGdCQUFnQixFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDekQsT0FBTyxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxNQUFNLENBQUM7OztBQVMxQyxNQUFNLE9BQU8scUJBQXFCO0lBUGxDO1FBV1csZUFBVSxHQUFHLEtBQUssQ0FBQztRQUVsQixnQkFBVyxHQUFHLElBQUksWUFBWSxFQUFPLENBQUM7UUFDdEMsZUFBVSxHQUFHLElBQUksWUFBWSxFQUFRLENBQUM7UUFLaEQsa0JBQWEsR0FBRyxJQUFJLE9BQU8sRUFBRSxDQUFDO0tBbUIvQjtJQWpCQyxRQUFRO1FBQ04sSUFBSSxJQUFJLENBQUMsS0FBSyxJQUFJLElBQUksQ0FBQyxVQUFVLEVBQUUsd0JBQXdCLEVBQUU7WUFDM0QsTUFBTSxhQUFhLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxlQUFlLENBQzlDLElBQUksQ0FBQyxVQUFVLENBQUMsd0JBQXdCLENBQ3pDLENBQUM7WUFDRixhQUFhLENBQUMsUUFBUSxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDO1lBRXRELGFBQWEsQ0FBQyxRQUFRLENBQUMsV0FBVztnQkFDaEMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQztpQkFDcEMsU0FBUyxDQUFDLENBQUMsS0FBVSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO1NBQzVEO0lBQ0gsQ0FBQztJQUVELFdBQVc7UUFDVCxJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUNuQyxJQUFJLENBQUMsYUFBYSxDQUFDLFFBQVEsRUFBRSxDQUFDO0lBQ2hDLENBQUM7O21IQTlCVSxxQkFBcUI7dUdBQXJCLHFCQUFxQiw4VUFTTixnQkFBZ0IsMkNDaEM1QyxxMURBK0NBLGs5QkQxQlksYUFBYSwySkFBRSxnQkFBZ0Isb0pBQUUsSUFBSTs0RkFFcEMscUJBQXFCO2tCQVBqQyxTQUFTOytCQUNFLGdCQUFnQixjQUdkLElBQUksV0FDUCxDQUFDLGFBQWEsRUFBRSxnQkFBZ0IsRUFBRSxJQUFJLENBQUM7OEJBR3ZDLFdBQVc7c0JBQW5CLEtBQUs7Z0JBQ0csV0FBVztzQkFBbkIsS0FBSztnQkFDRyxVQUFVO3NCQUFsQixLQUFLO2dCQUNHLFVBQVU7c0JBQWxCLEtBQUs7Z0JBRUksV0FBVztzQkFBcEIsTUFBTTtnQkFDRyxVQUFVO3NCQUFuQixNQUFNO2dCQUdQLEtBQUs7c0JBREosU0FBUzt1QkFBQyxLQUFLLEVBQUUsRUFBRSxJQUFJLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENka1RyZWVNb2R1bGUsIE5lc3RlZFRyZWVDb250cm9sIH0gZnJvbSAnQGFuZ3VsYXIvY2RrL3RyZWUnO1xuaW1wb3J0IHtcbiAgQ29tcG9uZW50LFxuICBFdmVudEVtaXR0ZXIsXG4gIElucHV0LFxuICBPbkRlc3Ryb3ksXG4gIE9uSW5pdCxcbiAgT3V0cHV0LFxuICBWaWV3Q2hpbGQsXG4gIFZpZXdDb250YWluZXJSZWYsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgTmdjeFRyZWVDb25maWcsIE5nY3hUcmVlTm9kZVdyYXBwZXIgfSBmcm9tICcuLi9uZ2N4LXRyZWUtbW9kZWxzJztcblxuaW1wb3J0IHsgTmdJZiwgTmdUZW1wbGF0ZU91dGxldCB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBTdWJqZWN0LCB0YWtlVW50aWwgfSBmcm9tICdyeGpzJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnbmdjeC10cmVlLW5vZGUnLFxuICB0ZW1wbGF0ZVVybDogJy4vbmdjeC10cmVlLW5vZGUuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi9uZ2N4LXRyZWUtbm9kZS5jb21wb25lbnQuc2NzcyddLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBpbXBvcnRzOiBbQ2RrVHJlZU1vZHVsZSwgTmdUZW1wbGF0ZU91dGxldCwgTmdJZl0sXG59KVxuZXhwb3J0IGNsYXNzIE5nY3hUcmVlTm9kZUNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25EZXN0cm95IHtcbiAgQElucHV0KCkgbm9kZVdyYXBwZXIhOiBOZ2N4VHJlZU5vZGVXcmFwcGVyPGFueT47XG4gIEBJbnB1dCgpIHRyZWVDb250cm9sITogTmVzdGVkVHJlZUNvbnRyb2w8TmdjeFRyZWVOb2RlV3JhcHBlcjxhbnk+LCBzdHJpbmc+O1xuICBASW5wdXQoKSB0cmVlQ29uZmlnPzogTmdjeFRyZWVDb25maWc8YW55PjtcbiAgQElucHV0KCkgaXNTZWxlY3RlZCA9IGZhbHNlO1xuXG4gIEBPdXRwdXQoKSBjdXN0b21FdmVudCA9IG5ldyBFdmVudEVtaXR0ZXI8YW55PigpO1xuICBAT3V0cHV0KCkgY2xpY2tFdmVudCA9IG5ldyBFdmVudEVtaXR0ZXI8dm9pZD4oKTtcblxuICBAVmlld0NoaWxkKCdyZWYnLCB7IHJlYWQ6IFZpZXdDb250YWluZXJSZWYsIHN0YXRpYzogdHJ1ZSB9KVxuICB2Y1JlZj86IFZpZXdDb250YWluZXJSZWY7XG5cbiAgbmdVbnN1YnNjcmliZSA9IG5ldyBTdWJqZWN0KCk7XG5cbiAgbmdPbkluaXQoKSB7XG4gICAgaWYgKHRoaXMudmNSZWYgJiYgdGhpcy50cmVlQ29uZmlnPy50cmVlTm9kZUNvbnRlbnRDb21wb25lbnQpIHtcbiAgICAgIGNvbnN0IG5vZGVDb21wb25lbnQgPSB0aGlzLnZjUmVmLmNyZWF0ZUNvbXBvbmVudChcbiAgICAgICAgdGhpcy50cmVlQ29uZmlnLnRyZWVOb2RlQ29udGVudENvbXBvbmVudFxuICAgICAgKTtcbiAgICAgIG5vZGVDb21wb25lbnQuaW5zdGFuY2Uubm9kZVdyYXBwZXIgPSB0aGlzLm5vZGVXcmFwcGVyO1xuXG4gICAgICBub2RlQ29tcG9uZW50Lmluc3RhbmNlLmN1c3RvbUV2ZW50XG4gICAgICAgID8ucGlwZSh0YWtlVW50aWwodGhpcy5uZ1Vuc3Vic2NyaWJlKSlcbiAgICAgICAgLnN1YnNjcmliZSgodmFsdWU6IGFueSkgPT4gdGhpcy5jdXN0b21FdmVudC5lbWl0KHZhbHVlKSk7XG4gICAgfVxuICB9XG5cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy5uZ1Vuc3Vic2NyaWJlLm5leHQodW5kZWZpbmVkKTtcbiAgICB0aGlzLm5nVW5zdWJzY3JpYmUuY29tcGxldGUoKTtcbiAgfVxufVxuIiwiPGRpdlxuICBjbGFzcz1cInRyZWUtbm9kZS1jb250ZW50LWNvbnRhaW5lclwiXG4gIFtjbGFzcy5zZWxlY3RlZF09XCJpc1NlbGVjdGVkXCJcbiAgW2NsYXNzLmZpcnN0XT1cIm5vZGVXcmFwcGVyLmlzRmlyc3RDaGlsZFwiXG4gIFtjbGFzcy5sYXN0XT1cIm5vZGVXcmFwcGVyLmlzTGFzdENoaWxkXCJcbiAgW2NsYXNzLmlzLXNlbGVjdGFibGVdPVwibm9kZVdyYXBwZXIuaXNTZWxlY3RhYmxlXCJcbiAgKGNsaWNrKT1cImNsaWNrRXZlbnQuZW1pdCgpXCI+XG4gIDxkaXYgY2xhc3M9XCJ0cmVlLW5vZGUtZXhwYW5kLWNvbnRhaW5lclwiPlxuICAgIDxidXR0b25cbiAgICAgICpuZ0lmPVwibm9kZVdyYXBwZXIuY2hpbGRyZW4ubGVuZ3RoID4gMFwiXG4gICAgICBjbGFzcz1cInRyZWUtbm9kZS1leHBhbmRcIlxuICAgICAgY2RrVHJlZU5vZGVUb2dnbGVcbiAgICAgIFthdHRyLmFyaWEtbGFiZWxdPVwiJ1RvZ2dsZSAnICsgbm9kZVdyYXBwZXIuZGF0YS50aXRsZVwiXG4gICAgICAoY2xpY2spPVwiJGV2ZW50LnByZXZlbnREZWZhdWx0KClcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJjaGV2cm9uXCIgW2NsYXNzLnJvdGF0ZV09XCJ0cmVlQ29udHJvbC5pc0V4cGFuZGVkKG5vZGVXcmFwcGVyKVwiPlxuICAgICAgICA8c3ZnIGlkPVwiYVwiIHhtbG5zPVwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIiB2aWV3Qm94PVwiMCAwIDkgOVwiPlxuICAgICAgICAgIDxwYXRoXG4gICAgICAgICAgICBkPVwibTIuODMuMDlsNC4yLDQuMmMuMDUuMDUuMDkuMTQuMDkuMjFzLS4wNC4xNS0uMDkuMjFsLTQuMiw0LjJjLS4wNS4wNS0uMTQuMDktLjIxLjA5cy0uMTUtLjA0LS4yMS0uMDlsLS40NS0uNDVjLS4wNS0uMDUtLjA5LS4xMy0uMDktLjIxLDAtLjA3LjA0LS4xNS4wOS0uMjFsMy41NC0zLjU0TDEuOTcuOTZjLS4wNS0uMDUtLjA5LS4xNC0uMDktLjIxcy4wNC0uMTUuMDktLjIxbC40NS0uNDVjLjA1LS4wNS4xNC0uMDkuMjEtLjA5cy4xNS4wNC4yMS4wOVpcIlxuICAgICAgICAgICAgc3R5bGU9XCJmaWxsOiB2YXIoLS1pY29uLWNvbG9yLCAjMzMzKTsgc3Ryb2tlLXdpZHRoOiAwcHhcIiAvPlxuICAgICAgICA8L3N2Zz5cbiAgICAgIDwvZGl2PlxuICAgIDwvYnV0dG9uPlxuICA8L2Rpdj5cbiAgPGRpdiBjbGFzcz1cInNtYWxsLWhvcml6b250YWwtdHJlZS1saW5lXCI+PC9kaXY+XG4gIDxkaXYgY2xhc3M9XCJ0cmVlLW5vZGUtaWNvbi1jb250YWluZXJcIiAqbmdJZj1cIm5vZGVXcmFwcGVyLmRhdGEuZmFJY29uXCI+XG4gICAgPGkgY2xhc3M9XCJmYVwiIFtjbGFzc109XCJub2RlV3JhcHBlci5kYXRhLmZhSWNvblwiPjwvaT5cbiAgPC9kaXY+XG4gIDxkaXYgY2xhc3M9XCJ0cmVlLW5vZGUtY29udGVudFwiPlxuICAgIDxzcGFuXG4gICAgICAqbmdJZj1cIlxuICAgICAgICAhdHJlZUNvbmZpZz8udHJlZU5vZGVDb250ZW50Q29tcG9uZW50ICYmXG4gICAgICAgICF0cmVlQ29uZmlnPy50cmVlTm9kZUNvbnRlbnRUZW1wbGF0ZVxuICAgICAgXCI+XG4gICAgICB7eyBub2RlV3JhcHBlci5kYXRhLnRpdGxlIH19XG4gICAgPC9zcGFuPlxuICAgIDxuZy1jb250YWluZXIgI3JlZj48L25nLWNvbnRhaW5lcj5cbiAgICA8bmctY29udGFpbmVyICpuZ0lmPVwidHJlZUNvbmZpZz8udHJlZU5vZGVDb250ZW50VGVtcGxhdGUgYXMgdGVtcGxhdGVcIj5cbiAgICAgIDxuZy1jb250YWluZXJcbiAgICAgICAgKm5nVGVtcGxhdGVPdXRsZXQ9XCJcbiAgICAgICAgICB0ZW1wbGF0ZTtcbiAgICAgICAgICBjb250ZXh0OiB7XG4gICAgICAgICAgICBub2RlV3JhcHBlcjogbm9kZVdyYXBwZXJcbiAgICAgICAgICB9XG4gICAgICAgIFwiPjwvbmctY29udGFpbmVyPlxuICAgIDwvbmctY29udGFpbmVyPlxuICA8L2Rpdj5cbjwvZGl2PlxuIl19
@@ -0,0 +1,10 @@
1
+ export const isParentOf = (parent, node) => {
2
+ if (!node.parent) {
3
+ return false;
4
+ }
5
+ if (parent.id === node.parent.id) {
6
+ return true;
7
+ }
8
+ return isParentOf(parent, node.parent);
9
+ };
10
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmdjeC10cmVlLXV0aWxzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmdjeC10cmVlL3NyYy9saWIvbmdjeC10cmVlL25nY3gtdHJlZS11dGlscy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFFQSxNQUFNLENBQUMsTUFBTSxVQUFVLEdBQUcsQ0FDeEIsTUFBZ0MsRUFDaEMsSUFBOEIsRUFDckIsRUFBRTtJQUNYLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFO1FBQ2hCLE9BQU8sS0FBSyxDQUFDO0tBQ2Q7SUFDRCxJQUFJLE1BQU0sQ0FBQyxFQUFFLEtBQUssSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLEVBQUU7UUFDaEMsT0FBTyxJQUFJLENBQUM7S0FDYjtJQUNELE9BQU8sVUFBVSxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7QUFDekMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgTmdjeFRyZWVOb2RlV3JhcHBlciB9IGZyb20gJy4vbmdjeC10cmVlLW1vZGVscyc7XG5cbmV4cG9ydCBjb25zdCBpc1BhcmVudE9mID0gKFxuICBwYXJlbnQ6IE5nY3hUcmVlTm9kZVdyYXBwZXI8YW55PixcbiAgbm9kZTogTmdjeFRyZWVOb2RlV3JhcHBlcjxhbnk+XG4pOiBib29sZWFuID0+IHtcbiAgaWYgKCFub2RlLnBhcmVudCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICBpZiAocGFyZW50LmlkID09PSBub2RlLnBhcmVudC5pZCkge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG4gIHJldHVybiBpc1BhcmVudE9mKHBhcmVudCwgbm9kZS5wYXJlbnQpO1xufTtcbiJdfQ==