@acorex/components 21.0.0-next.38 → 21.0.0-next.39

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.
@@ -4,6 +4,7 @@ import { AXBadgeComponent } from '@acorex/components/badge';
4
4
  import { AXButtonComponent } from '@acorex/components/button';
5
5
  import { AXCheckBoxComponent } from '@acorex/components/check-box';
6
6
  import { AXDecoratorIconComponent } from '@acorex/components/decorators';
7
+ import { AXTooltipDirective } from '@acorex/components/tooltip';
7
8
  import { AXPlatform } from '@acorex/core/platform';
8
9
  import * as i1 from '@angular/common';
9
10
  import { CommonModule, NgTemplateOutlet } from '@angular/common';
@@ -27,12 +28,13 @@ class AXTreeViewService {
27
28
  /**
28
29
  * Find a node by ID in the tree
29
30
  */
30
- findNodeById(nodes, id) {
31
+ findNodeById(nodes, id, idField = 'id') {
31
32
  for (const node of nodes) {
32
- if (node.id === id)
33
+ if (node[idField] === id)
33
34
  return node;
34
- if (node.children) {
35
- const found = this.findNodeById(node.children, id);
35
+ const children = node['children'];
36
+ if (children) {
37
+ const found = this.findNodeById(children, id, idField);
36
38
  if (found)
37
39
  return found;
38
40
  }
@@ -42,13 +44,15 @@ class AXTreeViewService {
42
44
  /**
43
45
  * Find parent node of a given node
44
46
  */
45
- findParentNode(nodes, targetNode) {
47
+ findParentNode(nodes, targetNode, idField = 'id', childrenField = 'children') {
48
+ const targetId = targetNode[idField];
46
49
  for (const node of nodes) {
47
- if (node.children?.some((child) => child.id === targetNode.id)) {
50
+ const children = node[childrenField];
51
+ if (children?.some((child) => child[idField] === targetId)) {
48
52
  return node;
49
53
  }
50
- if (node.children) {
51
- const found = this.findParentNode(node.children, targetNode);
54
+ if (children) {
55
+ const found = this.findParentNode(children, targetNode, idField, childrenField);
52
56
  if (found)
53
57
  return found;
54
58
  }
@@ -59,8 +63,10 @@ class AXTreeViewService {
59
63
  * Check if targetNode is a descendant of ancestorNode (or the same node)
60
64
  * Prevents circular references by checking if target exists in ancestor's children tree
61
65
  */
62
- isValidDropTarget(movedNode, targetNode) {
63
- if (movedNode.id === targetNode.id || this.isNodeDescendantOf(targetNode, movedNode)) {
66
+ isValidDropTarget(movedNode, targetNode, idField = 'id', childrenField = 'children') {
67
+ const movedId = movedNode[idField];
68
+ const targetId = targetNode[idField];
69
+ if (movedId === targetId || this.isNodeDescendantOf(targetNode, movedNode, idField, childrenField)) {
64
70
  return false;
65
71
  }
66
72
  return true;
@@ -68,18 +74,22 @@ class AXTreeViewService {
68
74
  /**
69
75
  * Check if targetNode is a descendant of ancestorNode
70
76
  */
71
- isNodeDescendantOf(targetNode, ancestorNode) {
72
- if (targetNode.id === ancestorNode.id) {
77
+ isNodeDescendantOf(targetNode, ancestorNode, idField = 'id', childrenField = 'children') {
78
+ const targetId = targetNode[idField];
79
+ const ancestorId = ancestorNode[idField];
80
+ if (targetId === ancestorId) {
73
81
  return true;
74
82
  }
75
- if (!ancestorNode.children || ancestorNode.children.length === 0) {
83
+ const children = ancestorNode[childrenField];
84
+ if (!children || children.length === 0) {
76
85
  return false;
77
86
  }
78
- for (const child of ancestorNode.children) {
79
- if (child.id === targetNode.id) {
87
+ for (const child of children) {
88
+ const childId = child[idField];
89
+ if (childId === targetId) {
80
90
  return true;
81
91
  }
82
- if (this.isNodeDescendantOf(targetNode, child)) {
92
+ if (this.isNodeDescendantOf(targetNode, child, idField, childrenField)) {
83
93
  return true;
84
94
  }
85
95
  }
@@ -88,14 +98,18 @@ class AXTreeViewService {
88
98
  /**
89
99
  * Build a flat list of all visible focusable nodes
90
100
  */
91
- buildFlatNodeList(nodes) {
101
+ buildFlatNodeList(nodes, hiddenField = 'hidden', disabledField = 'disabled', expandedField = 'expanded', childrenField = 'children') {
92
102
  const flatList = [];
93
103
  const traverse = (nodeList, level, parent) => {
94
104
  for (const node of nodeList) {
95
- if (node.visible !== false && !node.disabled) {
105
+ const hidden = node[hiddenField];
106
+ const disabled = node[disabledField];
107
+ if (hidden !== true && !disabled) {
96
108
  flatList.push({ node, level, parent });
97
- if (node.expanded && node.children) {
98
- traverse(node.children, level + 1, node);
109
+ const expanded = node[expandedField];
110
+ const children = node[childrenField];
111
+ if (expanded && children) {
112
+ traverse(children, level + 1, node);
99
113
  }
100
114
  }
101
115
  }
@@ -107,39 +121,44 @@ class AXTreeViewService {
107
121
  /**
108
122
  * Check if node has children
109
123
  */
110
- hasChildren(node) {
111
- return Boolean(node.children?.length);
124
+ hasChildren(node, childrenField = 'children') {
125
+ const children = node[childrenField];
126
+ return Boolean(children?.length);
112
127
  }
113
128
  /**
114
129
  * Check if node can be lazy loaded
115
130
  */
116
- canLazyLoad(node, isLazyDataSource) {
117
- return isLazyDataSource && Boolean(node.childrenCount && node.childrenCount > 0 && !this.hasChildren(node));
131
+ canLazyLoad(node, isLazyDataSource, childrenCountField = 'childrenCount', childrenField = 'children') {
132
+ const childrenCount = node[childrenCountField];
133
+ return isLazyDataSource && Boolean(childrenCount && childrenCount > 0 && !this.hasChildren(node, childrenField));
118
134
  }
119
135
  // ==================== Selection Management ====================
120
136
  /**
121
137
  * Recursively select/deselect all children
122
138
  */
123
- selectAllChildren(children, selected) {
139
+ selectAllChildren(children, selected, selectedField = 'selected', indeterminateField = 'indeterminate', childrenField = 'children') {
124
140
  for (const child of children) {
125
- child.selected = selected;
126
- child.indeterminate = false;
127
- if (child.children) {
128
- this.selectAllChildren(child.children, selected);
141
+ child[selectedField] = selected;
142
+ child[indeterminateField] = false;
143
+ const childChildren = child[childrenField];
144
+ if (childChildren) {
145
+ this.selectAllChildren(childChildren, selected, selectedField, indeterminateField, childrenField);
129
146
  }
130
147
  }
131
148
  }
132
149
  /**
133
150
  * Get selection state of children
134
151
  */
135
- getChildrenSelectionState(children) {
152
+ getChildrenSelectionState(children, selectedField = 'selected', indeterminateField = 'indeterminate') {
136
153
  let selectedCount = 0;
137
154
  let indeterminateCount = 0;
138
155
  for (const child of children) {
139
- if (child.selected && !child.indeterminate) {
156
+ const selected = child[selectedField];
157
+ const indeterminate = child[indeterminateField];
158
+ if (selected && !indeterminate) {
140
159
  selectedCount++;
141
160
  }
142
- if (child.indeterminate) {
161
+ if (indeterminate) {
143
162
  indeterminateCount++;
144
163
  }
145
164
  }
@@ -151,65 +170,69 @@ class AXTreeViewService {
151
170
  /**
152
171
  * Update parent node states based on children selection (with intermediate state support)
153
172
  */
154
- updateParentStates(nodes, changedNode, intermediateState) {
155
- const parent = this.findParentNode(nodes, changedNode);
156
- if (!parent || !parent.children)
173
+ updateParentStates(nodes, changedNode, intermediateState, idField = 'id', childrenField = 'children', selectedField = 'selected', indeterminateField = 'indeterminate') {
174
+ const parent = this.findParentNode(nodes, changedNode, idField, childrenField);
175
+ const parentChildren = parent?.[childrenField];
176
+ if (!parent || !parentChildren)
157
177
  return;
158
- const { allSelected, someSelected } = this.getChildrenSelectionState(parent.children);
178
+ const { allSelected, someSelected } = this.getChildrenSelectionState(parentChildren, selectedField, indeterminateField);
159
179
  if (allSelected) {
160
- parent.selected = true;
161
- parent.indeterminate = false;
180
+ parent[selectedField] = true;
181
+ parent[indeterminateField] = false;
162
182
  }
163
183
  else if (someSelected) {
164
184
  if (intermediateState) {
165
- parent.selected = true;
166
- parent.indeterminate = true;
185
+ parent[selectedField] = true;
186
+ parent[indeterminateField] = true;
167
187
  }
168
188
  else {
169
- parent.selected = false;
170
- parent.indeterminate = false;
189
+ parent[selectedField] = false;
190
+ parent[indeterminateField] = false;
171
191
  }
172
192
  }
173
193
  else {
174
- parent.selected = false;
175
- parent.indeterminate = false;
194
+ parent[selectedField] = false;
195
+ parent[indeterminateField] = false;
176
196
  }
177
- this.updateParentStates(nodes, parent, intermediateState);
197
+ this.updateParentStates(nodes, parent, intermediateState, idField, childrenField, selectedField, indeterminateField);
178
198
  }
179
199
  /**
180
200
  * Recursively deselect all nodes
181
201
  */
182
- deselectAllNodes(nodes) {
202
+ deselectAllNodes(nodes, selectedField = 'selected', indeterminateField = 'indeterminate', childrenField = 'children') {
183
203
  for (const node of nodes) {
184
- node.selected = false;
185
- node.indeterminate = false;
186
- if (node.children) {
187
- this.deselectAllNodes(node.children);
204
+ node[selectedField] = false;
205
+ node[indeterminateField] = false;
206
+ const children = node[childrenField];
207
+ if (children) {
208
+ this.deselectAllNodes(children, selectedField, indeterminateField, childrenField);
188
209
  }
189
210
  }
190
211
  }
191
212
  /**
192
213
  * Recursively set selection state for all nodes
193
214
  */
194
- setAllSelection(nodes, selected) {
215
+ setAllSelection(nodes, selected, selectedField = 'selected', indeterminateField = 'indeterminate', childrenField = 'children') {
195
216
  for (const node of nodes) {
196
- node.selected = selected;
197
- node.indeterminate = false;
198
- if (node.children) {
199
- this.setAllSelection(node.children, selected);
217
+ node[selectedField] = selected;
218
+ node[indeterminateField] = false;
219
+ const children = node[childrenField];
220
+ if (children) {
221
+ this.setAllSelection(children, selected, selectedField, indeterminateField, childrenField);
200
222
  }
201
223
  }
202
224
  }
203
225
  /**
204
226
  * Recursively count selected nodes
205
227
  */
206
- countSelected(nodes) {
228
+ countSelected(nodes, selectedField = 'selected', childrenField = 'children') {
207
229
  let count = 0;
208
230
  for (const node of nodes) {
209
- if (node.selected)
231
+ if (node[selectedField])
210
232
  count++;
211
- if (node.children) {
212
- count += this.countSelected(node.children);
233
+ const children = node[childrenField];
234
+ if (children) {
235
+ count += this.countSelected(children, selectedField, childrenField);
213
236
  }
214
237
  }
215
238
  return count;
@@ -217,53 +240,61 @@ class AXTreeViewService {
217
240
  /**
218
241
  * Recursively collect selected nodes
219
242
  */
220
- collectSelected(nodes, result) {
243
+ collectSelected(nodes, result, selectedField = 'selected', childrenField = 'children') {
221
244
  for (const node of nodes) {
222
- if (node.selected)
245
+ if (node[selectedField])
223
246
  result.push(node);
224
- if (node.children) {
225
- this.collectSelected(node.children, result);
247
+ const children = node[childrenField];
248
+ if (children) {
249
+ this.collectSelected(children, result, selectedField, childrenField);
226
250
  }
227
251
  }
228
252
  }
229
253
  /**
230
254
  * Recursively remove selected nodes
231
255
  */
232
- removeSelected(nodes) {
256
+ removeSelected(nodes, selectedField = 'selected', indeterminateField = 'indeterminate', childrenField = 'children') {
233
257
  for (let i = nodes.length - 1; i >= 0; i--) {
234
- if (nodes[i].selected && !nodes[i].indeterminate) {
258
+ const node = nodes[i];
259
+ const selected = node[selectedField];
260
+ const indeterminate = node[indeterminateField];
261
+ if (selected && !indeterminate) {
235
262
  nodes.splice(i, 1);
236
263
  }
237
- else if (nodes[i].children) {
238
- this.removeSelected(nodes[i].children ?? []);
264
+ else {
265
+ const children = node[childrenField];
266
+ if (children) {
267
+ this.removeSelected(children, selectedField, indeterminateField, childrenField);
268
+ }
239
269
  }
240
270
  }
241
271
  }
242
272
  /**
243
273
  * Recursively update all parent states in the tree (used after deletion)
244
274
  */
245
- updateAllParentStates(nodes, intermediateState) {
275
+ updateAllParentStates(nodes, intermediateState, childrenField = 'children', selectedField = 'selected', indeterminateField = 'indeterminate') {
246
276
  for (const node of nodes) {
247
- if (node.children && node.children.length > 0) {
248
- this.updateAllParentStates(node.children, intermediateState);
249
- const { allSelected, someSelected } = this.getChildrenSelectionState(node.children);
277
+ const children = node[childrenField];
278
+ if (children && children.length > 0) {
279
+ this.updateAllParentStates(children, intermediateState, childrenField, selectedField, indeterminateField);
280
+ const { allSelected, someSelected } = this.getChildrenSelectionState(children, selectedField, indeterminateField);
250
281
  if (allSelected) {
251
- node.selected = true;
252
- node.indeterminate = false;
282
+ node[selectedField] = true;
283
+ node[indeterminateField] = false;
253
284
  }
254
285
  else if (someSelected) {
255
286
  if (intermediateState) {
256
- node.selected = true;
257
- node.indeterminate = true;
287
+ node[selectedField] = true;
288
+ node[indeterminateField] = true;
258
289
  }
259
290
  else {
260
- node.selected = false;
261
- node.indeterminate = false;
291
+ node[selectedField] = false;
292
+ node[indeterminateField] = false;
262
293
  }
263
294
  }
264
295
  else {
265
- node.selected = false;
266
- node.indeterminate = false;
296
+ node[selectedField] = false;
297
+ node[indeterminateField] = false;
267
298
  }
268
299
  }
269
300
  }
@@ -272,17 +303,18 @@ class AXTreeViewService {
272
303
  /**
273
304
  * Recursively set expanded state (with lazy loading)
274
305
  */
275
- async setExpandedState(nodes, expanded, isLazyDataSource, loadNodeChildren) {
306
+ async setExpandedState(nodes, expanded, isLazyDataSource, loadNodeChildren, expandedField = 'expanded', childrenField = 'children', childrenCountField = 'childrenCount') {
276
307
  for (const node of nodes) {
277
- const hasChildren = this.hasChildren(node);
278
- const canLazyLoad = this.canLazyLoad(node, isLazyDataSource);
308
+ const hasChildren = this.hasChildren(node, childrenField);
309
+ const canLazyLoad = this.canLazyLoad(node, isLazyDataSource, childrenCountField, childrenField);
279
310
  if (hasChildren || canLazyLoad) {
280
311
  if (expanded && canLazyLoad) {
281
312
  await loadNodeChildren(node);
282
313
  }
283
- node.expanded = expanded;
284
- if (node.children) {
285
- await this.setExpandedState(node.children, expanded, isLazyDataSource, loadNodeChildren);
314
+ node[expandedField] = expanded;
315
+ const children = node[childrenField];
316
+ if (children) {
317
+ await this.setExpandedState(children, expanded, isLazyDataSource, loadNodeChildren, expandedField, childrenField, childrenCountField);
286
318
  }
287
319
  }
288
320
  }
@@ -291,23 +323,24 @@ class AXTreeViewService {
291
323
  /**
292
324
  * Get array reference by drop list ID
293
325
  */
294
- getArrayByListId(nodes, listId) {
326
+ getArrayByListId(nodes, listId, idField = 'id', childrenField = 'children') {
295
327
  if (listId === AXTreeViewService.ROOT_LIST_ID) {
296
328
  return nodes;
297
329
  }
298
330
  if (listId.startsWith(AXTreeViewService.NODE_DROP_PREFIX)) {
299
331
  const nodeId = listId.replace(AXTreeViewService.NODE_DROP_PREFIX, '');
300
- const node = this.findNodeById(nodes, nodeId);
332
+ const node = this.findNodeById(nodes, nodeId, idField);
301
333
  return node ? [node] : null;
302
334
  }
303
335
  const nodeId = listId.replace(AXTreeViewService.LIST_PREFIX, '');
304
- const node = this.findNodeById(nodes, nodeId);
305
- return node?.children ?? null;
336
+ const node = this.findNodeById(nodes, nodeId, idField);
337
+ const children = node?.[childrenField];
338
+ return children ?? null;
306
339
  }
307
340
  /**
308
341
  * Find parent node by list ID
309
342
  */
310
- findParentByListId(nodes, listId) {
343
+ findParentByListId(nodes, listId, idField = 'id') {
311
344
  if (listId === AXTreeViewService.ROOT_LIST_ID) {
312
345
  return undefined;
313
346
  }
@@ -315,13 +348,16 @@ class AXTreeViewService {
315
348
  ? AXTreeViewService.NODE_DROP_PREFIX
316
349
  : AXTreeViewService.LIST_PREFIX;
317
350
  const nodeId = listId.replace(prefix, '');
318
- return this.findNodeById(nodes, nodeId) ?? undefined;
351
+ return this.findNodeById(nodes, nodeId, idField) ?? undefined;
319
352
  }
320
353
  /**
321
354
  * Generate unique list ID for each node
322
355
  */
323
- getListId(node) {
324
- return node ? `${AXTreeViewService.LIST_PREFIX}${node.id}` : AXTreeViewService.ROOT_LIST_ID;
356
+ getListId(node, idField = 'id') {
357
+ if (!node)
358
+ return AXTreeViewService.ROOT_LIST_ID;
359
+ const nodeId = node[idField];
360
+ return `${AXTreeViewService.LIST_PREFIX}${nodeId}`;
325
361
  }
326
362
  /**
327
363
  * Get root list ID constant
@@ -341,6 +377,122 @@ class AXTreeViewService {
341
377
  getListPrefix() {
342
378
  return AXTreeViewService.LIST_PREFIX;
343
379
  }
380
+ // ==================== Node Utilities ====================
381
+ /**
382
+ * Get all nodes in a flat array
383
+ */
384
+ getAllNodes(nodes, childrenField = 'children') {
385
+ const allNodes = [];
386
+ const traverse = (nodeList) => {
387
+ for (const node of nodeList) {
388
+ allNodes.push(node);
389
+ const children = node[childrenField];
390
+ if (children) {
391
+ traverse(children);
392
+ }
393
+ }
394
+ };
395
+ traverse(nodes);
396
+ return allNodes;
397
+ }
398
+ /**
399
+ * Get the path to a node (array of parent nodes from root to node)
400
+ */
401
+ getNodePath(nodes, nodeId) {
402
+ const path = [];
403
+ const node = this.findNodeById(nodes, nodeId);
404
+ if (!node) {
405
+ return path;
406
+ }
407
+ let current = node;
408
+ while (current) {
409
+ path.unshift(current);
410
+ const parent = this.findParentNode(nodes, current);
411
+ current = parent ?? null;
412
+ }
413
+ return path;
414
+ }
415
+ /**
416
+ * Get the level/depth of a node (0 = root level)
417
+ */
418
+ getNodeLevel(nodes, nodeId) {
419
+ const path = this.getNodePath(nodes, nodeId);
420
+ return path.length > 0 ? path.length - 1 : -1;
421
+ }
422
+ /**
423
+ * Get sibling nodes of a given node
424
+ */
425
+ getSiblings(nodes, nodeId, idField = 'id', childrenField = 'children') {
426
+ const node = this.findNodeById(nodes, nodeId, idField);
427
+ if (!node) {
428
+ return [];
429
+ }
430
+ const parent = this.findParentNode(nodes, node, idField, childrenField);
431
+ const siblingsArray = parent?.[childrenField] ?? nodes;
432
+ return siblingsArray.filter((n) => n[idField] !== nodeId);
433
+ }
434
+ /**
435
+ * Clone a node (creates a deep copy)
436
+ */
437
+ cloneNode(node, idField = 'id', titleField = 'title', tooltipField = 'tooltip', iconField = 'icon', expandedField = 'expanded', selectedField = 'selected', indeterminateField = 'indeterminate', disabledField = 'disabled', hiddenField = 'hidden', childrenCountField = 'childrenCount', dataField = 'data', childrenField = 'children') {
438
+ const cloned = {
439
+ [idField]: `${node[idField]}-clone-${Date.now()}`,
440
+ [titleField]: node[titleField],
441
+ [tooltipField]: node[tooltipField],
442
+ [iconField]: node[iconField],
443
+ [expandedField]: node[expandedField],
444
+ [selectedField]: false, // Cloned nodes are not selected by default
445
+ [indeterminateField]: false,
446
+ [disabledField]: node[disabledField],
447
+ [hiddenField]: node[hiddenField],
448
+ [childrenCountField]: node[childrenCountField],
449
+ [dataField]: node[dataField] ? JSON.parse(JSON.stringify(node[dataField])) : undefined,
450
+ };
451
+ const children = node[childrenField];
452
+ if (children && children.length > 0) {
453
+ cloned[childrenField] = children.map((child) => this.cloneNode(child, idField, titleField, tooltipField, iconField, expandedField, selectedField, indeterminateField, disabledField, hiddenField, childrenCountField, dataField, childrenField));
454
+ cloned[childrenCountField] = cloned[childrenField].length;
455
+ }
456
+ return cloned;
457
+ }
458
+ /**
459
+ * Validate node structure (check for required fields and circular references)
460
+ */
461
+ validateNode(node, visitedIds = new Set(), idField = 'id', titleField = 'title', childrenField = 'children', childrenCountField = 'childrenCount') {
462
+ const errors = [];
463
+ const nodeId = node[idField];
464
+ const nodeTitle = node[titleField];
465
+ if (!nodeId) {
466
+ errors.push(`Node must have an ${idField}`);
467
+ }
468
+ if (!nodeTitle) {
469
+ errors.push(`Node must have a ${titleField}`);
470
+ }
471
+ if (nodeId && visitedIds.has(nodeId)) {
472
+ errors.push(`Circular reference detected: node ${nodeId} appears multiple times in the tree`);
473
+ }
474
+ const children = node[childrenField];
475
+ if (children) {
476
+ const newVisited = new Set(visitedIds);
477
+ if (nodeId) {
478
+ newVisited.add(nodeId);
479
+ }
480
+ for (const child of children) {
481
+ const childValidation = this.validateNode(child, newVisited, idField, titleField, childrenField, childrenCountField);
482
+ if (!childValidation.valid) {
483
+ errors.push(...childValidation.errors.map((e) => `Child of ${nodeId}: ${e}`));
484
+ }
485
+ }
486
+ const childrenCount = node[childrenCountField];
487
+ if (childrenCount !== undefined && childrenCount !== children.length) {
488
+ errors.push(`Node ${nodeId}: ${childrenCountField} (${childrenCount}) does not match ${childrenField} array length (${children.length})`);
489
+ }
490
+ }
491
+ return {
492
+ valid: errors.length === 0,
493
+ errors,
494
+ };
495
+ }
344
496
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: AXTreeViewService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
345
497
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: AXTreeViewService }); }
346
498
  }
@@ -361,10 +513,8 @@ class AXTreeViewComponent {
361
513
  this.selectMode = input('multiple', ...(ngDevMode ? [{ debugName: "selectMode" }] : []));
362
514
  /** Whether to show checkboxes for selection (only applies to multiple mode) */
363
515
  this.showCheckbox = input(true, ...(ngDevMode ? [{ debugName: "showCheckbox" }] : []));
364
- /** When true, selecting a parent also selects all loaded children (only for multiple mode) */
365
- this.checkChildrenOnSelect = input(true, ...(ngDevMode ? [{ debugName: "checkChildrenOnSelect" }] : []));
366
- /** When true, selecting a child makes parents indeterminate (only for multiple mode) */
367
- this.intermediateState = input(true, ...(ngDevMode ? [{ debugName: "intermediateState" }] : []));
516
+ /** Selection behavior: 'all' (select anything, no special behavior), 'intermediate' (parent indeterminate state when children selected), 'leaf' (only leaf nodes selectable), 'nested' (selecting parent selects all children) */
517
+ this.selectionBehavior = input('all', ...(ngDevMode ? [{ debugName: "selectionBehavior" }] : []));
368
518
  /** When true, clicking on a node toggles its selection (works for both single and multiple modes) */
369
519
  this.checkOnClick = input(false, ...(ngDevMode ? [{ debugName: "checkOnClick" }] : []));
370
520
  /** Drag and drop mode: 'none' (disabled), 'handler' (drag handle), 'item' (entire item) */
@@ -380,13 +530,35 @@ class AXTreeViewComponent {
380
530
  /** Custom icon for collapsed nodes */
381
531
  this.collapsedIcon = input('fa-solid fa-chevron-right', ...(ngDevMode ? [{ debugName: "collapsedIcon" }] : []));
382
532
  /** Indent size in pixels for each level */
383
- this.indentSize = input(12, ...(ngDevMode ? [{ debugName: "indentSize" }] : []));
384
- /** Node height in pixels */
385
- this.nodeHeight = input('normal', ...(ngDevMode ? [{ debugName: "nodeHeight" }] : []));
533
+ this.indentSize = input(16, ...(ngDevMode ? [{ debugName: "indentSize" }] : []));
386
534
  /** Visual style variant */
387
535
  this.look = input('default', ...(ngDevMode ? [{ debugName: "look" }] : []));
388
536
  /** Custom template for tree items */
389
- this.itemTemplate = input(...(ngDevMode ? [undefined, { debugName: "itemTemplate" }] : []));
537
+ this.nodeTemplate = input(...(ngDevMode ? [undefined, { debugName: "nodeTemplate" }] : []));
538
+ /** Field name for node ID (default: 'id') */
539
+ this.idField = input('id', ...(ngDevMode ? [{ debugName: "idField" }] : []));
540
+ /** Field name for node title (default: 'title') */
541
+ this.titleField = input('title', ...(ngDevMode ? [{ debugName: "titleField" }] : []));
542
+ /** Field name for node tooltip (default: 'tooltip') */
543
+ this.tooltipField = input('tooltip', ...(ngDevMode ? [{ debugName: "tooltipField" }] : []));
544
+ /** Field name for node icon (default: 'icon') */
545
+ this.iconField = input('icon', ...(ngDevMode ? [{ debugName: "iconField" }] : []));
546
+ /** Field name for expanded state (default: 'expanded') */
547
+ this.expandedField = input('expanded', ...(ngDevMode ? [{ debugName: "expandedField" }] : []));
548
+ /** Field name for selected state (default: 'selected') */
549
+ this.selectedField = input('selected', ...(ngDevMode ? [{ debugName: "selectedField" }] : []));
550
+ /** Field name for indeterminate state (default: 'indeterminate') */
551
+ this.indeterminateField = input('indeterminate', ...(ngDevMode ? [{ debugName: "indeterminateField" }] : []));
552
+ /** Field name for disabled state (default: 'disabled') */
553
+ this.disabledField = input('disabled', ...(ngDevMode ? [{ debugName: "disabledField" }] : []));
554
+ /** Field name for hidden state (default: 'hidden') */
555
+ this.hiddenField = input('hidden', ...(ngDevMode ? [{ debugName: "hiddenField" }] : []));
556
+ /** Field name for children array (default: 'children') */
557
+ this.childrenField = input('children', ...(ngDevMode ? [{ debugName: "childrenField" }] : []));
558
+ /** Field name for children count (default: 'childrenCount') */
559
+ this.childrenCountField = input('childrenCount', ...(ngDevMode ? [{ debugName: "childrenCountField" }] : []));
560
+ /** Field name for custom data (default: 'data') */
561
+ this.dataField = input('data', ...(ngDevMode ? [{ debugName: "dataField" }] : []));
390
562
  // ==================== Outputs ====================
391
563
  /** Emitted before a drop operation - set canceled to true to prevent drop */
392
564
  this.onBeforeDrop = output();
@@ -394,6 +566,8 @@ class AXTreeViewComponent {
394
566
  this.onNodeToggle = output();
395
567
  /** Emitted when a node is selected/deselected */
396
568
  this.onNodeSelect = output();
569
+ /** Emitted when selection changes - returns all currently selected nodes */
570
+ this.onSelectionChange = output();
397
571
  /** Emitted when nodes are reordered within the same parent */
398
572
  this.onOrderChange = output();
399
573
  /** Emitted when a node is moved to a different parent */
@@ -426,19 +600,35 @@ class AXTreeViewComponent {
426
600
  this.isUpdatingFromDatasource = false;
427
601
  /** Computed to check if datasource is a function */
428
602
  this.isLazyDataSource = computed(() => typeof this.datasource() === 'function', ...(ngDevMode ? [{ debugName: "isLazyDataSource" }] : []));
603
+ /** Computed: Returns true when selection is restricted to leaf nodes only */
604
+ this.isLeafOnlyMode = computed(() => this.selectionBehavior() === 'leaf', ...(ngDevMode ? [{ debugName: "isLeafOnlyMode" }] : []));
605
+ /** Computed: Returns true when selecting a parent automatically selects all its children */
606
+ this.cascadesToChildren = computed(() => {
607
+ const behavior = this.selectionBehavior();
608
+ return behavior === 'nested' || behavior === 'intermediate-nested';
609
+ }, ...(ngDevMode ? [{ debugName: "cascadesToChildren" }] : []));
610
+ /** Computed: Returns true when parent nodes show indeterminate state based on children selection */
611
+ this.hasIntermediateState = computed(() => {
612
+ const behavior = this.selectionBehavior();
613
+ return behavior === 'intermediate' || behavior === 'intermediate-nested';
614
+ }, ...(ngDevMode ? [{ debugName: "hasIntermediateState" }] : []));
429
615
  // ==================== Effects ====================
430
616
  /** Effect to handle datasource changes */
431
- this.#datasourceEffect = effect(() => {
432
- if (this.isUpdatingFromDatasource)
617
+ this.#datasourceEffect = effect(async () => {
618
+ if (this.isUpdatingFromDatasource) {
433
619
  return;
620
+ }
434
621
  const ds = this.datasource();
435
622
  if (Array.isArray(ds)) {
436
623
  this.nodes.set([...ds]);
437
624
  }
438
625
  else if (typeof ds === 'function') {
439
- this.loadRootItems(ds).catch((error) => {
626
+ try {
627
+ await this.loadRootItems(ds);
628
+ }
629
+ catch (error) {
440
630
  this.handleError('Failed to load root items', error);
441
- });
631
+ }
442
632
  }
443
633
  }, ...(ngDevMode ? [{ debugName: "#datasourceEffect" }] : []));
444
634
  /** Initialize direction change listener */
@@ -448,6 +638,115 @@ class AXTreeViewComponent {
448
638
  .subscribe((isRtl) => this.isRtl.set(isRtl));
449
639
  });
450
640
  }
641
+ // ==================== Node Property Helpers ====================
642
+ /**
643
+ * Get a property value from a node using the configured field name
644
+ */
645
+ getNodeProp(node, fieldName, defaultValue) {
646
+ return node[fieldName] ?? defaultValue;
647
+ }
648
+ /**
649
+ * Set a property value on a node using the configured field name
650
+ */
651
+ setNodeProp(node, fieldName, value) {
652
+ node[fieldName] = value;
653
+ }
654
+ /**
655
+ * Get node ID
656
+ */
657
+ getNodeId(node) {
658
+ return this.getNodeProp(node, this.idField(), '');
659
+ }
660
+ /**
661
+ * Get node title
662
+ */
663
+ getNodeTitle(node) {
664
+ return this.getNodeProp(node, this.titleField(), '');
665
+ }
666
+ /**
667
+ * Get node tooltip
668
+ */
669
+ getNodeTooltip(node) {
670
+ return this.getNodeProp(node, this.tooltipField(), undefined);
671
+ }
672
+ /**
673
+ * Get node icon
674
+ */
675
+ getNodeIcon(node) {
676
+ return this.getNodeProp(node, this.iconField(), undefined);
677
+ }
678
+ /**
679
+ * Get node expanded state
680
+ */
681
+ getNodeExpanded(node) {
682
+ return this.getNodeProp(node, this.expandedField(), false);
683
+ }
684
+ /**
685
+ * Set node expanded state
686
+ */
687
+ setNodeExpanded(node, value) {
688
+ this.setNodeProp(node, this.expandedField(), value);
689
+ }
690
+ /**
691
+ * Get node selected state
692
+ */
693
+ getNodeSelected(node) {
694
+ return this.getNodeProp(node, this.selectedField(), false);
695
+ }
696
+ /**
697
+ * Set node selected state
698
+ */
699
+ setNodeSelected(node, value) {
700
+ this.setNodeProp(node, this.selectedField(), value);
701
+ }
702
+ /**
703
+ * Get node indeterminate state
704
+ */
705
+ getNodeIndeterminate(node) {
706
+ return this.getNodeProp(node, this.indeterminateField(), false);
707
+ }
708
+ /**
709
+ * Set node indeterminate state
710
+ */
711
+ setNodeIndeterminate(node, value) {
712
+ this.setNodeProp(node, this.indeterminateField(), value);
713
+ }
714
+ /**
715
+ * Get node disabled state
716
+ */
717
+ getNodeDisabled(node) {
718
+ return this.getNodeProp(node, this.disabledField(), false);
719
+ }
720
+ /**
721
+ * Get node hidden state
722
+ */
723
+ getNodeHidden(node) {
724
+ return this.getNodeProp(node, this.hiddenField(), false);
725
+ }
726
+ /**
727
+ * Get node children array
728
+ */
729
+ getNodeChildren(node) {
730
+ return this.getNodeProp(node, this.childrenField(), undefined);
731
+ }
732
+ /**
733
+ * Set node children array
734
+ */
735
+ setNodeChildren(node, value) {
736
+ this.setNodeProp(node, this.childrenField(), value);
737
+ }
738
+ /**
739
+ * Get node children count
740
+ */
741
+ getNodeChildrenCount(node) {
742
+ return this.getNodeProp(node, this.childrenCountField(), undefined);
743
+ }
744
+ /**
745
+ * Set node children count
746
+ */
747
+ setNodeChildrenCount(node, value) {
748
+ this.setNodeProp(node, this.childrenCountField(), value);
749
+ }
451
750
  // ==================== Effects ====================
452
751
  /** Effect to handle datasource changes */
453
752
  #datasourceEffect;
@@ -458,21 +757,21 @@ class AXTreeViewComponent {
458
757
  * Expand all nodes in the tree (with lazy loading support)
459
758
  */
460
759
  async expandAll() {
461
- await this.treeService.setExpandedState(this.nodes(), true, this.isLazyDataSource(), (node) => this.loadNodeChildren(node));
760
+ await this.treeService.setExpandedState(this.nodes(), true, this.isLazyDataSource(), (node) => this.loadNodeChildren(node), this.expandedField(), this.childrenField(), this.childrenCountField());
462
761
  this.refreshNodes();
463
762
  }
464
763
  /**
465
764
  * Collapse all nodes in the tree
466
765
  */
467
766
  collapseAll() {
468
- this.treeService.setExpandedState(this.nodes(), false, this.isLazyDataSource(), (node) => this.loadNodeChildren(node));
767
+ this.treeService.setExpandedState(this.nodes(), false, this.isLazyDataSource(), (node) => this.loadNodeChildren(node), this.expandedField(), this.childrenField(), this.childrenCountField());
469
768
  this.refreshNodes();
470
769
  }
471
770
  /**
472
771
  * Get count of selected nodes
473
772
  */
474
773
  getSelectedCount() {
475
- return this.treeService.countSelected(this.nodes());
774
+ return this.treeService.countSelected(this.nodes(), this.selectedField(), this.childrenField());
476
775
  }
477
776
  /**
478
777
  * Check if any nodes are selected
@@ -485,36 +784,62 @@ class AXTreeViewComponent {
485
784
  */
486
785
  getSelectedNodes() {
487
786
  const selected = [];
488
- this.treeService.collectSelected(this.nodes(), selected);
787
+ this.treeService.collectSelected(this.nodes(), selected, this.selectedField(), this.childrenField());
489
788
  return selected;
490
789
  }
491
790
  /**
492
791
  * Delete selected nodes from the tree
493
792
  */
494
793
  deleteSelected() {
495
- this.treeService.removeSelected(this.nodes());
496
- this.treeService.updateAllParentStates(this.nodes(), this.intermediateState());
794
+ this.treeService.removeSelected(this.nodes(), this.selectedField(), this.indeterminateField(), this.childrenField());
795
+ if (!this.isLeafOnlyMode()) {
796
+ this.treeService.updateAllParentStates(this.nodes(), this.hasIntermediateState(), this.childrenField(), this.selectedField(), this.indeterminateField());
797
+ }
497
798
  this.refreshNodes();
799
+ this.emitSelectionChange();
498
800
  }
499
801
  /**
500
802
  * Select all nodes in the tree
501
803
  */
502
804
  selectAll() {
503
- this.treeService.setAllSelection(this.nodes(), true);
805
+ if (this.selectMode() === 'none') {
806
+ return;
807
+ }
808
+ if (this.isLeafOnlyMode()) {
809
+ // Only select leaf nodes
810
+ const selectLeafs = (nodes) => {
811
+ for (const node of nodes) {
812
+ if (this.isLeafNode(node) && !this.getNodeDisabled(node)) {
813
+ this.setNodeSelected(node, true);
814
+ this.setNodeIndeterminate(node, false);
815
+ }
816
+ const children = this.getNodeChildren(node);
817
+ if (children) {
818
+ selectLeafs(children);
819
+ }
820
+ }
821
+ };
822
+ selectLeafs(this.nodes());
823
+ }
824
+ else {
825
+ this.treeService.setAllSelection(this.nodes(), true, this.selectedField(), this.indeterminateField(), this.childrenField());
826
+ }
504
827
  this.refreshNodes();
828
+ this.emitSelectionChange();
505
829
  }
506
830
  /**
507
831
  * Deselect all nodes in the tree
508
832
  */
509
833
  deselectAll() {
510
- this.treeService.setAllSelection(this.nodes(), false);
834
+ this.treeService.setAllSelection(this.nodes(), false, this.selectedField(), this.indeterminateField(), this.childrenField());
511
835
  this.refreshNodes();
836
+ this.emitSelectionChange();
512
837
  }
513
838
  /**
514
839
  * Find a node by ID in the tree
515
840
  */
516
841
  findNode(id) {
517
- return this.treeService.findNodeById(this.nodes(), id);
842
+ return this.treeService.findNodeById(this.nodes(), id, this.idField());
518
843
  }
519
844
  /**
520
845
  * Refresh the tree to trigger change detection
@@ -528,17 +853,479 @@ class AXTreeViewComponent {
528
853
  isNodeLoading(nodeId) {
529
854
  return this.loadingNodes().has(nodeId);
530
855
  }
856
+ /**
857
+ * Get loading state for a node (internal state)
858
+ */
859
+ getNodeLoading(node) {
860
+ return this.loadingNodes().has(this.getNodeId(node));
861
+ }
862
+ /**
863
+ * Edit/update a node's properties
864
+ * @param nodeId - The ID of the node to edit
865
+ * @param updates - Partial node object with properties to update
866
+ * @returns true if node was found and updated, false otherwise
867
+ */
868
+ editNode(nodeId, updates) {
869
+ const node = this.findNode(nodeId);
870
+ if (!node) {
871
+ return false;
872
+ }
873
+ // Update node properties
874
+ Object.assign(node, updates);
875
+ // If children array is provided, ensure it exists
876
+ const childrenField = this.childrenField();
877
+ if (updates[childrenField] !== undefined) {
878
+ this.setNodeChildren(node, updates[childrenField]);
879
+ }
880
+ // Update childrenCount if children array is provided
881
+ if (updates[childrenField] !== undefined) {
882
+ const children = updates[childrenField];
883
+ this.setNodeChildrenCount(node, children?.length);
884
+ }
885
+ this.refreshNodes();
886
+ return true;
887
+ }
888
+ /**
889
+ * Add a child node to a parent node
890
+ * @param parentId - The ID of the parent node
891
+ * @param childNode - The child node to add
892
+ * @param index - Optional index to insert at (default: append to end)
893
+ * @returns true if parent was found and child was added, false otherwise
894
+ */
895
+ addChild(parentId, childNode, index) {
896
+ const parent = this.findNode(parentId);
897
+ if (!parent) {
898
+ return false;
899
+ }
900
+ // Ensure children array exists
901
+ let children = this.getNodeChildren(parent);
902
+ if (!children) {
903
+ children = [];
904
+ this.setNodeChildren(parent, children);
905
+ }
906
+ // Insert or append child
907
+ if (index !== undefined && index >= 0 && index <= children.length) {
908
+ children.splice(index, 0, childNode);
909
+ }
910
+ else {
911
+ children.push(childNode);
912
+ }
913
+ // Update childrenCount
914
+ this.setNodeChildrenCount(parent, children.length);
915
+ // Auto-expand parent if it was collapsed
916
+ if (!this.getNodeExpanded(parent)) {
917
+ this.setNodeExpanded(parent, true);
918
+ }
919
+ this.refreshNodes();
920
+ return true;
921
+ }
922
+ /**
923
+ * Remove a node from the tree
924
+ * @param nodeId - The ID of the node to remove
925
+ * @returns The removed node if found, null otherwise
926
+ */
927
+ removeNode(nodeId) {
928
+ const node = this.findNode(nodeId);
929
+ if (!node) {
930
+ return null;
931
+ }
932
+ // Find parent to remove from its children array
933
+ const parent = this.treeService.findParentNode(this.nodes(), node, this.idField(), this.childrenField());
934
+ const parentChildren = parent ? this.getNodeChildren(parent) : undefined;
935
+ const targetArray = parentChildren ?? this.nodes();
936
+ // Find and remove the node
937
+ const index = targetArray.findIndex((n) => this.getNodeId(n) === nodeId);
938
+ if (index !== -1) {
939
+ const removed = targetArray.splice(index, 1)[0];
940
+ // Update parent's childrenCount if it exists
941
+ if (parent) {
942
+ const updatedChildren = this.getNodeChildren(parent);
943
+ this.setNodeChildrenCount(parent, updatedChildren?.length ?? 0);
944
+ }
945
+ // Update parent states if needed
946
+ if (this.hasIntermediateState()) {
947
+ this.treeService.updateAllParentStates(this.nodes(), this.hasIntermediateState(), this.childrenField(), this.selectedField(), this.indeterminateField());
948
+ }
949
+ this.refreshNodes();
950
+ return removed;
951
+ }
952
+ return null;
953
+ }
954
+ /**
955
+ * Expand a specific node
956
+ * @param nodeId - The ID of the node to expand
957
+ * @returns Promise that resolves when expansion is complete (if lazy loading)
958
+ */
959
+ async expandNode(nodeId) {
960
+ const node = this.findNode(nodeId);
961
+ if (!node) {
962
+ return;
963
+ }
964
+ const hasChildren = this.treeService.hasChildren(node, this.childrenField());
965
+ const canLazyLoad = this.treeService.canLazyLoad(node, this.isLazyDataSource(), this.childrenCountField(), this.childrenField());
966
+ if (hasChildren || canLazyLoad) {
967
+ if (canLazyLoad) {
968
+ await this.loadNodeChildren(node);
969
+ }
970
+ this.setNodeExpanded(node, true);
971
+ this.refreshNodes();
972
+ this.onNodeToggle.emit({ component: this, node, nativeEvent: new Event('expand') });
973
+ }
974
+ }
975
+ /**
976
+ * Collapse a specific node
977
+ * @param nodeId - The ID of the node to collapse
978
+ */
979
+ collapseNode(nodeId) {
980
+ const node = this.findNode(nodeId);
981
+ if (!node) {
982
+ return;
983
+ }
984
+ if (this.getNodeExpanded(node)) {
985
+ this.setNodeExpanded(node, false);
986
+ this.refreshNodes();
987
+ this.onNodeToggle.emit({ component: this, node, nativeEvent: new Event('collapse') });
988
+ }
989
+ }
990
+ /**
991
+ * Toggle expansion state of a specific node
992
+ * @param nodeId - The ID of the node to toggle
993
+ * @returns Promise that resolves when toggle is complete (if lazy loading)
994
+ */
995
+ async toggleNodeExpansion(nodeId) {
996
+ const node = this.findNode(nodeId);
997
+ if (!node) {
998
+ return;
999
+ }
1000
+ if (this.getNodeExpanded(node)) {
1001
+ this.collapseNode(nodeId);
1002
+ }
1003
+ else {
1004
+ await this.expandNode(nodeId);
1005
+ }
1006
+ }
1007
+ /**
1008
+ * Programmatically select a node
1009
+ * @param nodeId - The ID of the node to select
1010
+ * @returns true if node was found and selected, false otherwise
1011
+ */
1012
+ selectNode(nodeId) {
1013
+ if (this.selectMode() === 'none') {
1014
+ return false;
1015
+ }
1016
+ const node = this.findNode(nodeId);
1017
+ if (!node || this.getNodeDisabled(node) || !this.canSelectNode(node)) {
1018
+ return false;
1019
+ }
1020
+ const mode = this.selectMode();
1021
+ if (mode === 'single') {
1022
+ this.treeService.deselectAllNodes(this.nodes(), this.selectedField(), this.indeterminateField(), this.childrenField());
1023
+ this.setNodeSelected(node, true);
1024
+ this.setNodeIndeterminate(node, false);
1025
+ }
1026
+ else {
1027
+ this.setNodeSelected(node, true);
1028
+ this.setNodeIndeterminate(node, false);
1029
+ const children = this.getNodeChildren(node);
1030
+ if (this.cascadesToChildren() && children && !this.isLeafOnlyMode()) {
1031
+ this.treeService.selectAllChildren(children, true, this.selectedField(), this.indeterminateField(), this.childrenField());
1032
+ }
1033
+ if (this.hasIntermediateState() && !this.isLeafOnlyMode()) {
1034
+ this.treeService.updateParentStates(this.nodes(), node, this.hasIntermediateState(), this.idField(), this.childrenField(), this.selectedField(), this.indeterminateField());
1035
+ }
1036
+ }
1037
+ this.refreshNodes();
1038
+ this.onNodeSelect.emit({
1039
+ component: this,
1040
+ node,
1041
+ isUserInteraction: false,
1042
+ });
1043
+ this.emitSelectionChange();
1044
+ return true;
1045
+ }
1046
+ /**
1047
+ * Programmatically deselect a node
1048
+ * @param nodeId - The ID of the node to deselect
1049
+ * @returns true if node was found and deselected, false otherwise
1050
+ */
1051
+ deselectNode(nodeId) {
1052
+ const node = this.findNode(nodeId);
1053
+ if (!node) {
1054
+ return false;
1055
+ }
1056
+ this.setNodeSelected(node, false);
1057
+ this.setNodeIndeterminate(node, false);
1058
+ const children = this.getNodeChildren(node);
1059
+ if (this.cascadesToChildren() && children && !this.isLeafOnlyMode()) {
1060
+ this.treeService.selectAllChildren(children, false, this.selectedField(), this.indeterminateField(), this.childrenField());
1061
+ }
1062
+ if (this.hasIntermediateState() && !this.isLeafOnlyMode()) {
1063
+ this.treeService.updateParentStates(this.nodes(), node, this.hasIntermediateState(), this.idField(), this.childrenField(), this.selectedField(), this.indeterminateField());
1064
+ }
1065
+ this.refreshNodes();
1066
+ this.onNodeSelect.emit({
1067
+ component: this,
1068
+ node,
1069
+ isUserInteraction: false,
1070
+ });
1071
+ this.emitSelectionChange();
1072
+ return true;
1073
+ }
1074
+ /**
1075
+ * Get parent node of a given node
1076
+ * @param nodeId - The ID of the node
1077
+ * @returns The parent node if found, null otherwise
1078
+ */
1079
+ getParent(nodeId) {
1080
+ const node = this.findNode(nodeId);
1081
+ if (!node) {
1082
+ return null;
1083
+ }
1084
+ return this.treeService.findParentNode(this.nodes(), node, this.idField(), this.childrenField()) ?? null;
1085
+ }
1086
+ /**
1087
+ * Get children of a node
1088
+ * @param nodeId - The ID of the parent node
1089
+ * @returns Array of child nodes, or null if node not found
1090
+ */
1091
+ getChildren(nodeId) {
1092
+ const node = this.findNode(nodeId);
1093
+ if (!node) {
1094
+ return null;
1095
+ }
1096
+ return this.getNodeChildren(node) ?? [];
1097
+ }
1098
+ /**
1099
+ * Get all root nodes
1100
+ * @returns Array of root nodes
1101
+ */
1102
+ getRootNodes() {
1103
+ return [...this.nodes()];
1104
+ }
1105
+ /**
1106
+ * Get all nodes in a flat array
1107
+ * @returns Array of all nodes in the tree
1108
+ */
1109
+ getAllNodes() {
1110
+ const allNodes = [];
1111
+ const traverse = (nodes) => {
1112
+ for (const node of nodes) {
1113
+ allNodes.push(node);
1114
+ const children = this.getNodeChildren(node);
1115
+ if (children) {
1116
+ traverse(children);
1117
+ }
1118
+ }
1119
+ };
1120
+ traverse(this.nodes());
1121
+ return allNodes;
1122
+ }
1123
+ /**
1124
+ * Get the path to a node (array of parent IDs from root to node)
1125
+ * @param nodeId - The ID of the node
1126
+ * @returns Array of node IDs representing the path, or empty array if node not found
1127
+ */
1128
+ getNodePath(nodeId) {
1129
+ const path = [];
1130
+ const node = this.findNode(nodeId);
1131
+ if (!node) {
1132
+ return path;
1133
+ }
1134
+ let current = node;
1135
+ while (current) {
1136
+ path.unshift(this.getNodeId(current));
1137
+ const parent = this.treeService.findParentNode(this.nodes(), current, this.idField(), this.childrenField());
1138
+ current = parent ?? null;
1139
+ }
1140
+ return path;
1141
+ }
1142
+ /**
1143
+ * Get the level/depth of a node (0 = root level)
1144
+ * @param nodeId - The ID of the node
1145
+ * @returns The level of the node, or -1 if node not found
1146
+ */
1147
+ getNodeLevel(nodeId) {
1148
+ const path = this.getNodePath(nodeId);
1149
+ return path.length > 0 ? path.length - 1 : -1;
1150
+ }
1151
+ /**
1152
+ * Programmatically move a node to a new parent
1153
+ * @param nodeId - The ID of the node to move
1154
+ * @param newParentId - The ID of the new parent (undefined for root level)
1155
+ * @param index - Optional index to insert at (default: append to end)
1156
+ * @returns true if move was successful, false otherwise
1157
+ */
1158
+ moveNode(nodeId, newParentId, index) {
1159
+ const node = this.findNode(nodeId);
1160
+ if (!node) {
1161
+ return false;
1162
+ }
1163
+ // Find current parent
1164
+ const currentParent = this.treeService.findParentNode(this.nodes(), node, this.idField(), this.childrenField());
1165
+ const currentParentChildren = currentParent ? this.getNodeChildren(currentParent) : undefined;
1166
+ const currentArray = currentParentChildren ?? this.nodes();
1167
+ // Find and remove from current location
1168
+ const currentIndex = currentArray.findIndex((n) => this.getNodeId(n) === nodeId);
1169
+ if (currentIndex === -1) {
1170
+ return false;
1171
+ }
1172
+ const movedNode = currentArray.splice(currentIndex, 1)[0];
1173
+ // Find new parent
1174
+ let targetArray;
1175
+ let newParent;
1176
+ if (newParentId) {
1177
+ newParent = this.findNode(newParentId);
1178
+ if (!newParent) {
1179
+ // Restore node if new parent not found
1180
+ currentArray.splice(currentIndex, 0, movedNode);
1181
+ return false;
1182
+ }
1183
+ // Validate drop target
1184
+ if (!this.treeService.isValidDropTarget(movedNode, newParent, this.idField(), this.childrenField())) {
1185
+ // Restore node if invalid drop target
1186
+ currentArray.splice(currentIndex, 0, movedNode);
1187
+ return false;
1188
+ }
1189
+ let newParentChildren = this.getNodeChildren(newParent);
1190
+ if (!newParentChildren) {
1191
+ newParentChildren = [];
1192
+ this.setNodeChildren(newParent, newParentChildren);
1193
+ }
1194
+ targetArray = newParentChildren;
1195
+ }
1196
+ else {
1197
+ targetArray = this.nodes();
1198
+ }
1199
+ // Calculate new index before inserting
1200
+ const newIndex = index !== undefined && index >= 0 && index <= targetArray.length ? index : targetArray.length;
1201
+ // Insert at new location
1202
+ if (index !== undefined && index >= 0 && index <= targetArray.length) {
1203
+ targetArray.splice(index, 0, movedNode);
1204
+ }
1205
+ else {
1206
+ targetArray.push(movedNode);
1207
+ }
1208
+ // Update childrenCount
1209
+ if (currentParent) {
1210
+ const updatedChildren = this.getNodeChildren(currentParent);
1211
+ this.setNodeChildrenCount(currentParent, updatedChildren?.length ?? 0);
1212
+ }
1213
+ if (newParent) {
1214
+ const updatedChildren = this.getNodeChildren(newParent);
1215
+ this.setNodeChildrenCount(newParent, updatedChildren?.length ?? 0);
1216
+ this.setNodeExpanded(newParent, true); // Auto-expand new parent
1217
+ }
1218
+ // Emit drop events
1219
+ this.emitDropEvents(movedNode, currentParent, newParent, currentIndex, newIndex, false);
1220
+ this.refreshNodes();
1221
+ return true;
1222
+ }
1223
+ /**
1224
+ * Clone a node (creates a deep copy)
1225
+ * @param nodeId - The ID of the node to clone
1226
+ * @returns The cloned node, or null if node not found
1227
+ */
1228
+ cloneNode(nodeId) {
1229
+ const node = this.findNode(nodeId);
1230
+ if (!node) {
1231
+ return null;
1232
+ }
1233
+ return this.treeService.cloneNode(node, this.idField(), this.titleField(), this.tooltipField(), this.iconField(), this.expandedField(), this.selectedField(), this.indeterminateField(), this.disabledField(), this.hiddenField(), this.childrenCountField(), this.dataField(), this.childrenField());
1234
+ }
1235
+ /**
1236
+ * Focus a specific node by ID
1237
+ * @param nodeId - The ID of the node to focus
1238
+ * @returns true if node was found and focused, false otherwise
1239
+ */
1240
+ focusNode(nodeId) {
1241
+ const node = this.findNode(nodeId);
1242
+ if (!node || this.getNodeHidden(node) === true || this.getNodeDisabled(node)) {
1243
+ return false;
1244
+ }
1245
+ this.focusNodeById(nodeId);
1246
+ return true;
1247
+ }
1248
+ /**
1249
+ * Get all expanded nodes
1250
+ * @returns Array of expanded nodes
1251
+ */
1252
+ getExpandedNodes() {
1253
+ const expanded = [];
1254
+ const traverse = (nodes) => {
1255
+ for (const node of nodes) {
1256
+ if (this.getNodeExpanded(node)) {
1257
+ expanded.push(node);
1258
+ }
1259
+ const children = this.getNodeChildren(node);
1260
+ if (children) {
1261
+ traverse(children);
1262
+ }
1263
+ }
1264
+ };
1265
+ traverse(this.nodes());
1266
+ return expanded;
1267
+ }
1268
+ /**
1269
+ * Get all collapsed nodes that have children
1270
+ * @returns Array of collapsed nodes with children
1271
+ */
1272
+ getCollapsedNodes() {
1273
+ const collapsed = [];
1274
+ const traverse = (nodes) => {
1275
+ for (const node of nodes) {
1276
+ const children = this.getNodeChildren(node);
1277
+ const childrenCount = this.getNodeChildrenCount(node);
1278
+ if (!this.getNodeExpanded(node) && (children?.length || childrenCount)) {
1279
+ collapsed.push(node);
1280
+ }
1281
+ if (children) {
1282
+ traverse(children);
1283
+ }
1284
+ }
1285
+ };
1286
+ traverse(this.nodes());
1287
+ return collapsed;
1288
+ }
1289
+ /**
1290
+ * Check if a node is expanded
1291
+ * @param nodeId - The ID of the node
1292
+ * @returns true if node is expanded, false otherwise
1293
+ */
1294
+ isNodeExpanded(nodeId) {
1295
+ const node = this.findNode(nodeId);
1296
+ return node ? this.getNodeExpanded(node) : false;
1297
+ }
1298
+ /**
1299
+ * Check if a node is selected
1300
+ * @param nodeId - The ID of the node
1301
+ * @returns true if node is selected, false otherwise
1302
+ */
1303
+ isNodeSelected(nodeId) {
1304
+ const node = this.findNode(nodeId);
1305
+ return node ? this.getNodeSelected(node) : false;
1306
+ }
1307
+ /**
1308
+ * Check if a node has children
1309
+ * @param nodeId - The ID of the node
1310
+ * @returns true if node has children, false otherwise
1311
+ */
1312
+ hasChildren(nodeId) {
1313
+ const node = this.findNode(nodeId);
1314
+ return this.treeService.hasChildren(node ?? {}, this.childrenField());
1315
+ }
531
1316
  /**
532
1317
  * Get template context for a node
533
1318
  */
534
1319
  getTemplateContext(node, level = 0) {
1320
+ const children = this.getNodeChildren(node);
1321
+ const childrenCount = this.getNodeChildrenCount(node);
535
1322
  return {
536
1323
  $implicit: node,
537
1324
  node,
538
1325
  level,
539
- expanded: node.expanded ?? false,
540
- childrenCount: node.childrenCount ?? node.children?.length ?? 0,
541
- loading: node.loading ?? false,
1326
+ expanded: this.getNodeExpanded(node),
1327
+ childrenCount: childrenCount ?? children?.length ?? 0,
1328
+ loading: this.getNodeLoading(node),
542
1329
  };
543
1330
  }
544
1331
  /**
@@ -554,7 +1341,8 @@ class AXTreeViewComponent {
554
1341
  * Check if node should show expand toggle
555
1342
  */
556
1343
  shouldShowExpandToggle(node) {
557
- return this.treeService.hasChildren(node) || this.treeService.canLazyLoad(node, this.isLazyDataSource());
1344
+ return (this.treeService.hasChildren(node, this.childrenField()) ||
1345
+ this.treeService.canLazyLoad(node, this.isLazyDataSource(), this.childrenCountField(), this.childrenField()));
558
1346
  }
559
1347
  /**
560
1348
  * Check if checkboxes should be shown (only for multiple mode)
@@ -562,11 +1350,50 @@ class AXTreeViewComponent {
562
1350
  shouldShowCheckbox() {
563
1351
  return this.selectMode() === 'multiple' && this.showCheckbox();
564
1352
  }
1353
+ /**
1354
+ * Check if a node is a leaf (has no children)
1355
+ * A node is a leaf if it has no loaded children AND no childrenCount (or childrenCount is 0)
1356
+ */
1357
+ isLeafNode(node) {
1358
+ const hasChildren = this.treeService.hasChildren(node, this.childrenField());
1359
+ const childrenCount = this.getNodeChildrenCount(node);
1360
+ const hasChildrenCount = childrenCount && childrenCount > 0;
1361
+ const canLazyLoad = this.treeService.canLazyLoad(node, this.isLazyDataSource(), this.childrenCountField(), this.childrenField());
1362
+ // A node is a leaf if:
1363
+ // 1. It has no loaded children
1364
+ // 2. AND it has no childrenCount (or childrenCount is 0)
1365
+ // 3. AND it cannot be lazy loaded
1366
+ return !hasChildren && !hasChildrenCount && !canLazyLoad;
1367
+ }
1368
+ /**
1369
+ * Check if a node can be selected (considering selectMode and isLeafOnlyMode)
1370
+ */
1371
+ canSelectNode(node) {
1372
+ if (this.selectMode() === 'none') {
1373
+ return false;
1374
+ }
1375
+ if (this.isLeafOnlyMode()) {
1376
+ return this.isLeafNode(node);
1377
+ }
1378
+ return true;
1379
+ }
1380
+ /**
1381
+ * Check if checkbox should be shown for a specific node
1382
+ */
1383
+ shouldShowCheckboxForNode(node) {
1384
+ if (!this.shouldShowCheckbox()) {
1385
+ return false;
1386
+ }
1387
+ if (this.isLeafOnlyMode()) {
1388
+ return this.isLeafNode(node);
1389
+ }
1390
+ return true;
1391
+ }
565
1392
  /**
566
1393
  * Generate unique list ID for each node
567
1394
  */
568
1395
  getListId(node) {
569
- return this.treeService.getListId(node);
1396
+ return this.treeService.getListId(node, this.idField());
570
1397
  }
571
1398
  /**
572
1399
  * Check if a node is currently focused
@@ -587,23 +1414,44 @@ class AXTreeViewComponent {
587
1414
  if (!this.shouldShowExpandToggle(node)) {
588
1415
  return null;
589
1416
  }
590
- return node.expanded ? 'true' : 'false';
1417
+ return this.getNodeExpanded(node) ? 'true' : 'false';
591
1418
  }
592
1419
  /**
593
1420
  * Get ARIA selected state for a node
594
1421
  */
595
1422
  getNodeAriaSelected(node) {
1423
+ if (this.selectMode() === 'none') {
1424
+ return null;
1425
+ }
1426
+ const selected = this.getNodeSelected(node);
596
1427
  if (this.selectMode() === 'single') {
597
- return node.selected ? 'true' : 'false';
1428
+ return selected ? 'true' : 'false';
1429
+ }
1430
+ if (this.selectMode() === 'multiple') {
1431
+ return selected ? 'true' : 'false';
598
1432
  }
599
1433
  return null;
600
1434
  }
1435
+ /**
1436
+ * Emit selection change event with all selected nodes
1437
+ */
1438
+ emitSelectionChange() {
1439
+ const selectedNodes = this.getSelectedNodes();
1440
+ this.onSelectionChange.emit({
1441
+ component: this,
1442
+ selectedNodes,
1443
+ });
1444
+ }
601
1445
  // ==================== Event Handlers ====================
602
1446
  /**
603
1447
  * Handle node click - for single selection mode or multiple mode with checkOnClick enabled
604
1448
  */
605
1449
  onNodeClick(node, event) {
606
- if (node.disabled)
1450
+ if (this.getNodeDisabled(node))
1451
+ return;
1452
+ if (this.selectMode() === 'none')
1453
+ return;
1454
+ if (!this.canSelectNode(node))
607
1455
  return;
608
1456
  const mode = this.selectMode();
609
1457
  const shouldCheckOnClick = this.checkOnClick();
@@ -618,19 +1466,19 @@ class AXTreeViewComponent {
618
1466
  * Toggle node expansion state with lazy loading support
619
1467
  */
620
1468
  async toggleNode(node, event) {
621
- if (node.disabled)
1469
+ if (this.getNodeDisabled(node))
622
1470
  return;
623
1471
  if (this.isEvent(event) && typeof event.stopPropagation === 'function') {
624
1472
  event.stopPropagation();
625
1473
  }
626
- const hasChildren = this.treeService.hasChildren(node);
627
- const canLazyLoad = this.treeService.canLazyLoad(node, this.isLazyDataSource());
1474
+ const hasChildren = this.treeService.hasChildren(node, this.childrenField());
1475
+ const canLazyLoad = this.treeService.canLazyLoad(node, this.isLazyDataSource(), this.childrenCountField(), this.childrenField());
628
1476
  if (hasChildren || canLazyLoad) {
629
- const willExpand = !node.expanded;
1477
+ const willExpand = !this.getNodeExpanded(node);
630
1478
  if (willExpand && canLazyLoad) {
631
1479
  await this.loadNodeChildren(node);
632
1480
  }
633
- node.expanded = willExpand;
1481
+ this.setNodeExpanded(node, willExpand);
634
1482
  this.refreshNodes();
635
1483
  this.onNodeToggle.emit({ component: this, node, nativeEvent: event });
636
1484
  }
@@ -641,17 +1489,22 @@ class AXTreeViewComponent {
641
1489
  toggleSelection(node, event) {
642
1490
  if (!event.isUserInteraction)
643
1491
  return;
1492
+ if (this.selectMode() === 'none')
1493
+ return;
1494
+ if (!this.canSelectNode(node))
1495
+ return;
644
1496
  const mode = this.selectMode();
645
1497
  if (mode !== 'multiple')
646
1498
  return;
647
1499
  const newValue = event.value === null ? true : event.value;
648
- node.selected = newValue;
649
- node.indeterminate = false;
650
- if (this.checkChildrenOnSelect() && node.children) {
651
- this.treeService.selectAllChildren(node.children, newValue);
1500
+ this.setNodeSelected(node, newValue);
1501
+ this.setNodeIndeterminate(node, false);
1502
+ const children = this.getNodeChildren(node);
1503
+ if (this.cascadesToChildren() && children && !this.isLeafOnlyMode()) {
1504
+ this.treeService.selectAllChildren(children, newValue, this.selectedField(), this.indeterminateField(), this.childrenField());
652
1505
  }
653
- if (this.intermediateState()) {
654
- this.treeService.updateParentStates(this.nodes(), node, this.intermediateState());
1506
+ if (this.hasIntermediateState() && !this.isLeafOnlyMode()) {
1507
+ this.treeService.updateParentStates(this.nodes(), node, this.hasIntermediateState(), this.idField(), this.childrenField(), this.selectedField(), this.indeterminateField());
655
1508
  }
656
1509
  this.refreshNodes();
657
1510
  this.onNodeSelect.emit({
@@ -659,12 +1512,13 @@ class AXTreeViewComponent {
659
1512
  node,
660
1513
  isUserInteraction: event.isUserInteraction,
661
1514
  });
1515
+ this.emitSelectionChange();
662
1516
  }
663
1517
  /**
664
1518
  * Handle drop events for tree nodes
665
1519
  */
666
1520
  onDrop(event, parentNode) {
667
- const targetArray = parentNode?.children ?? this.nodes();
1521
+ const targetArray = parentNode ? (this.getNodeChildren(parentNode) ?? []) : this.nodes();
668
1522
  const isReordering = event.previousContainer === event.container;
669
1523
  if (isReordering) {
670
1524
  this.handleReorder(event, targetArray, parentNode);
@@ -685,14 +1539,18 @@ class AXTreeViewComponent {
685
1539
  if (!sourceArray)
686
1540
  return;
687
1541
  const movedNode = sourceArray[event.previousIndex];
688
- if (!this.treeService.isValidDropTarget(movedNode, targetNode))
1542
+ if (!this.treeService.isValidDropTarget(movedNode, targetNode, this.idField(), this.childrenField()))
689
1543
  return;
690
1544
  if (!this.emitBeforeDropEvent(movedNode, sourceListId, targetNode, event.previousIndex, 0))
691
1545
  return;
692
- targetNode.children ??= [];
1546
+ let targetChildren = this.getNodeChildren(targetNode);
1547
+ if (!targetChildren) {
1548
+ targetChildren = [];
1549
+ this.setNodeChildren(targetNode, targetChildren);
1550
+ }
693
1551
  sourceArray.splice(event.previousIndex, 1);
694
- targetNode.children.unshift(movedNode);
695
- targetNode.expanded = true;
1552
+ targetChildren.unshift(movedNode);
1553
+ this.setNodeExpanded(targetNode, true);
696
1554
  this.emitDropEvents(movedNode, this.findParentByListId(sourceListId), targetNode, event.previousIndex, 0, false);
697
1555
  this.refreshNodes();
698
1556
  }
@@ -707,18 +1565,25 @@ class AXTreeViewComponent {
707
1565
  */
708
1566
  onTreeFocus(event) {
709
1567
  if (event.target === event.currentTarget) {
710
- afterNextRender(() => {
711
- const flatList = this.treeService.buildFlatNodeList(this.nodes());
712
- if (flatList.length > 0) {
713
- const focusedId = this.focusedNodeId();
714
- if (focusedId) {
1568
+ const flatList = this.treeService.buildFlatNodeList(this.nodes(), this.hiddenField(), this.disabledField(), this.expandedField(), this.childrenField());
1569
+ if (flatList.length > 0) {
1570
+ const focusedId = this.focusedNodeId();
1571
+ if (focusedId) {
1572
+ // Check if the focused node still exists and is not hidden
1573
+ const focusedNode = this.treeService.findNodeById(this.nodes(), focusedId, this.idField());
1574
+ if (focusedNode && this.getNodeHidden(focusedNode) !== true) {
715
1575
  this.focusNodeById(focusedId);
716
1576
  }
717
1577
  else {
718
- this.focusNodeById(flatList[0].node.id);
1578
+ // Focused node no longer exists, focus first node
1579
+ this.focusNodeById(this.getNodeId(flatList[0].node));
719
1580
  }
720
1581
  }
721
- });
1582
+ else {
1583
+ // No node is focused, focus first node
1584
+ this.focusNodeById(this.getNodeId(flatList[0].node));
1585
+ }
1586
+ }
722
1587
  }
723
1588
  }
724
1589
  /**
@@ -733,11 +1598,13 @@ class AXTreeViewComponent {
733
1598
  * Handle keyboard navigation
734
1599
  */
735
1600
  handleKeyDown(event) {
736
- const flatList = this.treeService.buildFlatNodeList(this.nodes());
1601
+ const flatList = this.treeService.buildFlatNodeList(this.nodes(), this.hiddenField(), this.disabledField(), this.expandedField(), this.childrenField());
737
1602
  if (flatList.length === 0)
738
1603
  return;
739
1604
  const currentFocused = this.getFocusedNode();
740
- let currentIndex = currentFocused ? flatList.findIndex((item) => item.node.id === currentFocused.id) : -1;
1605
+ let currentIndex = currentFocused
1606
+ ? flatList.findIndex((item) => this.getNodeId(item.node) === this.getNodeId(currentFocused))
1607
+ : -1;
741
1608
  if (currentIndex === -1 && event.target === event.currentTarget) {
742
1609
  currentIndex = 0;
743
1610
  }
@@ -750,7 +1617,7 @@ class AXTreeViewComponent {
750
1617
  if (navigationResult.targetIndex !== null &&
751
1618
  navigationResult.targetIndex >= 0 &&
752
1619
  navigationResult.targetIndex < flatList.length) {
753
- this.focusNodeById(flatList[navigationResult.targetIndex].node.id);
1620
+ this.focusNodeById(this.getNodeId(flatList[navigationResult.targetIndex].node));
754
1621
  }
755
1622
  }
756
1623
  }
@@ -773,32 +1640,34 @@ class AXTreeViewComponent {
773
1640
  * Load children for a node using lazy loading
774
1641
  */
775
1642
  async loadNodeChildren(node) {
776
- if (!this.isLazyDataSource() || node.loading)
777
- return;
778
- if (this.treeService.hasChildren(node) || !node.childrenCount || node.childrenCount === 0) {
1643
+ const nodeId = this.getNodeId(node);
1644
+ if (!this.isLazyDataSource() || this.loadingNodes().has(nodeId))
779
1645
  return;
1646
+ if (this.treeService.hasChildren(node, this.childrenField())) {
1647
+ const childrenCount = this.getNodeChildrenCount(node);
1648
+ if (!childrenCount || childrenCount === 0) {
1649
+ return;
1650
+ }
780
1651
  }
781
1652
  const ds = this.datasource();
782
1653
  if (typeof ds !== 'function')
783
1654
  return;
784
1655
  try {
785
- node.loading = true;
786
- this.loadingNodes.update((set) => new Set(set).add(node.id));
1656
+ this.loadingNodes.update((set) => new Set(set).add(nodeId));
787
1657
  this.refreshNodes();
788
- const result = ds(node.id);
1658
+ const result = ds(nodeId);
789
1659
  const children = result instanceof Promise ? await result : result;
790
- node.children = children;
791
- node.childrenCount = children.length;
1660
+ this.setNodeChildren(node, children);
1661
+ this.setNodeChildrenCount(node, children.length);
792
1662
  }
793
1663
  catch (error) {
794
1664
  this.handleError('Failed to load children', error);
795
- node.childrenCount = 0;
1665
+ this.setNodeChildrenCount(node, 0);
796
1666
  }
797
1667
  finally {
798
- node.loading = false;
799
1668
  this.loadingNodes.update((set) => {
800
1669
  const newSet = new Set(set);
801
- newSet.delete(node.id);
1670
+ newSet.delete(nodeId);
802
1671
  return newSet;
803
1672
  });
804
1673
  this.refreshNodes();
@@ -828,11 +1697,12 @@ class AXTreeViewComponent {
828
1697
  */
829
1698
  ensureNewArrayReferences(nodes) {
830
1699
  for (const node of nodes) {
831
- if (node.children && node.children.length > 0) {
1700
+ const children = this.getNodeChildren(node);
1701
+ if (children && children.length > 0) {
832
1702
  // Create new array reference for children
833
- node.children = [...node.children];
1703
+ this.setNodeChildren(node, [...children]);
834
1704
  // Recursively process nested children
835
- this.ensureNewArrayReferences(node.children);
1705
+ this.ensureNewArrayReferences(children);
836
1706
  }
837
1707
  }
838
1708
  }
@@ -840,9 +1710,9 @@ class AXTreeViewComponent {
840
1710
  * Handle single selection mode
841
1711
  */
842
1712
  handleSingleSelection(node, event) {
843
- this.treeService.deselectAllNodes(this.nodes());
844
- node.selected = true;
845
- node.indeterminate = false;
1713
+ this.treeService.deselectAllNodes(this.nodes(), this.selectedField(), this.indeterminateField(), this.childrenField());
1714
+ this.setNodeSelected(node, true);
1715
+ this.setNodeIndeterminate(node, false);
846
1716
  this.refreshNodes();
847
1717
  this.onNodeSelect.emit({
848
1718
  component: this,
@@ -850,19 +1720,21 @@ class AXTreeViewComponent {
850
1720
  nativeEvent: event,
851
1721
  isUserInteraction: true,
852
1722
  });
1723
+ this.emitSelectionChange();
853
1724
  }
854
1725
  /**
855
1726
  * Handle multiple selection mode with checkOnClick
856
1727
  */
857
1728
  handleMultipleSelection(node, event) {
858
- const newValue = !node.selected;
859
- node.selected = newValue;
860
- node.indeterminate = false;
861
- if (this.checkChildrenOnSelect() && node.children) {
862
- this.treeService.selectAllChildren(node.children, newValue);
1729
+ const newValue = !this.getNodeSelected(node);
1730
+ this.setNodeSelected(node, newValue);
1731
+ this.setNodeIndeterminate(node, false);
1732
+ const children = this.getNodeChildren(node);
1733
+ if (this.cascadesToChildren() && children && !this.isLeafOnlyMode()) {
1734
+ this.treeService.selectAllChildren(children, newValue, this.selectedField(), this.indeterminateField(), this.childrenField());
863
1735
  }
864
- if (this.intermediateState()) {
865
- this.treeService.updateParentStates(this.nodes(), node, this.intermediateState());
1736
+ if (this.hasIntermediateState() && !this.isLeafOnlyMode()) {
1737
+ this.treeService.updateParentStates(this.nodes(), node, this.hasIntermediateState(), this.idField(), this.childrenField(), this.selectedField(), this.indeterminateField());
866
1738
  }
867
1739
  this.refreshNodes();
868
1740
  this.onNodeSelect.emit({
@@ -871,18 +1743,19 @@ class AXTreeViewComponent {
871
1743
  nativeEvent: event,
872
1744
  isUserInteraction: true,
873
1745
  });
1746
+ this.emitSelectionChange();
874
1747
  }
875
1748
  /**
876
1749
  * Get array reference by drop list ID
877
1750
  */
878
1751
  getArrayByListId(listId) {
879
- return this.treeService.getArrayByListId(this.nodes(), listId);
1752
+ return this.treeService.getArrayByListId(this.nodes(), listId, this.idField(), this.childrenField());
880
1753
  }
881
1754
  /**
882
1755
  * Find parent node by list ID
883
1756
  */
884
1757
  findParentByListId(listId) {
885
- return this.treeService.findParentByListId(this.nodes(), listId);
1758
+ return this.treeService.findParentByListId(this.nodes(), listId, this.idField());
886
1759
  }
887
1760
  /**
888
1761
  * Check if move operation is allowed based on dragOperationType
@@ -967,7 +1840,7 @@ class AXTreeViewComponent {
967
1840
  const focusedId = this.focusedNodeId();
968
1841
  if (!focusedId)
969
1842
  return null;
970
- return this.treeService.findNodeById(this.nodes(), focusedId);
1843
+ return this.treeService.findNodeById(this.nodes(), focusedId, this.idField());
971
1844
  }
972
1845
  /**
973
1846
  * Set focus to a node by ID
@@ -1011,14 +1884,14 @@ class AXTreeViewComponent {
1011
1884
  break;
1012
1885
  case 'ArrowLeft':
1013
1886
  if (currentFocused) {
1014
- if (currentFocused.expanded && this.shouldShowExpandToggle(currentFocused)) {
1887
+ if (this.getNodeExpanded(currentFocused) && this.shouldShowExpandToggle(currentFocused)) {
1015
1888
  this.toggleNode(currentFocused, event);
1016
1889
  return { handled: true, shouldPreventDefault: true, targetIndex: null };
1017
1890
  }
1018
1891
  else {
1019
1892
  const currentItem = flatList[currentIndex];
1020
1893
  if (currentItem?.parent) {
1021
- targetIndex = flatList.findIndex((item) => item.node.id === currentItem.parent.id);
1894
+ targetIndex = flatList.findIndex((item) => this.getNodeId(item.node) === this.getNodeId(currentItem.parent));
1022
1895
  }
1023
1896
  else {
1024
1897
  shouldPreventDefault = false;
@@ -1031,22 +1904,21 @@ class AXTreeViewComponent {
1031
1904
  break;
1032
1905
  case 'ArrowRight':
1033
1906
  if (currentFocused) {
1034
- if (!currentFocused.expanded && this.shouldShowExpandToggle(currentFocused)) {
1907
+ if (!this.getNodeExpanded(currentFocused) && this.shouldShowExpandToggle(currentFocused)) {
1035
1908
  this.toggleNode(currentFocused, event);
1036
1909
  return { handled: true, shouldPreventDefault: true, targetIndex: null };
1037
1910
  }
1038
- else if (currentFocused.expanded &&
1039
- this.treeService.hasChildren(currentFocused) &&
1040
- currentFocused.children) {
1041
- const children = currentFocused.children;
1042
- if (children.length > 0) {
1911
+ else if (this.getNodeExpanded(currentFocused) &&
1912
+ this.treeService.hasChildren(currentFocused, this.childrenField())) {
1913
+ const children = this.getNodeChildren(currentFocused);
1914
+ if (children && children.length > 0) {
1043
1915
  const firstChild = children[0];
1044
- targetIndex = flatList.findIndex((item) => item.node.id === firstChild.id);
1916
+ targetIndex = flatList.findIndex((item) => this.getNodeId(item.node) === this.getNodeId(firstChild));
1045
1917
  if (targetIndex === -1) {
1046
- const updatedFlatList = this.treeService.buildFlatNodeList(this.nodes());
1047
- targetIndex = updatedFlatList.findIndex((item) => item.node.id === firstChild.id);
1918
+ const updatedFlatList = this.treeService.buildFlatNodeList(this.nodes(), this.hiddenField(), this.disabledField(), this.expandedField(), this.childrenField());
1919
+ targetIndex = updatedFlatList.findIndex((item) => this.getNodeId(item.node) === this.getNodeId(firstChild));
1048
1920
  if (targetIndex >= 0 && targetIndex < updatedFlatList.length) {
1049
- this.focusNodeById(updatedFlatList[targetIndex].node.id);
1921
+ this.focusNodeById(this.getNodeId(updatedFlatList[targetIndex].node));
1050
1922
  return { handled: true, shouldPreventDefault: true, targetIndex: null };
1051
1923
  }
1052
1924
  }
@@ -1071,7 +1943,7 @@ class AXTreeViewComponent {
1071
1943
  break;
1072
1944
  case ' ':
1073
1945
  case 'Space':
1074
- if (currentFocused && this.selectMode() === 'multiple') {
1946
+ if (currentFocused && this.selectMode() === 'multiple' && this.canSelectNode(currentFocused)) {
1075
1947
  event.preventDefault();
1076
1948
  this.handleSpaceKeySelection(currentFocused, event);
1077
1949
  return { handled: true, shouldPreventDefault: true, targetIndex: null };
@@ -1079,7 +1951,7 @@ class AXTreeViewComponent {
1079
1951
  shouldPreventDefault = false;
1080
1952
  break;
1081
1953
  case 'Enter':
1082
- if (currentFocused) {
1954
+ if (currentFocused && this.canSelectNode(currentFocused)) {
1083
1955
  event.preventDefault();
1084
1956
  this.handleEnterKeySelection(currentFocused, event);
1085
1957
  return { handled: true, shouldPreventDefault: true, targetIndex: null };
@@ -1088,7 +1960,7 @@ class AXTreeViewComponent {
1088
1960
  break;
1089
1961
  default:
1090
1962
  if ((event.ctrlKey || event.metaKey) && event.key === 'Enter') {
1091
- if (currentFocused && this.selectMode() === 'multiple') {
1963
+ if (currentFocused && this.selectMode() === 'multiple' && this.canSelectNode(currentFocused)) {
1092
1964
  event.preventDefault();
1093
1965
  this.handleCtrlEnterSelection(currentFocused, event);
1094
1966
  return { handled: true, shouldPreventDefault: true, targetIndex: null };
@@ -1104,14 +1976,17 @@ class AXTreeViewComponent {
1104
1976
  * Handle Space key selection
1105
1977
  */
1106
1978
  handleSpaceKeySelection(node, event) {
1107
- const newValue = !node.selected;
1108
- node.selected = newValue;
1109
- node.indeterminate = false;
1110
- if (this.checkChildrenOnSelect() && node.children) {
1111
- this.treeService.selectAllChildren(node.children, newValue);
1979
+ if (!this.canSelectNode(node))
1980
+ return;
1981
+ const newValue = !this.getNodeSelected(node);
1982
+ this.setNodeSelected(node, newValue);
1983
+ this.setNodeIndeterminate(node, false);
1984
+ const children = this.getNodeChildren(node);
1985
+ if (this.cascadesToChildren() && children && !this.isLeafOnlyMode()) {
1986
+ this.treeService.selectAllChildren(children, newValue, this.selectedField(), this.indeterminateField(), this.childrenField());
1112
1987
  }
1113
- if (this.intermediateState()) {
1114
- this.treeService.updateParentStates(this.nodes(), node, this.intermediateState());
1988
+ if (this.hasIntermediateState() && !this.isLeafOnlyMode()) {
1989
+ this.treeService.updateParentStates(this.nodes(), node, this.hasIntermediateState(), this.idField(), this.childrenField(), this.selectedField(), this.indeterminateField());
1115
1990
  }
1116
1991
  this.refreshNodes();
1117
1992
  this.onNodeSelect.emit({
@@ -1120,21 +1995,25 @@ class AXTreeViewComponent {
1120
1995
  nativeEvent: event,
1121
1996
  isUserInteraction: true,
1122
1997
  });
1998
+ this.emitSelectionChange();
1123
1999
  }
1124
2000
  /**
1125
2001
  * Handle Enter key selection
1126
2002
  */
1127
2003
  handleEnterKeySelection(node, event) {
2004
+ if (!this.canSelectNode(node))
2005
+ return;
1128
2006
  const mode = this.selectMode();
1129
- this.treeService.deselectAllNodes(this.nodes());
1130
- node.selected = true;
1131
- node.indeterminate = false;
2007
+ this.treeService.deselectAllNodes(this.nodes(), this.selectedField(), this.indeterminateField(), this.childrenField());
2008
+ this.setNodeSelected(node, true);
2009
+ this.setNodeIndeterminate(node, false);
1132
2010
  if (mode === 'multiple') {
1133
- if (this.checkChildrenOnSelect() && node.children) {
1134
- this.treeService.selectAllChildren(node.children, true);
2011
+ const children = this.getNodeChildren(node);
2012
+ if (this.cascadesToChildren() && children && !this.isLeafOnlyMode()) {
2013
+ this.treeService.selectAllChildren(children, true, this.selectedField(), this.indeterminateField(), this.childrenField());
1135
2014
  }
1136
- if (this.intermediateState()) {
1137
- this.treeService.updateParentStates(this.nodes(), node, this.intermediateState());
2015
+ if (this.hasIntermediateState() && !this.isLeafOnlyMode()) {
2016
+ this.treeService.updateParentStates(this.nodes(), node, this.hasIntermediateState(), this.idField(), this.childrenField(), this.selectedField(), this.indeterminateField());
1138
2017
  }
1139
2018
  }
1140
2019
  this.refreshNodes();
@@ -1144,19 +2023,23 @@ class AXTreeViewComponent {
1144
2023
  nativeEvent: event,
1145
2024
  isUserInteraction: true,
1146
2025
  });
2026
+ this.emitSelectionChange();
1147
2027
  }
1148
2028
  /**
1149
2029
  * Handle Ctrl/Cmd + Enter key selection
1150
2030
  */
1151
2031
  handleCtrlEnterSelection(node, event) {
1152
- const newValue = !node.selected;
1153
- node.selected = newValue;
1154
- node.indeterminate = false;
1155
- if (this.checkChildrenOnSelect() && node.children) {
1156
- this.treeService.selectAllChildren(node.children, newValue);
2032
+ if (!this.canSelectNode(node))
2033
+ return;
2034
+ const newValue = !this.getNodeSelected(node);
2035
+ this.setNodeSelected(node, newValue);
2036
+ this.setNodeIndeterminate(node, false);
2037
+ const children = this.getNodeChildren(node);
2038
+ if (this.cascadesToChildren() && children && !this.isLeafOnlyMode()) {
2039
+ this.treeService.selectAllChildren(children, newValue, this.selectedField(), this.indeterminateField(), this.childrenField());
1157
2040
  }
1158
- if (this.intermediateState()) {
1159
- this.treeService.updateParentStates(this.nodes(), node, this.intermediateState());
2041
+ if (this.hasIntermediateState() && !this.isLeafOnlyMode()) {
2042
+ this.treeService.updateParentStates(this.nodes(), node, this.hasIntermediateState(), this.idField(), this.childrenField(), this.selectedField(), this.indeterminateField());
1160
2043
  }
1161
2044
  this.refreshNodes();
1162
2045
  this.onNodeSelect.emit({
@@ -1165,6 +2048,7 @@ class AXTreeViewComponent {
1165
2048
  nativeEvent: event,
1166
2049
  isUserInteraction: true,
1167
2050
  });
2051
+ this.emitSelectionChange();
1168
2052
  }
1169
2053
  /**
1170
2054
  * Type guard to check if value is an Event
@@ -1184,7 +2068,7 @@ class AXTreeViewComponent {
1184
2068
  }
1185
2069
  }
1186
2070
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: AXTreeViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1187
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.9", type: AXTreeViewComponent, isStandalone: true, selector: "ax-tree-view", inputs: { datasource: { classPropertyName: "datasource", publicName: "datasource", isSignal: true, isRequired: true, transformFunction: null }, selectMode: { classPropertyName: "selectMode", publicName: "selectMode", isSignal: true, isRequired: false, transformFunction: null }, showCheckbox: { classPropertyName: "showCheckbox", publicName: "showCheckbox", isSignal: true, isRequired: false, transformFunction: null }, checkChildrenOnSelect: { classPropertyName: "checkChildrenOnSelect", publicName: "checkChildrenOnSelect", isSignal: true, isRequired: false, transformFunction: null }, intermediateState: { classPropertyName: "intermediateState", publicName: "intermediateState", isSignal: true, isRequired: false, transformFunction: null }, checkOnClick: { classPropertyName: "checkOnClick", publicName: "checkOnClick", isSignal: true, isRequired: false, transformFunction: null }, dragMode: { classPropertyName: "dragMode", publicName: "dragMode", isSignal: true, isRequired: false, transformFunction: null }, dragOperationType: { classPropertyName: "dragOperationType", publicName: "dragOperationType", isSignal: true, isRequired: false, transformFunction: null }, showIcons: { classPropertyName: "showIcons", publicName: "showIcons", isSignal: true, isRequired: false, transformFunction: null }, showChildrenBadge: { classPropertyName: "showChildrenBadge", publicName: "showChildrenBadge", isSignal: true, isRequired: false, transformFunction: null }, expandedIcon: { classPropertyName: "expandedIcon", publicName: "expandedIcon", isSignal: true, isRequired: false, transformFunction: null }, collapsedIcon: { classPropertyName: "collapsedIcon", publicName: "collapsedIcon", isSignal: true, isRequired: false, transformFunction: null }, indentSize: { classPropertyName: "indentSize", publicName: "indentSize", isSignal: true, isRequired: false, transformFunction: null }, nodeHeight: { classPropertyName: "nodeHeight", publicName: "nodeHeight", isSignal: true, isRequired: false, transformFunction: null }, look: { classPropertyName: "look", publicName: "look", isSignal: true, isRequired: false, transformFunction: null }, itemTemplate: { classPropertyName: "itemTemplate", publicName: "itemTemplate", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { datasource: "datasourceChange", onBeforeDrop: "onBeforeDrop", onNodeToggle: "onNodeToggle", onNodeSelect: "onNodeSelect", onOrderChange: "onOrderChange", onMoveChange: "onMoveChange", onItemsChange: "onItemsChange" }, host: { attributes: { "role": "tree", "tabindex": "0" }, listeners: { "keydown": "handleKeyDown($event)", "focus": "onTreeFocus($event)", "blur": "onTreeBlur($event)" }, properties: { "class.ax-tree-view-default": "look() === 'default'", "class.ax-tree-view-card": "look() === 'card'", "class.ax-tree-view-with-line": "look() === 'with-line'", "class.ax-tree-view-rtl": "isRtl", "style.--ax-tree-view-indent-size": "indentSize() + 'px'", "style.--ax-tree-view-line-offset": "(indentSize() / 2) + 'px'", "attr.aria-label": "\"Tree navigation\"" }, classAttribute: "ax-tree-view" }, providers: [AXTreeViewService], ngImport: i0, template: "<!-- Root drop list -->\n<div\n axFocusTrap\n [axDropList]=\"dragMode() !== 'none'\"\n [sortingDisabled]=\"false\"\n [id]=\"getListId()\"\n [attr.data-node-id]=\"null\"\n dropListGroup=\"ax-tree-view-nodes\"\n (dropListDropped)=\"onDrop($event)\"\n class=\"ax-tree-view-drop-list\"\n [class.ax-tree-view-card]=\"look() === 'card'\"\n [class.ax-tree-view-with-lines]=\"look() === 'with-line'\"\n [class.ax-tree-view-compact]=\"nodeHeight() === 'compact'\"\n [class.ax-tree-view-comfortable]=\"nodeHeight() === 'comfortable'\"\n role=\"group\"\n>\n @for (node of nodes(); track node.id) {\n @if (node.visible !== false) {\n <div\n [axDrag]=\"dragMode() !== 'none'\"\n [dragDisabled]=\"node.disabled\"\n [dragData]=\"node\"\n class=\"ax-tree-view-node\"\n [class.ax-tree-view-node-selected]=\"node.selected\"\n [class.ax-tree-view-node-disabled]=\"node.disabled\"\n [class.ax-tree-view-node-loading]=\"node.loading\"\n role=\"treeitem\"\n [attr.aria-level]=\"getNodeAriaLevel(0)\"\n [attr.aria-expanded]=\"getNodeAriaExpanded(node)\"\n [attr.aria-selected]=\"getNodeAriaSelected(node)\"\n [attr.aria-disabled]=\"node.disabled ? 'true' : null\"\n >\n <div\n class=\"ax-tree-view-node-content\"\n [axDropList]=\"dragMode() !== 'none'\"\n [id]=\"'ax-tree-view-node-drop-' + node.id\"\n [attr.data-node-id]=\"node.id\"\n [attr.data-tree-node-id]=\"node.id\"\n [attr.data-drop-type]=\"'onto-node'\"\n dropListGroup=\"ax-tree-view-nodes\"\n (dropListDropped)=\"onDropOntoNode($event, node)\"\n (click)=\"\n (selectMode() === 'single' || (selectMode() === 'multiple' && checkOnClick())) && onNodeClick(node, $event)\n \"\n (focus)=\"onNodeFocus(node.id)\"\n [tabindex]=\"isNodeFocused(node.id) ? 0 : -1\"\n >\n @if (dragMode() === 'handler') {\n <span class=\"ax-tree-view-drag-handle\" axDragHandle title=\"Drag to reorder\"> \u22EE\u22EE </span>\n }\n <ax-button\n class=\"ax-tree-view-expand-toggle ax-sm\"\n (onClick)=\"toggleNode(node, $any($event))\"\n [class.ax-tree-view-has-children]=\"shouldShowExpandToggle(node)\"\n [class.ax-tree-view-expanded]=\"node.expanded\"\n [disabled]=\"node.disabled || node.loading\"\n [style.visibility]=\"shouldShowExpandToggle(node) ? 'visible' : 'hidden'\"\n >\n @if (node.loading) {\n <ax-icon>\n <i class=\"fa-solid fa-spinner fa-spin ax-tree-view-loading-spinner\"></i>\n </ax-icon>\n } @else {\n <ax-icon>\n <i\n [class]=\"node.expanded ? directionExpandedIcon() : directionCollapsedIcon()\"\n class=\"ax-tree-view-toggle-icon\"\n ></i>\n </ax-icon>\n }\n </ax-button>\n @if (itemTemplate()) {\n <ng-container\n [ngTemplateOutlet]=\"itemTemplate()!\"\n [ngTemplateOutletContext]=\"getTemplateContext(node, 0)\"\n ></ng-container>\n } @else {\n @if (shouldShowCheckbox()) {\n <ax-check-box\n class=\"ax-tree-view-checkbox\"\n [ngModel]=\"node.indeterminate ? null : node.selected || false\"\n [indeterminate]=\"node.indeterminate || false\"\n (onValueChanged)=\"toggleSelection(node, $event)\"\n ></ax-check-box>\n }\n @if (showIcons() && node.icon) {\n <i [class]=\"node.icon\" class=\"ax-tree-view-node-icon\"></i>\n }\n <span class=\"ax-tree-view-node-label\">{{ node.label }}</span>\n @if (showChildrenBadge() && (node.childrenCount || (node.children && node.children.length > 0))) {\n <ax-badge\n class=\"ax-tree-view-children-badge\"\n [text]=\"(node.childrenCount ?? node.children?.length ?? 0).toString()\"\n ></ax-badge>\n }\n }\n </div>\n </div>\n @if (node.expanded && node.children && node.children.length > 0) {\n <div class=\"ax-tree-view-children\" role=\"group\">\n <ng-container\n [ngTemplateOutlet]=\"childrenList\"\n [ngTemplateOutletContext]=\"{ children: node.children, parent: node, level: 1 }\"\n ></ng-container>\n </div>\n }\n }\n }\n</div>\n\n<!-- Recursive children template -->\n<ng-template #childrenList let-children=\"children\" let-parent=\"parent\" let-level=\"level\">\n <div\n [axDropList]=\"dragMode() !== 'none'\"\n [id]=\"getListId(parent)\"\n [attr.data-node-id]=\"parent.id\"\n dropListGroup=\"ax-tree-view-nodes\"\n (dropListDropped)=\"onDrop($event, parent)\"\n class=\"ax-tree-view-drop-list\"\n role=\"group\"\n >\n @for (node of children; track node.id) {\n @if (node.visible !== false) {\n <div\n [axDrag]=\"dragMode() !== 'none'\"\n [dragDisabled]=\"node.disabled\"\n [dragData]=\"node\"\n class=\"ax-tree-view-node\"\n [class.ax-tree-view-node-selected]=\"node.selected\"\n [class.ax-tree-view-node-disabled]=\"node.disabled\"\n [class.ax-tree-view-node-loading]=\"node.loading\"\n [class.ax-tree-view-node-focused]=\"isNodeFocused(node.id)\"\n role=\"treeitem\"\n [attr.aria-level]=\"getNodeAriaLevel(level)\"\n [attr.aria-expanded]=\"getNodeAriaExpanded(node)\"\n [attr.aria-selected]=\"getNodeAriaSelected(node)\"\n [attr.aria-disabled]=\"node.disabled ? 'true' : null\"\n >\n <div\n class=\"ax-tree-view-node-content\"\n [style.padding-inline-start.px]=\"getNodePaddingInline(level)\"\n [axDropList]=\"dragMode() !== 'none'\"\n [id]=\"'ax-tree-view-node-drop-' + node.id\"\n [attr.data-node-id]=\"node.id\"\n [attr.data-tree-node-id]=\"node.id\"\n [attr.data-drop-type]=\"'onto-node'\"\n dropListGroup=\"ax-tree-view-nodes\"\n (dropListDropped)=\"onDropOntoNode($event, node)\"\n (click)=\"\n (selectMode() === 'single' || (selectMode() === 'multiple' && checkOnClick())) &&\n onNodeClick(node, $event)\n \"\n (focus)=\"onNodeFocus(node.id)\"\n (blur)=\"focusedNodeId.set(null)\"\n [tabindex]=\"isNodeFocused(node.id) ? 0 : -1\"\n >\n @if (dragMode() === 'handler') {\n <span class=\"ax-tree-view-drag-handle\" axDragHandle title=\"Drag to reorder\"> \u22EE\u22EE </span>\n }\n <ax-button\n class=\"ax-tree-view-expand-toggle ax-sm\"\n (onClick)=\"toggleNode(node, $any($event))\"\n [class.ax-tree-view-has-children]=\"shouldShowExpandToggle(node)\"\n [class.ax-tree-view-expanded]=\"node.expanded\"\n [disabled]=\"node.disabled || node.loading\"\n [style.visibility]=\"shouldShowExpandToggle(node) ? 'visible' : 'hidden'\"\n >\n @if (node.loading) {\n <ax-icon>\n <i class=\"fa-solid fa-spinner fa-spin ax-tree-view-loading-spinner\"></i>\n </ax-icon>\n } @else {\n <ax-icon>\n <i\n [class]=\"node.expanded ? directionExpandedIcon() : directionCollapsedIcon()\"\n class=\"ax-tree-view-toggle-icon\"\n ></i>\n </ax-icon>\n }\n </ax-button>\n\n @if (itemTemplate()) {\n <ng-container\n [ngTemplateOutlet]=\"itemTemplate()!\"\n [ngTemplateOutletContext]=\"getTemplateContext(node, level)\"\n ></ng-container>\n } @else {\n @if (shouldShowCheckbox()) {\n <ax-check-box\n class=\"ax-tree-view-checkbox\"\n [ngModel]=\"node.indeterminate ? null : node.selected || false\"\n [indeterminate]=\"node.indeterminate || false\"\n (onValueChanged)=\"toggleSelection(node, $event)\"\n ></ax-check-box>\n }\n @if (showIcons() && node.icon) {\n <i [class]=\"node.icon\" class=\"ax-tree-view-node-icon\"></i>\n }\n <span class=\"ax-tree-view-node-label\">{{ node.label }}</span>\n @if (showChildrenBadge() && (node.childrenCount || (node.children && node.children.length > 0))) {\n <ax-badge\n class=\"ax-tree-view-children-badge\"\n [text]=\"(node.childrenCount ?? node.children?.length ?? 0).toString()\"\n ></ax-badge>\n }\n }\n </div>\n </div>\n @if (node.expanded && node.children && node.children.length > 0) {\n <div class=\"ax-tree-view-children\" role=\"group\">\n <ng-container\n [ngTemplateOutlet]=\"childrenList\"\n [ngTemplateOutletContext]=\"{ children: node.children, parent: node, level: level + 1 }\"\n ></ng-container>\n </div>\n }\n }\n }\n </div>\n</ng-template>\n", styles: [".ax-tree-view{display:block;width:100%;--ax-comp-tree-view-indent-size: 12px;--ax-comp-tree-view-node-hover-bg: rgba(var(--ax-sys-color-on-lightest-surface), .04);--ax-comp-tree-view-node-selected-bg: rgba(var(--ax-sys-color-primary-500), .12);--ax-comp-tree-view-node-border-radius: 6px;--ax-comp-tree-view-node-margin: .25rem;--ax-comp-tree-view-line-color: rgba(var(--ax-sys-color-on-lightest-surface), .15);--ax-comp-tree-view-drag-preview-opacity: .9;--ax-comp-tree-view-drag-placeholder-bg: rgba(var(--ax-sys-color-on-lightest-surface), .02);--ax-comp-tree-view-drop-active-bg: rgba(var(--ax-sys-color-primary-500), .08);--ax-comp-tree-view-drop-active-outline: rgba(var(--ax-sys-color-primary-500), .3);--ax-comp-tree-view-content-padding: 0;--ax-comp-tree-view-content-gap: .5rem;--ax-comp-tree-view-drop-list-min-height: 2rem;--ax-comp-tree-view-drag-handle-padding: .25rem;--ax-comp-tree-view-expand-toggle-padding: .25rem;--ax-comp-tree-view-card-node-margin: .5rem;--ax-comp-tree-view-card-content-padding: 1rem;--ax-comp-tree-view-outline-offset: 2px;--ax-comp-tree-view-outline-offset-negative: -2px}.ax-tree-view-drop-list{min-height:var(--ax-comp-tree-view-drop-list-min-height)}.ax-tree-view-compact .ax-tree-view-node-content{padding:var(--ax-comp-tree-view-content-padding, .25rem .5rem);gap:var(--ax-comp-tree-view-content-gap, .375rem);font-size:.8125rem}.ax-tree-view-comfortable .ax-tree-view-node-content{padding:var(--ax-comp-tree-view-content-padding, .75rem .625rem);gap:var(--ax-comp-tree-view-content-gap, .625rem);font-size:.9375rem}.ax-tree-view-node{position:relative;margin:var(--ax-comp-tree-view-node-margin) 0;border-radius:var(--ax-comp-tree-view-node-border-radius);border:1px solid transparent;cursor:move}.ax-tree-view-node:hover:not(.ax-dragging){background:var(--ax-comp-tree-view-node-hover-bg)}.ax-tree-view-node.ax-tree-view-node-selected{background:var(--ax-comp-tree-view-node-selected-bg);border-color:currentColor}.ax-tree-view-node.ax-dragging{opacity:var(--ax-comp-tree-view-drag-placeholder-opacity);cursor:grabbing!important}.ax-tree-view-node.ax-drag-placeholder{background:var(--ax-comp-tree-view-drag-placeholder-bg)}.ax-drag-preview{opacity:var(--ax-comp-tree-view-drag-preview-opacity)!important;box-shadow:0 4px 12px rgba(var(--ax-sys-color-on-lightest-surface),.2)!important;cursor:grabbing!important;border:2px dashed currentColor!important}.ax-tree-view-node-content.ax-drop-list-sorting-active{background:var(--ax-comp-tree-view-drop-active-bg);border-radius:var(--ax-comp-tree-view-node-border-radius);outline:2px dashed var(--ax-comp-tree-view-drop-active-outline);outline-offset:var(--ax-comp-tree-view-outline-offset-negative)}.ax-tree-view-node-content{display:flex;align-items:center;gap:var(--ax-comp-tree-view-content-gap);padding:var(--ax-comp-tree-view-content-padding);cursor:pointer;-webkit-user-select:none;user-select:none;outline:none;border:1px solid transparent;border-radius:var(--ax-comp-tree-view-node-border-radius)}.ax-tree-view-node-content:focus{outline:none}.ax-tree-view-node-content:focus-visible{outline:2px solid rgba(var(--ax-sys-color-primary-500),.8);outline-offset:var(--ax-comp-tree-view-outline-offset);border-radius:var(--ax-comp-tree-view-node-border-radius)}.ax-tree-view-drag-handle{cursor:grab;opacity:.6;padding:var(--ax-comp-tree-view-drag-handle-padding)}.ax-tree-view-drag-handle:hover{opacity:1}.ax-tree-view-drag-handle:active{cursor:grabbing}.ax-tree-view-expand-toggle{background:none;border:none;cursor:pointer;padding:var(--ax-comp-tree-view-expand-toggle-padding);min-width:1.5rem;height:1.5rem}.ax-tree-view-expand-toggle:not(.ax-tree-view-has-children){opacity:0;pointer-events:none}.ax-tree-view-toggle-icon{font-size:.75rem}.ax-tree-view-node-icon{font-size:1.125rem;flex-shrink:0}.ax-tree-view-node-label{flex:1;font-size:.875rem;line-height:1rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ax-tree-view-children{padding-inline-start:var(--ax-tree-view-indent-size, var(--ax-comp-tree-view-indent-size))}.ax-tree-view-node-disabled{opacity:.5;cursor:not-allowed;pointer-events:none}.ax-tree-view-node-loading{opacity:.7}.ax-tree-view-card .ax-tree-view-node{border:1px solid rgba(var(--ax-sys-color-border-lightest-surface),1);margin:var(--ax-comp-tree-view-card-node-margin) 0}.ax-tree-view-card .ax-tree-view-node-content{padding:var(--ax-comp-tree-view-card-content-padding)}.ax-tree-view-with-lines .ax-tree-view-children{position:relative;padding-inline-start:var(--ax-tree-view-indent-size, var(--ax-comp-tree-view-indent-size))}.ax-tree-view-with-lines .ax-tree-view-children:before{content:\"\";position:absolute;inset-inline-start:var(--ax-tree-view-line-offset, calc(var(--ax-comp-tree-view-indent-size) / 2));top:0;height:calc(100% - .875rem);width:1px;background:var(--ax-tree-view-line-color, var(--ax-comp-tree-view-line-color))}.ax-tree-view-with-lines .ax-tree-view-node{position:relative}.ax-tree-view-with-lines .ax-tree-view-node:before{content:\"\";position:absolute;inset-inline-start:calc(-1 * var(--ax-tree-view-line-offset, calc(var(--ax-comp-tree-view-indent-size) / 2)));top:60%;width:var(--ax-tree-view-line-offset, calc(var(--ax-comp-tree-view-indent-size) / 2));height:1px;background:var(--ax-tree-view-line-color, var(--ax-comp-tree-view-line-color))}.ax-tree-view-with-lines>.ax-tree-view-drop-list>.ax-tree-view-node:before,.ax-tree-view-with-lines>.ax-tree-view-node:before{display:none}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: AXDragDirective, selector: "[axDrag]", inputs: ["axDrag", "dragData", "dragDisabled", "dragTransition", "dragElementClone", "dropZoneGroup", "dragStartDelay", "dragResetOnDblClick", "dragLockAxis", "dragClonedTemplate", "dragCursor", "dragBoundary", "dragTransitionDuration"], outputs: ["dragPositionChanged"] }, { kind: "directive", type: AXDragHandleDirective, selector: "[axDragHandle]" }, { kind: "directive", type: AXDropListDirective, selector: "[axDropList]", inputs: ["axDropList", "sortingDisabled", "dropListGroup", "dropListOrientation"], outputs: ["dropListDropped"], exportAs: ["axDropList"] }, { kind: "directive", type: AXFocusTrapDirective, selector: "[axFocusTrap]" }, { kind: "component", type: AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "component", type: AXCheckBoxComponent, selector: "ax-check-box", inputs: ["disabled", "tabIndex", "readonly", "color", "value", "name", "id", "isLoading", "indeterminate"], outputs: ["onBlur", "onFocus", "valueChange", "onValueChanged"] }, { kind: "component", type: AXBadgeComponent, selector: "ax-badge", inputs: ["color", "look", "text"] }, { kind: "component", type: AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
2071
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.9", type: AXTreeViewComponent, isStandalone: true, selector: "ax-tree-view", inputs: { datasource: { classPropertyName: "datasource", publicName: "datasource", isSignal: true, isRequired: true, transformFunction: null }, selectMode: { classPropertyName: "selectMode", publicName: "selectMode", isSignal: true, isRequired: false, transformFunction: null }, showCheckbox: { classPropertyName: "showCheckbox", publicName: "showCheckbox", isSignal: true, isRequired: false, transformFunction: null }, selectionBehavior: { classPropertyName: "selectionBehavior", publicName: "selectionBehavior", isSignal: true, isRequired: false, transformFunction: null }, checkOnClick: { classPropertyName: "checkOnClick", publicName: "checkOnClick", isSignal: true, isRequired: false, transformFunction: null }, dragMode: { classPropertyName: "dragMode", publicName: "dragMode", isSignal: true, isRequired: false, transformFunction: null }, dragOperationType: { classPropertyName: "dragOperationType", publicName: "dragOperationType", isSignal: true, isRequired: false, transformFunction: null }, showIcons: { classPropertyName: "showIcons", publicName: "showIcons", isSignal: true, isRequired: false, transformFunction: null }, showChildrenBadge: { classPropertyName: "showChildrenBadge", publicName: "showChildrenBadge", isSignal: true, isRequired: false, transformFunction: null }, expandedIcon: { classPropertyName: "expandedIcon", publicName: "expandedIcon", isSignal: true, isRequired: false, transformFunction: null }, collapsedIcon: { classPropertyName: "collapsedIcon", publicName: "collapsedIcon", isSignal: true, isRequired: false, transformFunction: null }, indentSize: { classPropertyName: "indentSize", publicName: "indentSize", isSignal: true, isRequired: false, transformFunction: null }, look: { classPropertyName: "look", publicName: "look", isSignal: true, isRequired: false, transformFunction: null }, nodeTemplate: { classPropertyName: "nodeTemplate", publicName: "nodeTemplate", isSignal: true, isRequired: false, transformFunction: null }, idField: { classPropertyName: "idField", publicName: "idField", isSignal: true, isRequired: false, transformFunction: null }, titleField: { classPropertyName: "titleField", publicName: "titleField", isSignal: true, isRequired: false, transformFunction: null }, tooltipField: { classPropertyName: "tooltipField", publicName: "tooltipField", isSignal: true, isRequired: false, transformFunction: null }, iconField: { classPropertyName: "iconField", publicName: "iconField", isSignal: true, isRequired: false, transformFunction: null }, expandedField: { classPropertyName: "expandedField", publicName: "expandedField", isSignal: true, isRequired: false, transformFunction: null }, selectedField: { classPropertyName: "selectedField", publicName: "selectedField", isSignal: true, isRequired: false, transformFunction: null }, indeterminateField: { classPropertyName: "indeterminateField", publicName: "indeterminateField", isSignal: true, isRequired: false, transformFunction: null }, disabledField: { classPropertyName: "disabledField", publicName: "disabledField", isSignal: true, isRequired: false, transformFunction: null }, hiddenField: { classPropertyName: "hiddenField", publicName: "hiddenField", isSignal: true, isRequired: false, transformFunction: null }, childrenField: { classPropertyName: "childrenField", publicName: "childrenField", isSignal: true, isRequired: false, transformFunction: null }, childrenCountField: { classPropertyName: "childrenCountField", publicName: "childrenCountField", isSignal: true, isRequired: false, transformFunction: null }, dataField: { classPropertyName: "dataField", publicName: "dataField", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { datasource: "datasourceChange", onBeforeDrop: "onBeforeDrop", onNodeToggle: "onNodeToggle", onNodeSelect: "onNodeSelect", onSelectionChange: "onSelectionChange", onOrderChange: "onOrderChange", onMoveChange: "onMoveChange", onItemsChange: "onItemsChange" }, host: { attributes: { "role": "tree", "tabindex": "0" }, listeners: { "keydown": "handleKeyDown($event)", "focus": "onTreeFocus($event)", "blur": "onTreeBlur($event)" }, properties: { "class.ax-tree-view-default": "look() === 'default'", "class.ax-tree-view-card": "look() === 'card'", "class.ax-tree-view-with-line": "look() === 'with-line'", "class.ax-tree-view-rtl": "isRtl", "style.--ax-tree-view-indent-size": "indentSize() + 'px'", "style.--ax-tree-view-line-offset": "(indentSize() / 2) + 'px'", "attr.aria-label": "\"Tree navigation\"" }, classAttribute: "ax-tree-view" }, providers: [AXTreeViewService], ngImport: i0, template: "<!-- Root drop list -->\n<div\n axFocusTrap\n [axDropList]=\"dragMode() !== 'none'\"\n [sortingDisabled]=\"false\"\n [id]=\"getListId()\"\n [attr.data-node-id]=\"null\"\n dropListGroup=\"ax-tree-view-nodes\"\n (dropListDropped)=\"onDrop($event)\"\n class=\"ax-tree-view-drop-list\"\n [class.ax-tree-view-card]=\"look() === 'card'\"\n [class.ax-tree-view-with-lines]=\"look() === 'with-line'\"\n role=\"group\"\n>\n @for (node of nodes(); track getNodeId(node)) {\n @if (getNodeHidden(node) !== true) {\n <div\n [axDrag]=\"dragMode() !== 'none'\"\n [dragDisabled]=\"getNodeDisabled(node)\"\n [dragData]=\"node\"\n class=\"ax-tree-view-node\"\n [class.ax-tree-view-node-selected]=\"getNodeSelected(node)\"\n [class.ax-tree-view-node-disabled]=\"getNodeDisabled(node)\"\n [class.ax-tree-view-node-loading]=\"getNodeLoading(node)\"\n role=\"treeitem\"\n [attr.aria-level]=\"getNodeAriaLevel(0)\"\n [attr.aria-expanded]=\"getNodeAriaExpanded(node)\"\n [attr.aria-selected]=\"getNodeAriaSelected(node)\"\n [attr.aria-disabled]=\"getNodeDisabled(node) || (isLeafOnlyMode() && !isLeafNode(node)) ? 'true' : null\"\n >\n <div\n class=\"ax-tree-view-node-content\"\n [axDropList]=\"dragMode() !== 'none'\"\n [id]=\"'ax-tree-view-node-drop-' + getNodeId(node)\"\n [attr.data-node-id]=\"getNodeId(node)\"\n [attr.data-tree-node-id]=\"getNodeId(node)\"\n [attr.data-drop-type]=\"'onto-node'\"\n dropListGroup=\"ax-tree-view-nodes\"\n (dropListDropped)=\"onDropOntoNode($event, node)\"\n (click)=\"\n (selectMode() === 'single' || (selectMode() === 'multiple' && checkOnClick())) && onNodeClick(node, $event)\n \"\n (focus)=\"onNodeFocus(getNodeId(node))\"\n [tabindex]=\"isNodeFocused(getNodeId(node)) ? 0 : -1\"\n >\n @if (dragMode() === 'handler') {\n <span class=\"ax-tree-view-drag-handle\" axDragHandle title=\"Drag to reorder\"> \u22EE\u22EE </span>\n }\n <ax-button\n class=\"ax-tree-view-expand-toggle ax-sm\"\n (onClick)=\"toggleNode(node, $any($event))\"\n [class.ax-tree-view-has-children]=\"shouldShowExpandToggle(node)\"\n [class.ax-tree-view-expanded]=\"getNodeExpanded(node)\"\n [disabled]=\"getNodeDisabled(node) || getNodeLoading(node)\"\n [style.visibility]=\"shouldShowExpandToggle(node) ? 'visible' : 'hidden'\"\n >\n @if (getNodeLoading(node)) {\n <ax-icon>\n <i class=\"fa-solid fa-spinner fa-spin ax-tree-view-loading-spinner\"></i>\n </ax-icon>\n } @else {\n <ax-icon>\n <i\n [class]=\"getNodeExpanded(node) ? directionExpandedIcon() : directionCollapsedIcon()\"\n class=\"ax-tree-view-toggle-icon\"\n ></i>\n </ax-icon>\n }\n </ax-button>\n @if (nodeTemplate()) {\n <ng-container\n [ngTemplateOutlet]=\"nodeTemplate()!\"\n [ngTemplateOutletContext]=\"getTemplateContext(node, 0)\"\n ></ng-container>\n } @else {\n @if (shouldShowCheckboxForNode(node)) {\n <ax-check-box\n class=\"ax-tree-view-checkbox\"\n [ngModel]=\"getNodeIndeterminate(node) ? null : getNodeSelected(node) || false\"\n [indeterminate]=\"getNodeIndeterminate(node) || false\"\n (onValueChanged)=\"toggleSelection(node, $event)\"\n ></ax-check-box>\n }\n @if (showIcons() && getNodeIcon(node)) {\n <i [class]=\"getNodeIcon(node)\" class=\"ax-tree-view-node-icon\"></i>\n }\n <span\n class=\"ax-tree-view-node-label\"\n [axTooltip]=\"getNodeTooltip(node) || ''\"\n [axTooltipDisabled]=\"!getNodeTooltip(node)\"\n [axTooltipPlacement]=\"'top-start'\"\n >\n {{ getNodeTitle(node) }}\n </span>\n @if (\n showChildrenBadge() &&\n (getNodeChildrenCount(node) || (getNodeChildren(node) && getNodeChildren(node)!.length > 0))\n ) {\n <span class=\"ax-tree-view-node-badge\">\n <ax-badge\n class=\"ax-tree-view-children-badge\"\n [text]=\"(getNodeChildrenCount(node) ?? getNodeChildren(node)?.length ?? 0).toString()\"\n ></ax-badge>\n </span>\n }\n }\n </div>\n </div>\n @if (getNodeExpanded(node) && getNodeChildren(node) && getNodeChildren(node)!.length > 0) {\n <div class=\"ax-tree-view-children\" role=\"group\">\n <ng-container\n [ngTemplateOutlet]=\"childrenList\"\n [ngTemplateOutletContext]=\"{ children: getNodeChildren(node), parent: node, level: 1 }\"\n ></ng-container>\n </div>\n }\n }\n }\n</div>\n\n<!-- Recursive children template -->\n<ng-template #childrenList let-children=\"children\" let-parent=\"parent\" let-level=\"level\">\n <div\n [axDropList]=\"dragMode() !== 'none'\"\n [id]=\"getListId(parent)\"\n [attr.data-node-id]=\"getNodeId(parent)\"\n dropListGroup=\"ax-tree-view-nodes\"\n (dropListDropped)=\"onDrop($event, parent)\"\n class=\"ax-tree-view-drop-list\"\n role=\"group\"\n >\n @for (node of children; track getNodeId(node)) {\n @if (getNodeHidden(node) !== true) {\n <div\n [axDrag]=\"dragMode() !== 'none'\"\n [dragDisabled]=\"getNodeDisabled(node)\"\n [dragData]=\"node\"\n class=\"ax-tree-view-node\"\n [class.ax-tree-view-node-selected]=\"getNodeSelected(node)\"\n [class.ax-tree-view-node-disabled]=\"getNodeDisabled(node)\"\n [class.ax-tree-view-node-loading]=\"getNodeLoading(node)\"\n [class.ax-tree-view-node-focused]=\"isNodeFocused(getNodeId(node))\"\n role=\"treeitem\"\n [attr.aria-level]=\"getNodeAriaLevel(level)\"\n [attr.aria-expanded]=\"getNodeAriaExpanded(node)\"\n [attr.aria-selected]=\"getNodeAriaSelected(node)\"\n [attr.aria-disabled]=\"getNodeDisabled(node) ? 'true' : null\"\n >\n <div\n class=\"ax-tree-view-node-content\"\n [axDropList]=\"dragMode() !== 'none'\"\n [id]=\"'ax-tree-view-node-drop-' + getNodeId(node)\"\n [attr.data-node-id]=\"getNodeId(node)\"\n [attr.data-tree-node-id]=\"getNodeId(node)\"\n [attr.data-drop-type]=\"'onto-node'\"\n dropListGroup=\"ax-tree-view-nodes\"\n (dropListDropped)=\"onDropOntoNode($event, node)\"\n (click)=\"\n (selectMode() === 'single' || (selectMode() === 'multiple' && checkOnClick())) &&\n onNodeClick(node, $event)\n \"\n (focus)=\"onNodeFocus(getNodeId(node))\"\n (blur)=\"focusedNodeId.set(null)\"\n [tabindex]=\"isNodeFocused(getNodeId(node)) ? 0 : -1\"\n >\n @if (dragMode() === 'handler') {\n <span class=\"ax-tree-view-drag-handle\" axDragHandle title=\"Drag to reorder\"> \u22EE\u22EE </span>\n }\n <ax-button\n class=\"ax-tree-view-expand-toggle ax-sm\"\n (onClick)=\"toggleNode(node, $any($event))\"\n [class.ax-tree-view-has-children]=\"shouldShowExpandToggle(node)\"\n [class.ax-tree-view-expanded]=\"getNodeExpanded(node)\"\n [disabled]=\"getNodeDisabled(node) || getNodeLoading(node)\"\n [style.visibility]=\"shouldShowExpandToggle(node) ? 'visible' : 'hidden'\"\n >\n @if (getNodeLoading(node)) {\n <ax-icon>\n <i class=\"fa-solid fa-spinner fa-spin ax-tree-view-loading-spinner\"></i>\n </ax-icon>\n } @else {\n <ax-icon>\n <i\n [class]=\"getNodeExpanded(node) ? directionExpandedIcon() : directionCollapsedIcon()\"\n class=\"ax-tree-view-toggle-icon\"\n ></i>\n </ax-icon>\n }\n </ax-button>\n\n @if (nodeTemplate()) {\n <ng-container\n [ngTemplateOutlet]=\"nodeTemplate()!\"\n [ngTemplateOutletContext]=\"getTemplateContext(node, level)\"\n ></ng-container>\n } @else {\n @if (shouldShowCheckboxForNode(node)) {\n <ax-check-box\n class=\"ax-tree-view-checkbox\"\n [ngModel]=\"getNodeIndeterminate(node) ? null : getNodeSelected(node) || false\"\n [indeterminate]=\"getNodeIndeterminate(node) || false\"\n (onValueChanged)=\"toggleSelection(node, $event)\"\n ></ax-check-box>\n }\n @if (showIcons() && getNodeIcon(node)) {\n <i [class]=\"getNodeIcon(node)\" class=\"ax-tree-view-node-icon\"></i>\n }\n <span\n class=\"ax-tree-view-node-label\"\n [axTooltip]=\"getNodeTooltip(node) || ''\"\n [axTooltipDisabled]=\"!getNodeTooltip(node)\"\n [axTooltipPlacement]=\"'top-start'\"\n >\n {{ getNodeTitle(node) }}\n </span>\n @if (\n showChildrenBadge() &&\n (getNodeChildrenCount(node) || (getNodeChildren(node) && getNodeChildren(node)!.length > 0))\n ) {\n <span class=\"ax-tree-view-node-badge\">\n <ax-badge\n class=\"ax-tree-view-children-badge\"\n [text]=\"(getNodeChildrenCount(node) ?? getNodeChildren(node)?.length ?? 0).toString()\"\n ></ax-badge>\n </span>\n }\n }\n </div>\n </div>\n @if (getNodeExpanded(node) && getNodeChildren(node) && getNodeChildren(node)!.length > 0) {\n <div class=\"ax-tree-view-children\" role=\"group\">\n <ng-container\n [ngTemplateOutlet]=\"childrenList\"\n [ngTemplateOutletContext]=\"{ children: getNodeChildren(node), parent: node, level: level + 1 }\"\n ></ng-container>\n </div>\n }\n }\n }\n </div>\n</ng-template>\n", styles: [".ax-tree-view{display:block;width:100%;--ax-comp-tree-view-indent-size: 12px;--ax-comp-tree-view-node-hover-bg: rgba(var(--ax-sys-color-on-lightest-surface), .04);--ax-comp-tree-view-node-selected-bg: rgba(var(--ax-sys-color-primary-500), .12);--ax-comp-tree-view-node-border-radius: 6px;--ax-comp-tree-view-node-margin: .25rem;--ax-comp-tree-view-line-color: rgba(var(--ax-sys-color-on-lightest-surface), .15);--ax-comp-tree-view-drag-preview-opacity: .9;--ax-comp-tree-view-drag-placeholder-bg: rgba(var(--ax-sys-color-on-lightest-surface), .02);--ax-comp-tree-view-drop-active-bg: rgba(var(--ax-sys-color-primary-500), .08);--ax-comp-tree-view-drop-active-outline: rgba(var(--ax-sys-color-primary-500), .3);--ax-comp-tree-view-content-padding: 0;--ax-comp-tree-view-content-gap: .5rem;--ax-comp-tree-view-drop-list-min-height: 2rem;--ax-comp-tree-view-drag-handle-padding: .25rem;--ax-comp-tree-view-badge-padding: .25rem;--ax-comp-tree-view-expand-toggle-padding: .25rem;--ax-comp-tree-view-outline-offset: 2px;--ax-comp-tree-view-outline-offset-negative: -2px}.ax-tree-view-drop-list{min-height:var(--ax-comp-tree-view-drop-list-min-height)}.ax-tree-view-node{position:relative;margin:var(--ax-comp-tree-view-node-margin) 0;border-radius:var(--ax-comp-tree-view-node-border-radius);cursor:move}.ax-tree-view-node:hover:not(.ax-dragging){background:var(--ax-comp-tree-view-node-hover-bg)}.ax-tree-view-node.ax-tree-view-node-selected{background:var(--ax-comp-tree-view-node-selected-bg)}.ax-tree-view-node.ax-dragging{opacity:var(--ax-comp-tree-view-drag-placeholder-opacity);cursor:grabbing!important}.ax-tree-view-node.ax-drag-placeholder{background:var(--ax-comp-tree-view-drag-placeholder-bg)}.ax-drag-preview{opacity:var(--ax-comp-tree-view-drag-preview-opacity)!important;box-shadow:0 4px 12px rgba(var(--ax-sys-color-on-lightest-surface),.2)!important;cursor:grabbing!important;border:2px dashed currentColor!important}.ax-tree-view-node-content.ax-drop-list-sorting-active{background:var(--ax-comp-tree-view-drop-active-bg);border-radius:var(--ax-comp-tree-view-node-border-radius);outline:2px dashed var(--ax-comp-tree-view-drop-active-outline);outline-offset:var(--ax-comp-tree-view-outline-offset-negative)}.ax-tree-view-node-content{display:flex;align-items:center;gap:var(--ax-comp-tree-view-content-gap);padding:var(--ax-comp-tree-view-content-padding);cursor:pointer;-webkit-user-select:none;user-select:none;outline:none;border-radius:var(--ax-comp-tree-view-node-border-radius)}.ax-tree-view-node-content:focus{outline:none}.ax-tree-view-node-content:focus-visible{outline:2px solid rgba(var(--ax-sys-color-primary-500),.8);outline-offset:var(--ax-comp-tree-view-outline-offset);border-radius:var(--ax-comp-tree-view-node-border-radius)}.ax-tree-view-drag-handle{cursor:grab;opacity:.6;padding:var(--ax-comp-tree-view-drag-handle-padding);padding-inline-start:calc(var(--ax-comp-tree-view-drag-handle-padding) * 2)}.ax-tree-view-drag-handle:hover{opacity:1}.ax-tree-view-drag-handle:active{cursor:grabbing}.ax-tree-view-expand-toggle{background:none;border:none;cursor:pointer;padding:var(--ax-comp-tree-view-expand-toggle-padding);min-width:1.5rem;height:1.5rem}.ax-tree-view-expand-toggle:not(.ax-tree-view-has-children){opacity:0;pointer-events:none}.ax-tree-view-toggle-icon{font-size:.75rem}.ax-tree-view-node-icon{font-size:1.125rem;flex-shrink:0}.ax-tree-view-node-label{flex:1;font-size:.875rem;line-height:1rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ax-tree-view-node-badge{padding:var(--ax-comp-tree-view-badge-padding);padding-inline-end:calc(var(--ax-comp-tree-view-badge-padding) * 1.5)}.ax-tree-view-children{padding-inline-start:var(--ax-tree-view-indent-size, var(--ax-comp-tree-view-indent-size))}.ax-tree-view-node-disabled{opacity:.5;cursor:not-allowed;pointer-events:none}.ax-tree-view-node-loading{opacity:.7}.ax-tree-view-card .ax-tree-view-node{border:1px solid rgba(var(--ax-sys-color-border-lightest-surface),1)}.ax-tree-view-card .ax-tree-view-node.ax-tree-view-node-selected{border:1px solid rgba(var(--ax-sys-color-border-surface),1)}.ax-tree-view-with-lines .ax-tree-view-children{position:relative;padding-inline-start:var(--ax-tree-view-indent-size, var(--ax-comp-tree-view-indent-size))}.ax-tree-view-with-lines .ax-tree-view-children:before{content:\"\";position:absolute;inset-inline-start:var(--ax-tree-view-line-offset, calc(var(--ax-comp-tree-view-indent-size) / 2));top:0;height:calc(100% - .875rem);width:1px;background:var(--ax-tree-view-line-color, var(--ax-comp-tree-view-line-color))}.ax-tree-view-with-lines .ax-tree-view-node{position:relative}.ax-tree-view-with-lines .ax-tree-view-node:before{content:\"\";position:absolute;inset-inline-start:calc(-1 * var(--ax-tree-view-line-offset, calc(var(--ax-comp-tree-view-indent-size) / 2)));top:60%;width:var(--ax-tree-view-line-offset, calc(var(--ax-comp-tree-view-indent-size) / 2));height:1px;background:var(--ax-tree-view-line-color, var(--ax-comp-tree-view-line-color))}.ax-tree-view-with-lines>.ax-tree-view-drop-list>.ax-tree-view-node:before,.ax-tree-view-with-lines>.ax-tree-view-node:before{display:none}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: AXDragDirective, selector: "[axDrag]", inputs: ["axDrag", "dragData", "dragDisabled", "dragTransition", "dragElementClone", "dropZoneGroup", "dragStartDelay", "dragResetOnDblClick", "dragLockAxis", "dragClonedTemplate", "dragCursor", "dragBoundary", "dragTransitionDuration"], outputs: ["dragPositionChanged"] }, { kind: "directive", type: AXDragHandleDirective, selector: "[axDragHandle]" }, { kind: "directive", type: AXDropListDirective, selector: "[axDropList]", inputs: ["axDropList", "sortingDisabled", "dropListGroup", "dropListOrientation"], outputs: ["dropListDropped"], exportAs: ["axDropList"] }, { kind: "directive", type: AXFocusTrapDirective, selector: "[axFocusTrap]" }, { kind: "component", type: AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "component", type: AXCheckBoxComponent, selector: "ax-check-box", inputs: ["disabled", "tabIndex", "readonly", "color", "value", "name", "id", "isLoading", "indeterminate"], outputs: ["onBlur", "onFocus", "valueChange", "onValueChanged"] }, { kind: "component", type: AXBadgeComponent, selector: "ax-badge", inputs: ["color", "look", "text"] }, { kind: "component", type: AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "directive", type: AXTooltipDirective, selector: "[axTooltip]", inputs: ["axTooltipDisabled", "axTooltip", "axTooltipContext", "axTooltipPlacement", "axTooltipOffsetX", "axTooltipOffsetY", "axTooltipOpenAfter", "axTooltipCloseAfter"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
1188
2072
  }
1189
2073
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: AXTreeViewComponent, decorators: [{
1190
2074
  type: Component,
@@ -1200,6 +2084,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImpor
1200
2084
  AXCheckBoxComponent,
1201
2085
  AXBadgeComponent,
1202
2086
  AXDecoratorIconComponent,
2087
+ AXTooltipDirective,
1203
2088
  ], host: {
1204
2089
  class: 'ax-tree-view',
1205
2090
  '[class.ax-tree-view-default]': "look() === 'default'",
@@ -1214,8 +2099,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImpor
1214
2099
  '(focus)': 'onTreeFocus($event)',
1215
2100
  '(blur)': 'onTreeBlur($event)',
1216
2101
  tabindex: '0',
1217
- }, template: "<!-- Root drop list -->\n<div\n axFocusTrap\n [axDropList]=\"dragMode() !== 'none'\"\n [sortingDisabled]=\"false\"\n [id]=\"getListId()\"\n [attr.data-node-id]=\"null\"\n dropListGroup=\"ax-tree-view-nodes\"\n (dropListDropped)=\"onDrop($event)\"\n class=\"ax-tree-view-drop-list\"\n [class.ax-tree-view-card]=\"look() === 'card'\"\n [class.ax-tree-view-with-lines]=\"look() === 'with-line'\"\n [class.ax-tree-view-compact]=\"nodeHeight() === 'compact'\"\n [class.ax-tree-view-comfortable]=\"nodeHeight() === 'comfortable'\"\n role=\"group\"\n>\n @for (node of nodes(); track node.id) {\n @if (node.visible !== false) {\n <div\n [axDrag]=\"dragMode() !== 'none'\"\n [dragDisabled]=\"node.disabled\"\n [dragData]=\"node\"\n class=\"ax-tree-view-node\"\n [class.ax-tree-view-node-selected]=\"node.selected\"\n [class.ax-tree-view-node-disabled]=\"node.disabled\"\n [class.ax-tree-view-node-loading]=\"node.loading\"\n role=\"treeitem\"\n [attr.aria-level]=\"getNodeAriaLevel(0)\"\n [attr.aria-expanded]=\"getNodeAriaExpanded(node)\"\n [attr.aria-selected]=\"getNodeAriaSelected(node)\"\n [attr.aria-disabled]=\"node.disabled ? 'true' : null\"\n >\n <div\n class=\"ax-tree-view-node-content\"\n [axDropList]=\"dragMode() !== 'none'\"\n [id]=\"'ax-tree-view-node-drop-' + node.id\"\n [attr.data-node-id]=\"node.id\"\n [attr.data-tree-node-id]=\"node.id\"\n [attr.data-drop-type]=\"'onto-node'\"\n dropListGroup=\"ax-tree-view-nodes\"\n (dropListDropped)=\"onDropOntoNode($event, node)\"\n (click)=\"\n (selectMode() === 'single' || (selectMode() === 'multiple' && checkOnClick())) && onNodeClick(node, $event)\n \"\n (focus)=\"onNodeFocus(node.id)\"\n [tabindex]=\"isNodeFocused(node.id) ? 0 : -1\"\n >\n @if (dragMode() === 'handler') {\n <span class=\"ax-tree-view-drag-handle\" axDragHandle title=\"Drag to reorder\"> \u22EE\u22EE </span>\n }\n <ax-button\n class=\"ax-tree-view-expand-toggle ax-sm\"\n (onClick)=\"toggleNode(node, $any($event))\"\n [class.ax-tree-view-has-children]=\"shouldShowExpandToggle(node)\"\n [class.ax-tree-view-expanded]=\"node.expanded\"\n [disabled]=\"node.disabled || node.loading\"\n [style.visibility]=\"shouldShowExpandToggle(node) ? 'visible' : 'hidden'\"\n >\n @if (node.loading) {\n <ax-icon>\n <i class=\"fa-solid fa-spinner fa-spin ax-tree-view-loading-spinner\"></i>\n </ax-icon>\n } @else {\n <ax-icon>\n <i\n [class]=\"node.expanded ? directionExpandedIcon() : directionCollapsedIcon()\"\n class=\"ax-tree-view-toggle-icon\"\n ></i>\n </ax-icon>\n }\n </ax-button>\n @if (itemTemplate()) {\n <ng-container\n [ngTemplateOutlet]=\"itemTemplate()!\"\n [ngTemplateOutletContext]=\"getTemplateContext(node, 0)\"\n ></ng-container>\n } @else {\n @if (shouldShowCheckbox()) {\n <ax-check-box\n class=\"ax-tree-view-checkbox\"\n [ngModel]=\"node.indeterminate ? null : node.selected || false\"\n [indeterminate]=\"node.indeterminate || false\"\n (onValueChanged)=\"toggleSelection(node, $event)\"\n ></ax-check-box>\n }\n @if (showIcons() && node.icon) {\n <i [class]=\"node.icon\" class=\"ax-tree-view-node-icon\"></i>\n }\n <span class=\"ax-tree-view-node-label\">{{ node.label }}</span>\n @if (showChildrenBadge() && (node.childrenCount || (node.children && node.children.length > 0))) {\n <ax-badge\n class=\"ax-tree-view-children-badge\"\n [text]=\"(node.childrenCount ?? node.children?.length ?? 0).toString()\"\n ></ax-badge>\n }\n }\n </div>\n </div>\n @if (node.expanded && node.children && node.children.length > 0) {\n <div class=\"ax-tree-view-children\" role=\"group\">\n <ng-container\n [ngTemplateOutlet]=\"childrenList\"\n [ngTemplateOutletContext]=\"{ children: node.children, parent: node, level: 1 }\"\n ></ng-container>\n </div>\n }\n }\n }\n</div>\n\n<!-- Recursive children template -->\n<ng-template #childrenList let-children=\"children\" let-parent=\"parent\" let-level=\"level\">\n <div\n [axDropList]=\"dragMode() !== 'none'\"\n [id]=\"getListId(parent)\"\n [attr.data-node-id]=\"parent.id\"\n dropListGroup=\"ax-tree-view-nodes\"\n (dropListDropped)=\"onDrop($event, parent)\"\n class=\"ax-tree-view-drop-list\"\n role=\"group\"\n >\n @for (node of children; track node.id) {\n @if (node.visible !== false) {\n <div\n [axDrag]=\"dragMode() !== 'none'\"\n [dragDisabled]=\"node.disabled\"\n [dragData]=\"node\"\n class=\"ax-tree-view-node\"\n [class.ax-tree-view-node-selected]=\"node.selected\"\n [class.ax-tree-view-node-disabled]=\"node.disabled\"\n [class.ax-tree-view-node-loading]=\"node.loading\"\n [class.ax-tree-view-node-focused]=\"isNodeFocused(node.id)\"\n role=\"treeitem\"\n [attr.aria-level]=\"getNodeAriaLevel(level)\"\n [attr.aria-expanded]=\"getNodeAriaExpanded(node)\"\n [attr.aria-selected]=\"getNodeAriaSelected(node)\"\n [attr.aria-disabled]=\"node.disabled ? 'true' : null\"\n >\n <div\n class=\"ax-tree-view-node-content\"\n [style.padding-inline-start.px]=\"getNodePaddingInline(level)\"\n [axDropList]=\"dragMode() !== 'none'\"\n [id]=\"'ax-tree-view-node-drop-' + node.id\"\n [attr.data-node-id]=\"node.id\"\n [attr.data-tree-node-id]=\"node.id\"\n [attr.data-drop-type]=\"'onto-node'\"\n dropListGroup=\"ax-tree-view-nodes\"\n (dropListDropped)=\"onDropOntoNode($event, node)\"\n (click)=\"\n (selectMode() === 'single' || (selectMode() === 'multiple' && checkOnClick())) &&\n onNodeClick(node, $event)\n \"\n (focus)=\"onNodeFocus(node.id)\"\n (blur)=\"focusedNodeId.set(null)\"\n [tabindex]=\"isNodeFocused(node.id) ? 0 : -1\"\n >\n @if (dragMode() === 'handler') {\n <span class=\"ax-tree-view-drag-handle\" axDragHandle title=\"Drag to reorder\"> \u22EE\u22EE </span>\n }\n <ax-button\n class=\"ax-tree-view-expand-toggle ax-sm\"\n (onClick)=\"toggleNode(node, $any($event))\"\n [class.ax-tree-view-has-children]=\"shouldShowExpandToggle(node)\"\n [class.ax-tree-view-expanded]=\"node.expanded\"\n [disabled]=\"node.disabled || node.loading\"\n [style.visibility]=\"shouldShowExpandToggle(node) ? 'visible' : 'hidden'\"\n >\n @if (node.loading) {\n <ax-icon>\n <i class=\"fa-solid fa-spinner fa-spin ax-tree-view-loading-spinner\"></i>\n </ax-icon>\n } @else {\n <ax-icon>\n <i\n [class]=\"node.expanded ? directionExpandedIcon() : directionCollapsedIcon()\"\n class=\"ax-tree-view-toggle-icon\"\n ></i>\n </ax-icon>\n }\n </ax-button>\n\n @if (itemTemplate()) {\n <ng-container\n [ngTemplateOutlet]=\"itemTemplate()!\"\n [ngTemplateOutletContext]=\"getTemplateContext(node, level)\"\n ></ng-container>\n } @else {\n @if (shouldShowCheckbox()) {\n <ax-check-box\n class=\"ax-tree-view-checkbox\"\n [ngModel]=\"node.indeterminate ? null : node.selected || false\"\n [indeterminate]=\"node.indeterminate || false\"\n (onValueChanged)=\"toggleSelection(node, $event)\"\n ></ax-check-box>\n }\n @if (showIcons() && node.icon) {\n <i [class]=\"node.icon\" class=\"ax-tree-view-node-icon\"></i>\n }\n <span class=\"ax-tree-view-node-label\">{{ node.label }}</span>\n @if (showChildrenBadge() && (node.childrenCount || (node.children && node.children.length > 0))) {\n <ax-badge\n class=\"ax-tree-view-children-badge\"\n [text]=\"(node.childrenCount ?? node.children?.length ?? 0).toString()\"\n ></ax-badge>\n }\n }\n </div>\n </div>\n @if (node.expanded && node.children && node.children.length > 0) {\n <div class=\"ax-tree-view-children\" role=\"group\">\n <ng-container\n [ngTemplateOutlet]=\"childrenList\"\n [ngTemplateOutletContext]=\"{ children: node.children, parent: node, level: level + 1 }\"\n ></ng-container>\n </div>\n }\n }\n }\n </div>\n</ng-template>\n", styles: [".ax-tree-view{display:block;width:100%;--ax-comp-tree-view-indent-size: 12px;--ax-comp-tree-view-node-hover-bg: rgba(var(--ax-sys-color-on-lightest-surface), .04);--ax-comp-tree-view-node-selected-bg: rgba(var(--ax-sys-color-primary-500), .12);--ax-comp-tree-view-node-border-radius: 6px;--ax-comp-tree-view-node-margin: .25rem;--ax-comp-tree-view-line-color: rgba(var(--ax-sys-color-on-lightest-surface), .15);--ax-comp-tree-view-drag-preview-opacity: .9;--ax-comp-tree-view-drag-placeholder-bg: rgba(var(--ax-sys-color-on-lightest-surface), .02);--ax-comp-tree-view-drop-active-bg: rgba(var(--ax-sys-color-primary-500), .08);--ax-comp-tree-view-drop-active-outline: rgba(var(--ax-sys-color-primary-500), .3);--ax-comp-tree-view-content-padding: 0;--ax-comp-tree-view-content-gap: .5rem;--ax-comp-tree-view-drop-list-min-height: 2rem;--ax-comp-tree-view-drag-handle-padding: .25rem;--ax-comp-tree-view-expand-toggle-padding: .25rem;--ax-comp-tree-view-card-node-margin: .5rem;--ax-comp-tree-view-card-content-padding: 1rem;--ax-comp-tree-view-outline-offset: 2px;--ax-comp-tree-view-outline-offset-negative: -2px}.ax-tree-view-drop-list{min-height:var(--ax-comp-tree-view-drop-list-min-height)}.ax-tree-view-compact .ax-tree-view-node-content{padding:var(--ax-comp-tree-view-content-padding, .25rem .5rem);gap:var(--ax-comp-tree-view-content-gap, .375rem);font-size:.8125rem}.ax-tree-view-comfortable .ax-tree-view-node-content{padding:var(--ax-comp-tree-view-content-padding, .75rem .625rem);gap:var(--ax-comp-tree-view-content-gap, .625rem);font-size:.9375rem}.ax-tree-view-node{position:relative;margin:var(--ax-comp-tree-view-node-margin) 0;border-radius:var(--ax-comp-tree-view-node-border-radius);border:1px solid transparent;cursor:move}.ax-tree-view-node:hover:not(.ax-dragging){background:var(--ax-comp-tree-view-node-hover-bg)}.ax-tree-view-node.ax-tree-view-node-selected{background:var(--ax-comp-tree-view-node-selected-bg);border-color:currentColor}.ax-tree-view-node.ax-dragging{opacity:var(--ax-comp-tree-view-drag-placeholder-opacity);cursor:grabbing!important}.ax-tree-view-node.ax-drag-placeholder{background:var(--ax-comp-tree-view-drag-placeholder-bg)}.ax-drag-preview{opacity:var(--ax-comp-tree-view-drag-preview-opacity)!important;box-shadow:0 4px 12px rgba(var(--ax-sys-color-on-lightest-surface),.2)!important;cursor:grabbing!important;border:2px dashed currentColor!important}.ax-tree-view-node-content.ax-drop-list-sorting-active{background:var(--ax-comp-tree-view-drop-active-bg);border-radius:var(--ax-comp-tree-view-node-border-radius);outline:2px dashed var(--ax-comp-tree-view-drop-active-outline);outline-offset:var(--ax-comp-tree-view-outline-offset-negative)}.ax-tree-view-node-content{display:flex;align-items:center;gap:var(--ax-comp-tree-view-content-gap);padding:var(--ax-comp-tree-view-content-padding);cursor:pointer;-webkit-user-select:none;user-select:none;outline:none;border:1px solid transparent;border-radius:var(--ax-comp-tree-view-node-border-radius)}.ax-tree-view-node-content:focus{outline:none}.ax-tree-view-node-content:focus-visible{outline:2px solid rgba(var(--ax-sys-color-primary-500),.8);outline-offset:var(--ax-comp-tree-view-outline-offset);border-radius:var(--ax-comp-tree-view-node-border-radius)}.ax-tree-view-drag-handle{cursor:grab;opacity:.6;padding:var(--ax-comp-tree-view-drag-handle-padding)}.ax-tree-view-drag-handle:hover{opacity:1}.ax-tree-view-drag-handle:active{cursor:grabbing}.ax-tree-view-expand-toggle{background:none;border:none;cursor:pointer;padding:var(--ax-comp-tree-view-expand-toggle-padding);min-width:1.5rem;height:1.5rem}.ax-tree-view-expand-toggle:not(.ax-tree-view-has-children){opacity:0;pointer-events:none}.ax-tree-view-toggle-icon{font-size:.75rem}.ax-tree-view-node-icon{font-size:1.125rem;flex-shrink:0}.ax-tree-view-node-label{flex:1;font-size:.875rem;line-height:1rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ax-tree-view-children{padding-inline-start:var(--ax-tree-view-indent-size, var(--ax-comp-tree-view-indent-size))}.ax-tree-view-node-disabled{opacity:.5;cursor:not-allowed;pointer-events:none}.ax-tree-view-node-loading{opacity:.7}.ax-tree-view-card .ax-tree-view-node{border:1px solid rgba(var(--ax-sys-color-border-lightest-surface),1);margin:var(--ax-comp-tree-view-card-node-margin) 0}.ax-tree-view-card .ax-tree-view-node-content{padding:var(--ax-comp-tree-view-card-content-padding)}.ax-tree-view-with-lines .ax-tree-view-children{position:relative;padding-inline-start:var(--ax-tree-view-indent-size, var(--ax-comp-tree-view-indent-size))}.ax-tree-view-with-lines .ax-tree-view-children:before{content:\"\";position:absolute;inset-inline-start:var(--ax-tree-view-line-offset, calc(var(--ax-comp-tree-view-indent-size) / 2));top:0;height:calc(100% - .875rem);width:1px;background:var(--ax-tree-view-line-color, var(--ax-comp-tree-view-line-color))}.ax-tree-view-with-lines .ax-tree-view-node{position:relative}.ax-tree-view-with-lines .ax-tree-view-node:before{content:\"\";position:absolute;inset-inline-start:calc(-1 * var(--ax-tree-view-line-offset, calc(var(--ax-comp-tree-view-indent-size) / 2)));top:60%;width:var(--ax-tree-view-line-offset, calc(var(--ax-comp-tree-view-indent-size) / 2));height:1px;background:var(--ax-tree-view-line-color, var(--ax-comp-tree-view-line-color))}.ax-tree-view-with-lines>.ax-tree-view-drop-list>.ax-tree-view-node:before,.ax-tree-view-with-lines>.ax-tree-view-node:before{display:none}\n"] }]
1218
- }], propDecorators: { datasource: [{ type: i0.Input, args: [{ isSignal: true, alias: "datasource", required: true }] }, { type: i0.Output, args: ["datasourceChange"] }], selectMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectMode", required: false }] }], showCheckbox: [{ type: i0.Input, args: [{ isSignal: true, alias: "showCheckbox", required: false }] }], checkChildrenOnSelect: [{ type: i0.Input, args: [{ isSignal: true, alias: "checkChildrenOnSelect", required: false }] }], intermediateState: [{ type: i0.Input, args: [{ isSignal: true, alias: "intermediateState", required: false }] }], checkOnClick: [{ type: i0.Input, args: [{ isSignal: true, alias: "checkOnClick", required: false }] }], dragMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "dragMode", required: false }] }], dragOperationType: [{ type: i0.Input, args: [{ isSignal: true, alias: "dragOperationType", required: false }] }], showIcons: [{ type: i0.Input, args: [{ isSignal: true, alias: "showIcons", required: false }] }], showChildrenBadge: [{ type: i0.Input, args: [{ isSignal: true, alias: "showChildrenBadge", required: false }] }], expandedIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandedIcon", required: false }] }], collapsedIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapsedIcon", required: false }] }], indentSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "indentSize", required: false }] }], nodeHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "nodeHeight", required: false }] }], look: [{ type: i0.Input, args: [{ isSignal: true, alias: "look", required: false }] }], itemTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemTemplate", required: false }] }], onBeforeDrop: [{ type: i0.Output, args: ["onBeforeDrop"] }], onNodeToggle: [{ type: i0.Output, args: ["onNodeToggle"] }], onNodeSelect: [{ type: i0.Output, args: ["onNodeSelect"] }], onOrderChange: [{ type: i0.Output, args: ["onOrderChange"] }], onMoveChange: [{ type: i0.Output, args: ["onMoveChange"] }], onItemsChange: [{ type: i0.Output, args: ["onItemsChange"] }] } });
2102
+ }, template: "<!-- Root drop list -->\n<div\n axFocusTrap\n [axDropList]=\"dragMode() !== 'none'\"\n [sortingDisabled]=\"false\"\n [id]=\"getListId()\"\n [attr.data-node-id]=\"null\"\n dropListGroup=\"ax-tree-view-nodes\"\n (dropListDropped)=\"onDrop($event)\"\n class=\"ax-tree-view-drop-list\"\n [class.ax-tree-view-card]=\"look() === 'card'\"\n [class.ax-tree-view-with-lines]=\"look() === 'with-line'\"\n role=\"group\"\n>\n @for (node of nodes(); track getNodeId(node)) {\n @if (getNodeHidden(node) !== true) {\n <div\n [axDrag]=\"dragMode() !== 'none'\"\n [dragDisabled]=\"getNodeDisabled(node)\"\n [dragData]=\"node\"\n class=\"ax-tree-view-node\"\n [class.ax-tree-view-node-selected]=\"getNodeSelected(node)\"\n [class.ax-tree-view-node-disabled]=\"getNodeDisabled(node)\"\n [class.ax-tree-view-node-loading]=\"getNodeLoading(node)\"\n role=\"treeitem\"\n [attr.aria-level]=\"getNodeAriaLevel(0)\"\n [attr.aria-expanded]=\"getNodeAriaExpanded(node)\"\n [attr.aria-selected]=\"getNodeAriaSelected(node)\"\n [attr.aria-disabled]=\"getNodeDisabled(node) || (isLeafOnlyMode() && !isLeafNode(node)) ? 'true' : null\"\n >\n <div\n class=\"ax-tree-view-node-content\"\n [axDropList]=\"dragMode() !== 'none'\"\n [id]=\"'ax-tree-view-node-drop-' + getNodeId(node)\"\n [attr.data-node-id]=\"getNodeId(node)\"\n [attr.data-tree-node-id]=\"getNodeId(node)\"\n [attr.data-drop-type]=\"'onto-node'\"\n dropListGroup=\"ax-tree-view-nodes\"\n (dropListDropped)=\"onDropOntoNode($event, node)\"\n (click)=\"\n (selectMode() === 'single' || (selectMode() === 'multiple' && checkOnClick())) && onNodeClick(node, $event)\n \"\n (focus)=\"onNodeFocus(getNodeId(node))\"\n [tabindex]=\"isNodeFocused(getNodeId(node)) ? 0 : -1\"\n >\n @if (dragMode() === 'handler') {\n <span class=\"ax-tree-view-drag-handle\" axDragHandle title=\"Drag to reorder\"> \u22EE\u22EE </span>\n }\n <ax-button\n class=\"ax-tree-view-expand-toggle ax-sm\"\n (onClick)=\"toggleNode(node, $any($event))\"\n [class.ax-tree-view-has-children]=\"shouldShowExpandToggle(node)\"\n [class.ax-tree-view-expanded]=\"getNodeExpanded(node)\"\n [disabled]=\"getNodeDisabled(node) || getNodeLoading(node)\"\n [style.visibility]=\"shouldShowExpandToggle(node) ? 'visible' : 'hidden'\"\n >\n @if (getNodeLoading(node)) {\n <ax-icon>\n <i class=\"fa-solid fa-spinner fa-spin ax-tree-view-loading-spinner\"></i>\n </ax-icon>\n } @else {\n <ax-icon>\n <i\n [class]=\"getNodeExpanded(node) ? directionExpandedIcon() : directionCollapsedIcon()\"\n class=\"ax-tree-view-toggle-icon\"\n ></i>\n </ax-icon>\n }\n </ax-button>\n @if (nodeTemplate()) {\n <ng-container\n [ngTemplateOutlet]=\"nodeTemplate()!\"\n [ngTemplateOutletContext]=\"getTemplateContext(node, 0)\"\n ></ng-container>\n } @else {\n @if (shouldShowCheckboxForNode(node)) {\n <ax-check-box\n class=\"ax-tree-view-checkbox\"\n [ngModel]=\"getNodeIndeterminate(node) ? null : getNodeSelected(node) || false\"\n [indeterminate]=\"getNodeIndeterminate(node) || false\"\n (onValueChanged)=\"toggleSelection(node, $event)\"\n ></ax-check-box>\n }\n @if (showIcons() && getNodeIcon(node)) {\n <i [class]=\"getNodeIcon(node)\" class=\"ax-tree-view-node-icon\"></i>\n }\n <span\n class=\"ax-tree-view-node-label\"\n [axTooltip]=\"getNodeTooltip(node) || ''\"\n [axTooltipDisabled]=\"!getNodeTooltip(node)\"\n [axTooltipPlacement]=\"'top-start'\"\n >\n {{ getNodeTitle(node) }}\n </span>\n @if (\n showChildrenBadge() &&\n (getNodeChildrenCount(node) || (getNodeChildren(node) && getNodeChildren(node)!.length > 0))\n ) {\n <span class=\"ax-tree-view-node-badge\">\n <ax-badge\n class=\"ax-tree-view-children-badge\"\n [text]=\"(getNodeChildrenCount(node) ?? getNodeChildren(node)?.length ?? 0).toString()\"\n ></ax-badge>\n </span>\n }\n }\n </div>\n </div>\n @if (getNodeExpanded(node) && getNodeChildren(node) && getNodeChildren(node)!.length > 0) {\n <div class=\"ax-tree-view-children\" role=\"group\">\n <ng-container\n [ngTemplateOutlet]=\"childrenList\"\n [ngTemplateOutletContext]=\"{ children: getNodeChildren(node), parent: node, level: 1 }\"\n ></ng-container>\n </div>\n }\n }\n }\n</div>\n\n<!-- Recursive children template -->\n<ng-template #childrenList let-children=\"children\" let-parent=\"parent\" let-level=\"level\">\n <div\n [axDropList]=\"dragMode() !== 'none'\"\n [id]=\"getListId(parent)\"\n [attr.data-node-id]=\"getNodeId(parent)\"\n dropListGroup=\"ax-tree-view-nodes\"\n (dropListDropped)=\"onDrop($event, parent)\"\n class=\"ax-tree-view-drop-list\"\n role=\"group\"\n >\n @for (node of children; track getNodeId(node)) {\n @if (getNodeHidden(node) !== true) {\n <div\n [axDrag]=\"dragMode() !== 'none'\"\n [dragDisabled]=\"getNodeDisabled(node)\"\n [dragData]=\"node\"\n class=\"ax-tree-view-node\"\n [class.ax-tree-view-node-selected]=\"getNodeSelected(node)\"\n [class.ax-tree-view-node-disabled]=\"getNodeDisabled(node)\"\n [class.ax-tree-view-node-loading]=\"getNodeLoading(node)\"\n [class.ax-tree-view-node-focused]=\"isNodeFocused(getNodeId(node))\"\n role=\"treeitem\"\n [attr.aria-level]=\"getNodeAriaLevel(level)\"\n [attr.aria-expanded]=\"getNodeAriaExpanded(node)\"\n [attr.aria-selected]=\"getNodeAriaSelected(node)\"\n [attr.aria-disabled]=\"getNodeDisabled(node) ? 'true' : null\"\n >\n <div\n class=\"ax-tree-view-node-content\"\n [axDropList]=\"dragMode() !== 'none'\"\n [id]=\"'ax-tree-view-node-drop-' + getNodeId(node)\"\n [attr.data-node-id]=\"getNodeId(node)\"\n [attr.data-tree-node-id]=\"getNodeId(node)\"\n [attr.data-drop-type]=\"'onto-node'\"\n dropListGroup=\"ax-tree-view-nodes\"\n (dropListDropped)=\"onDropOntoNode($event, node)\"\n (click)=\"\n (selectMode() === 'single' || (selectMode() === 'multiple' && checkOnClick())) &&\n onNodeClick(node, $event)\n \"\n (focus)=\"onNodeFocus(getNodeId(node))\"\n (blur)=\"focusedNodeId.set(null)\"\n [tabindex]=\"isNodeFocused(getNodeId(node)) ? 0 : -1\"\n >\n @if (dragMode() === 'handler') {\n <span class=\"ax-tree-view-drag-handle\" axDragHandle title=\"Drag to reorder\"> \u22EE\u22EE </span>\n }\n <ax-button\n class=\"ax-tree-view-expand-toggle ax-sm\"\n (onClick)=\"toggleNode(node, $any($event))\"\n [class.ax-tree-view-has-children]=\"shouldShowExpandToggle(node)\"\n [class.ax-tree-view-expanded]=\"getNodeExpanded(node)\"\n [disabled]=\"getNodeDisabled(node) || getNodeLoading(node)\"\n [style.visibility]=\"shouldShowExpandToggle(node) ? 'visible' : 'hidden'\"\n >\n @if (getNodeLoading(node)) {\n <ax-icon>\n <i class=\"fa-solid fa-spinner fa-spin ax-tree-view-loading-spinner\"></i>\n </ax-icon>\n } @else {\n <ax-icon>\n <i\n [class]=\"getNodeExpanded(node) ? directionExpandedIcon() : directionCollapsedIcon()\"\n class=\"ax-tree-view-toggle-icon\"\n ></i>\n </ax-icon>\n }\n </ax-button>\n\n @if (nodeTemplate()) {\n <ng-container\n [ngTemplateOutlet]=\"nodeTemplate()!\"\n [ngTemplateOutletContext]=\"getTemplateContext(node, level)\"\n ></ng-container>\n } @else {\n @if (shouldShowCheckboxForNode(node)) {\n <ax-check-box\n class=\"ax-tree-view-checkbox\"\n [ngModel]=\"getNodeIndeterminate(node) ? null : getNodeSelected(node) || false\"\n [indeterminate]=\"getNodeIndeterminate(node) || false\"\n (onValueChanged)=\"toggleSelection(node, $event)\"\n ></ax-check-box>\n }\n @if (showIcons() && getNodeIcon(node)) {\n <i [class]=\"getNodeIcon(node)\" class=\"ax-tree-view-node-icon\"></i>\n }\n <span\n class=\"ax-tree-view-node-label\"\n [axTooltip]=\"getNodeTooltip(node) || ''\"\n [axTooltipDisabled]=\"!getNodeTooltip(node)\"\n [axTooltipPlacement]=\"'top-start'\"\n >\n {{ getNodeTitle(node) }}\n </span>\n @if (\n showChildrenBadge() &&\n (getNodeChildrenCount(node) || (getNodeChildren(node) && getNodeChildren(node)!.length > 0))\n ) {\n <span class=\"ax-tree-view-node-badge\">\n <ax-badge\n class=\"ax-tree-view-children-badge\"\n [text]=\"(getNodeChildrenCount(node) ?? getNodeChildren(node)?.length ?? 0).toString()\"\n ></ax-badge>\n </span>\n }\n }\n </div>\n </div>\n @if (getNodeExpanded(node) && getNodeChildren(node) && getNodeChildren(node)!.length > 0) {\n <div class=\"ax-tree-view-children\" role=\"group\">\n <ng-container\n [ngTemplateOutlet]=\"childrenList\"\n [ngTemplateOutletContext]=\"{ children: getNodeChildren(node), parent: node, level: level + 1 }\"\n ></ng-container>\n </div>\n }\n }\n }\n </div>\n</ng-template>\n", styles: [".ax-tree-view{display:block;width:100%;--ax-comp-tree-view-indent-size: 12px;--ax-comp-tree-view-node-hover-bg: rgba(var(--ax-sys-color-on-lightest-surface), .04);--ax-comp-tree-view-node-selected-bg: rgba(var(--ax-sys-color-primary-500), .12);--ax-comp-tree-view-node-border-radius: 6px;--ax-comp-tree-view-node-margin: .25rem;--ax-comp-tree-view-line-color: rgba(var(--ax-sys-color-on-lightest-surface), .15);--ax-comp-tree-view-drag-preview-opacity: .9;--ax-comp-tree-view-drag-placeholder-bg: rgba(var(--ax-sys-color-on-lightest-surface), .02);--ax-comp-tree-view-drop-active-bg: rgba(var(--ax-sys-color-primary-500), .08);--ax-comp-tree-view-drop-active-outline: rgba(var(--ax-sys-color-primary-500), .3);--ax-comp-tree-view-content-padding: 0;--ax-comp-tree-view-content-gap: .5rem;--ax-comp-tree-view-drop-list-min-height: 2rem;--ax-comp-tree-view-drag-handle-padding: .25rem;--ax-comp-tree-view-badge-padding: .25rem;--ax-comp-tree-view-expand-toggle-padding: .25rem;--ax-comp-tree-view-outline-offset: 2px;--ax-comp-tree-view-outline-offset-negative: -2px}.ax-tree-view-drop-list{min-height:var(--ax-comp-tree-view-drop-list-min-height)}.ax-tree-view-node{position:relative;margin:var(--ax-comp-tree-view-node-margin) 0;border-radius:var(--ax-comp-tree-view-node-border-radius);cursor:move}.ax-tree-view-node:hover:not(.ax-dragging){background:var(--ax-comp-tree-view-node-hover-bg)}.ax-tree-view-node.ax-tree-view-node-selected{background:var(--ax-comp-tree-view-node-selected-bg)}.ax-tree-view-node.ax-dragging{opacity:var(--ax-comp-tree-view-drag-placeholder-opacity);cursor:grabbing!important}.ax-tree-view-node.ax-drag-placeholder{background:var(--ax-comp-tree-view-drag-placeholder-bg)}.ax-drag-preview{opacity:var(--ax-comp-tree-view-drag-preview-opacity)!important;box-shadow:0 4px 12px rgba(var(--ax-sys-color-on-lightest-surface),.2)!important;cursor:grabbing!important;border:2px dashed currentColor!important}.ax-tree-view-node-content.ax-drop-list-sorting-active{background:var(--ax-comp-tree-view-drop-active-bg);border-radius:var(--ax-comp-tree-view-node-border-radius);outline:2px dashed var(--ax-comp-tree-view-drop-active-outline);outline-offset:var(--ax-comp-tree-view-outline-offset-negative)}.ax-tree-view-node-content{display:flex;align-items:center;gap:var(--ax-comp-tree-view-content-gap);padding:var(--ax-comp-tree-view-content-padding);cursor:pointer;-webkit-user-select:none;user-select:none;outline:none;border-radius:var(--ax-comp-tree-view-node-border-radius)}.ax-tree-view-node-content:focus{outline:none}.ax-tree-view-node-content:focus-visible{outline:2px solid rgba(var(--ax-sys-color-primary-500),.8);outline-offset:var(--ax-comp-tree-view-outline-offset);border-radius:var(--ax-comp-tree-view-node-border-radius)}.ax-tree-view-drag-handle{cursor:grab;opacity:.6;padding:var(--ax-comp-tree-view-drag-handle-padding);padding-inline-start:calc(var(--ax-comp-tree-view-drag-handle-padding) * 2)}.ax-tree-view-drag-handle:hover{opacity:1}.ax-tree-view-drag-handle:active{cursor:grabbing}.ax-tree-view-expand-toggle{background:none;border:none;cursor:pointer;padding:var(--ax-comp-tree-view-expand-toggle-padding);min-width:1.5rem;height:1.5rem}.ax-tree-view-expand-toggle:not(.ax-tree-view-has-children){opacity:0;pointer-events:none}.ax-tree-view-toggle-icon{font-size:.75rem}.ax-tree-view-node-icon{font-size:1.125rem;flex-shrink:0}.ax-tree-view-node-label{flex:1;font-size:.875rem;line-height:1rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ax-tree-view-node-badge{padding:var(--ax-comp-tree-view-badge-padding);padding-inline-end:calc(var(--ax-comp-tree-view-badge-padding) * 1.5)}.ax-tree-view-children{padding-inline-start:var(--ax-tree-view-indent-size, var(--ax-comp-tree-view-indent-size))}.ax-tree-view-node-disabled{opacity:.5;cursor:not-allowed;pointer-events:none}.ax-tree-view-node-loading{opacity:.7}.ax-tree-view-card .ax-tree-view-node{border:1px solid rgba(var(--ax-sys-color-border-lightest-surface),1)}.ax-tree-view-card .ax-tree-view-node.ax-tree-view-node-selected{border:1px solid rgba(var(--ax-sys-color-border-surface),1)}.ax-tree-view-with-lines .ax-tree-view-children{position:relative;padding-inline-start:var(--ax-tree-view-indent-size, var(--ax-comp-tree-view-indent-size))}.ax-tree-view-with-lines .ax-tree-view-children:before{content:\"\";position:absolute;inset-inline-start:var(--ax-tree-view-line-offset, calc(var(--ax-comp-tree-view-indent-size) / 2));top:0;height:calc(100% - .875rem);width:1px;background:var(--ax-tree-view-line-color, var(--ax-comp-tree-view-line-color))}.ax-tree-view-with-lines .ax-tree-view-node{position:relative}.ax-tree-view-with-lines .ax-tree-view-node:before{content:\"\";position:absolute;inset-inline-start:calc(-1 * var(--ax-tree-view-line-offset, calc(var(--ax-comp-tree-view-indent-size) / 2)));top:60%;width:var(--ax-tree-view-line-offset, calc(var(--ax-comp-tree-view-indent-size) / 2));height:1px;background:var(--ax-tree-view-line-color, var(--ax-comp-tree-view-line-color))}.ax-tree-view-with-lines>.ax-tree-view-drop-list>.ax-tree-view-node:before,.ax-tree-view-with-lines>.ax-tree-view-node:before{display:none}\n"] }]
2103
+ }], propDecorators: { datasource: [{ type: i0.Input, args: [{ isSignal: true, alias: "datasource", required: true }] }, { type: i0.Output, args: ["datasourceChange"] }], selectMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectMode", required: false }] }], showCheckbox: [{ type: i0.Input, args: [{ isSignal: true, alias: "showCheckbox", required: false }] }], selectionBehavior: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectionBehavior", required: false }] }], checkOnClick: [{ type: i0.Input, args: [{ isSignal: true, alias: "checkOnClick", required: false }] }], dragMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "dragMode", required: false }] }], dragOperationType: [{ type: i0.Input, args: [{ isSignal: true, alias: "dragOperationType", required: false }] }], showIcons: [{ type: i0.Input, args: [{ isSignal: true, alias: "showIcons", required: false }] }], showChildrenBadge: [{ type: i0.Input, args: [{ isSignal: true, alias: "showChildrenBadge", required: false }] }], expandedIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandedIcon", required: false }] }], collapsedIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapsedIcon", required: false }] }], indentSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "indentSize", required: false }] }], look: [{ type: i0.Input, args: [{ isSignal: true, alias: "look", required: false }] }], nodeTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "nodeTemplate", required: false }] }], idField: [{ type: i0.Input, args: [{ isSignal: true, alias: "idField", required: false }] }], titleField: [{ type: i0.Input, args: [{ isSignal: true, alias: "titleField", required: false }] }], tooltipField: [{ type: i0.Input, args: [{ isSignal: true, alias: "tooltipField", required: false }] }], iconField: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconField", required: false }] }], expandedField: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandedField", required: false }] }], selectedField: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedField", required: false }] }], indeterminateField: [{ type: i0.Input, args: [{ isSignal: true, alias: "indeterminateField", required: false }] }], disabledField: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabledField", required: false }] }], hiddenField: [{ type: i0.Input, args: [{ isSignal: true, alias: "hiddenField", required: false }] }], childrenField: [{ type: i0.Input, args: [{ isSignal: true, alias: "childrenField", required: false }] }], childrenCountField: [{ type: i0.Input, args: [{ isSignal: true, alias: "childrenCountField", required: false }] }], dataField: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataField", required: false }] }], onBeforeDrop: [{ type: i0.Output, args: ["onBeforeDrop"] }], onNodeToggle: [{ type: i0.Output, args: ["onNodeToggle"] }], onNodeSelect: [{ type: i0.Output, args: ["onNodeSelect"] }], onSelectionChange: [{ type: i0.Output, args: ["onSelectionChange"] }], onOrderChange: [{ type: i0.Output, args: ["onOrderChange"] }], onMoveChange: [{ type: i0.Output, args: ["onMoveChange"] }], onItemsChange: [{ type: i0.Output, args: ["onItemsChange"] }] } });
1219
2104
 
1220
2105
  class AXTreeViewModule {
1221
2106
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: AXTreeViewModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }