@igo2/common 20.1.0-next.2 → 20.1.0-next.21

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.
Files changed (76) hide show
  1. package/badge/index.d.ts +1 -1
  2. package/drag-drop/index.d.ts +48 -35
  3. package/entity/index.d.ts +90 -24
  4. package/fesm2022/igo2-common-action.mjs +26 -34
  5. package/fesm2022/igo2-common-action.mjs.map +1 -1
  6. package/fesm2022/igo2-common-backdrop.mjs +7 -7
  7. package/fesm2022/igo2-common-backdrop.mjs.map +1 -1
  8. package/fesm2022/igo2-common-badge.mjs +7 -7
  9. package/fesm2022/igo2-common-badge.mjs.map +1 -1
  10. package/fesm2022/igo2-common-clickout.mjs +7 -7
  11. package/fesm2022/igo2-common-clickout.mjs.map +1 -1
  12. package/fesm2022/igo2-common-clone.mjs +7 -7
  13. package/fesm2022/igo2-common-clone.mjs.map +1 -1
  14. package/fesm2022/igo2-common-collapsible.mjs +10 -10
  15. package/fesm2022/igo2-common-collapsible.mjs.map +1 -1
  16. package/fesm2022/igo2-common-color.mjs +7 -7
  17. package/fesm2022/igo2-common-color.mjs.map +1 -1
  18. package/fesm2022/igo2-common-confirm-dialog.mjs +10 -10
  19. package/fesm2022/igo2-common-confirm-dialog.mjs.map +1 -1
  20. package/fesm2022/igo2-common-context-menu.mjs +10 -10
  21. package/fesm2022/igo2-common-context-menu.mjs.map +1 -1
  22. package/fesm2022/igo2-common-custom-html.mjs +10 -10
  23. package/fesm2022/igo2-common-custom-html.mjs.map +1 -1
  24. package/fesm2022/igo2-common-datepicker.mjs +3 -3
  25. package/fesm2022/igo2-common-datepicker.mjs.map +1 -1
  26. package/fesm2022/igo2-common-dom.mjs +7 -7
  27. package/fesm2022/igo2-common-dom.mjs.map +1 -1
  28. package/fesm2022/igo2-common-drag-drop.mjs +242 -126
  29. package/fesm2022/igo2-common-drag-drop.mjs.map +1 -1
  30. package/fesm2022/igo2-common-dynamic-component.mjs +14 -14
  31. package/fesm2022/igo2-common-dynamic-component.mjs.map +1 -1
  32. package/fesm2022/igo2-common-entity.mjs +159 -43
  33. package/fesm2022/igo2-common-entity.mjs.map +1 -1
  34. package/fesm2022/igo2-common-flexible.mjs +7 -7
  35. package/fesm2022/igo2-common-flexible.mjs.map +1 -1
  36. package/fesm2022/igo2-common-form.mjs +50 -50
  37. package/fesm2022/igo2-common-form.mjs.map +1 -1
  38. package/fesm2022/igo2-common-home-button.mjs +7 -7
  39. package/fesm2022/igo2-common-home-button.mjs.map +1 -1
  40. package/fesm2022/igo2-common-icon.mjs +7 -19
  41. package/fesm2022/igo2-common-icon.mjs.map +1 -1
  42. package/fesm2022/igo2-common-image.mjs +11 -11
  43. package/fesm2022/igo2-common-image.mjs.map +1 -1
  44. package/fesm2022/igo2-common-interactive-tour.mjs +13 -13
  45. package/fesm2022/igo2-common-interactive-tour.mjs.map +1 -1
  46. package/fesm2022/igo2-common-json-dialog.mjs +10 -10
  47. package/fesm2022/igo2-common-json-dialog.mjs.map +1 -1
  48. package/fesm2022/igo2-common-keyvalue.mjs +7 -7
  49. package/fesm2022/igo2-common-keyvalue.mjs.map +1 -1
  50. package/fesm2022/igo2-common-list.mjs +11 -11
  51. package/fesm2022/igo2-common-list.mjs.map +1 -1
  52. package/fesm2022/igo2-common-panel.mjs +8 -8
  53. package/fesm2022/igo2-common-panel.mjs.map +1 -1
  54. package/fesm2022/igo2-common-resizable-bar.mjs +6 -6
  55. package/fesm2022/igo2-common-resizable-bar.mjs.map +1 -1
  56. package/fesm2022/igo2-common-select-value-dialog.mjs +10 -10
  57. package/fesm2022/igo2-common-select-value-dialog.mjs.map +1 -1
  58. package/fesm2022/igo2-common-sidenav.mjs +7 -7
  59. package/fesm2022/igo2-common-sidenav.mjs.map +1 -1
  60. package/fesm2022/igo2-common-spinner.mjs +10 -10
  61. package/fesm2022/igo2-common-spinner.mjs.map +1 -1
  62. package/fesm2022/igo2-common-stop-propagation.mjs +10 -10
  63. package/fesm2022/igo2-common-stop-propagation.mjs.map +1 -1
  64. package/fesm2022/igo2-common-table.mjs +7 -7
  65. package/fesm2022/igo2-common-table.mjs.map +1 -1
  66. package/fesm2022/igo2-common-timepicker.mjs +3 -3
  67. package/fesm2022/igo2-common-timepicker.mjs.map +1 -1
  68. package/fesm2022/igo2-common-tool.mjs +15 -15
  69. package/fesm2022/igo2-common-tool.mjs.map +1 -1
  70. package/fesm2022/igo2-common-widget.mjs +14 -14
  71. package/fesm2022/igo2-common-widget.mjs.map +1 -1
  72. package/fesm2022/igo2-common-workspace.mjs +18 -18
  73. package/fesm2022/igo2-common-workspace.mjs.map +1 -1
  74. package/icon/index.d.ts +1 -3
  75. package/package.json +5 -4
  76. package/src/style/partial/common.variables.scss +0 -1
@@ -1,6 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { input, output, HostListener, HostBinding, Directive, inject, ElementRef, Renderer2, effect, booleanAttribute, contentChildren, NgModule } from '@angular/core';
3
- import { SelectionModel } from '@angular/cdk/collections';
2
+ import { input, output, HostListener, HostBinding, Directive, inject, ElementRef, Renderer2, signal, effect, booleanAttribute, contentChildren, untracked, NgModule } from '@angular/core';
4
3
  import { MatTreeNode } from '@angular/material/tree';
5
4
 
6
5
  class DragAndDropDirective {
@@ -55,10 +54,10 @@ class DragAndDropDirective {
55
54
  }
56
55
  return filesObj;
57
56
  }
58
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.6", ngImport: i0, type: DragAndDropDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
59
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.3.6", type: DragAndDropDirective, isStandalone: true, selector: "[igoDragAndDrop]", inputs: { allowedExtensions: { classPropertyName: "allowedExtensions", publicName: "allowedExtensions", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { filesDropped: "filesDropped", filesInvalid: "filesInvalid" }, host: { listeners: { "dragover": "onDragOver($event)", "dragleave": "onDragLeave($event)", "drop": "onDrop($event)" }, properties: { "style.background": "this.background" } }, ngImport: i0 });
57
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: DragAndDropDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
58
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.3.18", type: DragAndDropDirective, isStandalone: true, selector: "[igoDragAndDrop]", inputs: { allowedExtensions: { classPropertyName: "allowedExtensions", publicName: "allowedExtensions", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { filesDropped: "filesDropped", filesInvalid: "filesInvalid" }, host: { listeners: { "dragover": "onDragOver($event)", "dragleave": "onDragLeave($event)", "drop": "onDrop($event)" }, properties: { "style.background": "this.background" } }, ngImport: i0 });
60
59
  }
61
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.6", ngImport: i0, type: DragAndDropDirective, decorators: [{
60
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: DragAndDropDirective, decorators: [{
62
61
  type: Directive,
63
62
  args: [{
64
63
  selector: '[igoDragAndDrop]',
@@ -89,65 +88,112 @@ class TreeDragDropDirective {
89
88
  elementRef = inject(ElementRef);
90
89
  renderer = inject(Renderer2);
91
90
  draggedNode;
92
- dropNodeTarget;
91
+ dropNodeTarget = signal(null, ...(ngDevMode ? [{ debugName: "dropNodeTarget" }] : []));
93
92
  expandTimeout;
94
93
  nodesListeners;
95
94
  nodesEffect = effect(() => {
96
95
  this.nodes();
97
96
  this.addAllListener();
98
97
  }, ...(ngDevMode ? [{ debugName: "nodesEffect" }] : []));
99
- dropLineTarget;
100
- highlightedNode = new SelectionModel();
101
- treeControl = input.required(...(ngDevMode ? [{ debugName: "treeControl" }] : []));
98
+ dropLineTarget = signal(null, ...(ngDevMode ? [{ debugName: "dropLineTarget" }] : []));
99
+ previousDropLine = signal(null, ...(ngDevMode ? [{ debugName: "previousDropLine" }] : []));
100
+ dropPosition = signal(null, ...(ngDevMode ? [{ debugName: "dropPosition" }] : []));
101
+ dragging = signal(false, ...(ngDevMode ? [{ debugName: "dragging" }] : []));
102
+ // Use a Set or just manage classes manually since SelectionModel was providing simple toggle
103
+ // But we can stick to simple class logic
104
+ highlightedNode;
105
+ tree = input.required(...(ngDevMode ? [{ debugName: "tree" }] : []));
106
+ childrenAccessor = input.required(...(ngDevMode ? [{ debugName: "childrenAccessor" }] : []));
107
+ config = input.required(...(ngDevMode ? [{ debugName: "config" }] : []));
102
108
  /** The default is 5 */
103
109
  maxLevel = input(5, ...(ngDevMode ? [{ debugName: "maxLevel" }] : []));
104
110
  treeDragDropIsDisabled = input(false, ...(ngDevMode ? [{ debugName: "treeDragDropIsDisabled", transform: booleanAttribute }] : [{
105
111
  transform: booleanAttribute
106
112
  }]));
107
113
  dragStart = output();
108
- // eslint-disable-next-line @angular-eslint/no-output-on-prefix
109
- onDrop = output();
110
- // eslint-disable-next-line @angular-eslint/no-output-on-prefix
111
- onDropError = output();
112
- hostDragOver(event) {
113
- event.preventDefault();
114
- }
115
- hostDrop(event) {
116
- this.drop(event);
117
- }
118
- dragging;
114
+ dropped = output();
115
+ droppedError = output();
119
116
  nodes = contentChildren(MatTreeNode, ...(ngDevMode ? [{ debugName: "nodes", descendants: true }] : [{ descendants: true }]));
120
117
  constructor() {
121
- this.onDrop.subscribe(() => this.dragEnd());
122
- this.highlightedNode.changed.subscribe((change) => {
123
- if (change.removed.length) {
124
- this.removeNodeClass(change.removed[0].id, '--drag-hover');
118
+ this.dropped.subscribe(() => this.dragEnd());
119
+ effect(() => {
120
+ const disabled = this.treeDragDropIsDisabled();
121
+ disabled ? this.removeAllListener() : this.addAllListener();
122
+ });
123
+ effect(() => {
124
+ const current = this.dropLineTarget();
125
+ const parent = this.elementRef.nativeElement.parentElement;
126
+ if (!current) {
127
+ untracked(() => {
128
+ const previous = this.previousDropLine();
129
+ if (previous !== null) {
130
+ this.renderer.removeChild(parent, previous);
131
+ this.previousDropLine.set(null);
132
+ }
133
+ });
125
134
  }
126
- if (change.added.length) {
127
- this.addNodeClass(change.added[0].id, '--drag-hover');
135
+ else {
136
+ this.renderer.appendChild(parent, current);
128
137
  }
129
138
  });
130
139
  effect(() => {
131
- const disabled = this.treeDragDropIsDisabled();
132
- disabled ? this.removeAllListener() : this.addAllListener();
140
+ if (!this.dragging()) {
141
+ return;
142
+ }
143
+ const targetNode = this.dropNodeTarget();
144
+ const position = this.dropPosition();
145
+ const dropLineTarget = this.dropLineTarget();
146
+ if (targetNode) {
147
+ this.setHighlightedNode(targetNode);
148
+ if (position) {
149
+ if (dropLineTarget) {
150
+ this.updateDropTargetLinePosition(position, dropLineTarget);
151
+ }
152
+ this.handleGroupExpansion(targetNode, position.type === 'inside');
153
+ }
154
+ }
133
155
  });
134
156
  }
157
+ get isGroup() {
158
+ return this.config().isGroup;
159
+ }
160
+ get getDescendantLevels() {
161
+ return this.config().descendantLevels;
162
+ }
135
163
  ngOnDestroy() {
136
164
  this.removeAllListener();
165
+ this.removeDropTargetLine();
137
166
  if (this.nodesEffect) {
138
- // EffectRef provides destroy() to stop the effect
139
167
  this.nodesEffect.destroy();
140
168
  this.nodesEffect = undefined;
141
169
  }
142
170
  }
171
+ hostDragOver(event) {
172
+ event.preventDefault();
173
+ }
174
+ hostDragLeave(event) {
175
+ const rect = this.elementRef.nativeElement.getBoundingClientRect();
176
+ if (event.clientY < rect.top ||
177
+ event.clientY >= rect.bottom ||
178
+ event.clientX < rect.left ||
179
+ event.clientX >= rect.right) {
180
+ this.dragLeave();
181
+ }
182
+ }
183
+ hostDrop(event) {
184
+ this.drop(event);
185
+ }
143
186
  onDragStart(node) {
144
- this.dragging = true;
187
+ this.addDropTargetLine();
188
+ this.dragging.set(true);
145
189
  this.draggedNode = node;
146
190
  this.addNodeClass(node.id, '--dragged');
147
191
  this.dragStart.emit(node);
148
192
  }
149
193
  dragEnd() {
150
- this.dragging = false;
194
+ this.dragging.set(false);
195
+ this.dropNodeTarget.set(null);
196
+ this.dropPosition.set(null);
151
197
  if (this.draggedNode) {
152
198
  this.removeNodeClass(this.draggedNode.id, '--dragged');
153
199
  this.draggedNode = null;
@@ -158,71 +204,81 @@ class TreeDragDropDirective {
158
204
  dragOver(node, event) {
159
205
  event.preventDefault();
160
206
  event.stopPropagation();
161
- this.dropNodeTarget = node;
207
+ this.dropNodeTarget.set(node);
162
208
  const position = this.getPosition(event, node);
163
- this.updateDropTargetLinePosition(position);
164
- this.setHighlightedNode(node);
165
- this.handleGroupExpansion(node, position.type === 'inside');
209
+ this.dropPosition.set(position);
166
210
  }
167
211
  dragLeave() {
168
212
  clearTimeout(this.expandTimeout);
169
213
  this.expandTimeout = null;
170
- this.highlightedNode.clear();
214
+ if (this.highlightedNode) {
215
+ this.removeNodeClass(this.highlightedNode.id, '--drag-hover');
216
+ this.highlightedNode = undefined;
217
+ }
171
218
  }
172
219
  drop(event) {
173
- if (!this.dropNodeTarget || this.treeDragDropIsDisabled()) {
220
+ let nodeTarget = this.dropNodeTarget();
221
+ if (!nodeTarget || this.treeDragDropIsDisabled()) {
174
222
  return;
175
223
  }
176
- const dropPosition = this.getPosition(event, this.dropNodeTarget);
177
- const validation = this.canDropNode(this.dropNodeTarget, dropPosition);
224
+ const dropPosition = this.getPosition(event, nodeTarget);
225
+ const validation = this.canDropNode(nodeTarget, dropPosition);
178
226
  if (!validation.canDrop) {
179
- this.onDropError.emit(validation);
227
+ this.droppedError.emit(validation);
180
228
  return;
181
229
  }
230
+ let targetNodeLevel = this.getNodeLevel(nodeTarget);
182
231
  // Allow to drop a last child outside is group. We refer to it's ancestor for the target
183
232
  if (dropPosition.type === 'below' &&
184
- dropPosition.level !== this.dropNodeTarget.level) {
185
- this.dropNodeTarget = this.getNodeAncestors(this.dropNodeTarget.id, dropPosition.level);
233
+ dropPosition.level !== targetNodeLevel) {
234
+ const ancestor = this.getNodeAncestors(nodeTarget.id, dropPosition.level);
235
+ this.dropNodeTarget.set(ancestor);
236
+ nodeTarget = ancestor;
237
+ targetNodeLevel = this.getNodeLevel(nodeTarget);
186
238
  }
187
- if (this.dropNodeTarget.isGroup) {
239
+ if (this.isGroup(nodeTarget)) {
188
240
  if (dropPosition.type === 'inside') {
189
- const isExpanded = this.treeControl().isExpanded(this.dropNodeTarget);
241
+ const isExpanded = this.tree().isExpanded(nodeTarget);
190
242
  if (isExpanded) {
191
- const children = this.getDirectDescendants(this.dropNodeTarget);
243
+ const children = this.getDirectDescendants(nodeTarget);
192
244
  if (children[0]?.id === this.draggedNode.id) {
193
245
  return;
194
246
  }
195
247
  }
196
- this.treeControl().expand(this.dropNodeTarget);
197
- return this.onDrop.emit({
248
+ this.tree().expand(nodeTarget);
249
+ return this.dropped.emit({
198
250
  node: this.draggedNode,
199
- ref: this.dropNodeTarget,
251
+ ref: nodeTarget,
200
252
  position: dropPosition.type
201
253
  });
202
254
  }
203
255
  }
204
256
  if (dropPosition.type === 'below' &&
205
- dropPosition.level !== this.dropNodeTarget.level) {
206
- const ancestor = this.getNodeAncestors(this.dropNodeTarget.id);
207
- return this.onDrop.emit({
257
+ dropPosition.level !== targetNodeLevel) {
258
+ const ancestor = this.getNodeAncestors(nodeTarget.id);
259
+ return this.dropped.emit({
208
260
  node: this.draggedNode,
209
261
  ref: ancestor,
210
262
  position: dropPosition.type
211
263
  });
212
264
  }
213
- this.onDrop.emit({
265
+ this.dropped.emit({
214
266
  node: this.draggedNode,
215
- ref: this.dropNodeTarget,
267
+ ref: nodeTarget,
216
268
  position: dropPosition.type
217
269
  });
218
270
  }
219
271
  addNodeClass(id, className) {
220
- const node = this.nodes().find((node) => node.data.id === id);
221
- this.renderer.addClass(node['_elementRef'].nativeElement, className);
272
+ const node = this.findTreeNode(id);
273
+ if (node) {
274
+ this.renderer.addClass(node['_elementRef'].nativeElement, className);
275
+ }
222
276
  }
223
277
  removeNodeClass(id, className) {
224
- const node = this.nodes().find((node) => node.data.id === id);
225
- this.renderer.removeClass(node['_elementRef'].nativeElement, className);
278
+ const node = this.findTreeNode(id);
279
+ if (node) {
280
+ this.renderer.removeClass(node['_elementRef'].nativeElement, className);
281
+ }
226
282
  }
227
283
  addAllListener() {
228
284
  if (this.treeDragDropIsDisabled()) {
@@ -256,52 +312,70 @@ class TreeDragDropDirective {
256
312
  this.nodesListeners = null;
257
313
  }
258
314
  setHighlightedNode(node) {
259
- const toHighlight = node.isGroup ? node : this.getNodeAncestors(node.id);
260
- toHighlight
261
- ? this.highlightedNode.select(toHighlight)
262
- : this.highlightedNode.clear();
315
+ const toHighlight = this.isGroup(node)
316
+ ? node
317
+ : this.getNodeAncestors(node.id);
318
+ if (this.highlightedNode && this.highlightedNode.id !== toHighlight?.id) {
319
+ this.removeNodeClass(this.highlightedNode.id, '--drag-hover');
320
+ this.highlightedNode = undefined;
321
+ }
322
+ if (toHighlight) {
323
+ this.highlightedNode = toHighlight;
324
+ this.addNodeClass(toHighlight.id, '--drag-hover');
325
+ }
326
+ else if (this.highlightedNode) {
327
+ this.removeNodeClass(this.highlightedNode.id, '--drag-hover');
328
+ this.highlightedNode = undefined;
329
+ }
263
330
  }
264
331
  addDropTargetLine() {
265
332
  const target = this.renderer.createElement('div');
266
333
  target.classList.add('drop-target-line');
267
334
  target.setAttribute('style', `position: absolute; top: 0; width: 100%; pointer-events: none; z-index: 4; height: 2px; background-color: black; transition: margin-left 150ms;`);
268
- this.dropLineTarget = target;
269
- this.renderer.appendChild(this.elementRef.nativeElement.parentElement, this.dropLineTarget);
335
+ this.dropLineTarget.set(target);
270
336
  }
271
337
  removeDropTargetLine() {
272
- if (!this.dropLineTarget) {
273
- return;
338
+ const target = this.dropLineTarget();
339
+ if (target) {
340
+ this.previousDropLine.set(target);
341
+ this.dropLineTarget.set(null);
274
342
  }
275
- this.renderer.removeChild(this.elementRef.nativeElement.parentElement, this.dropLineTarget);
276
- this.dropLineTarget = null;
277
343
  }
278
- updateDropTargetLinePosition(position) {
279
- if (!this.dropLineTarget) {
280
- this.addDropTargetLine();
281
- }
344
+ hideDropTargetLine() {
345
+ const target = this.dropLineTarget();
346
+ this.renderer.setStyle(target, 'display', 'none');
347
+ }
348
+ showDropTargetLine() {
349
+ const target = this.dropLineTarget();
350
+ this.renderer.setStyle(target, 'display', 'block');
351
+ }
352
+ updateDropTargetLinePosition(position, dropLineTarget) {
282
353
  if (position.type === 'inside') {
283
- return this.removeDropTargetLine();
354
+ return this.hideDropTargetLine();
284
355
  }
285
- this.renderer.setStyle(this.dropLineTarget, 'margin-left', position.level * 24 + 20 + 'px');
286
- this.renderer.setStyle(this.dropLineTarget, 'transform', 'translate3d(0,' + position.y + 'px, 0)');
356
+ else {
357
+ this.showDropTargetLine();
358
+ }
359
+ this.renderer.setStyle(dropLineTarget, 'margin-left', position.level * 24 + 20 + 'px');
360
+ this.renderer.setStyle(dropLineTarget, 'transform', 'translate3d(0,' + position.y + 'px, 0)');
287
361
  }
288
362
  handleGroupExpansion(node, isInside) {
289
363
  if (!isInside) {
290
364
  return this.dragLeave();
291
365
  }
292
- const isOpen = this.treeControl().isExpanded(node);
366
+ const isOpen = this.tree().isExpanded(node);
293
367
  if (!isOpen && !this.expandTimeout) {
294
368
  this.expandTimeout = window.setTimeout(() => {
295
- this.treeControl().expand(node);
369
+ this.tree().expand(node);
296
370
  }, 1200);
297
371
  }
298
372
  }
299
373
  getNodeElement(node) {
300
- const treeNode = this.nodes().find((n) => n.data.id === node.id);
374
+ const treeNode = this.findTreeNode(node.id);
301
375
  return treeNode?.['_elementRef'].nativeElement;
302
376
  }
303
377
  canDropNode(hoveredNode, position) {
304
- if (this.draggedNode.isGroup) {
378
+ if (this.isGroup(this.draggedNode)) {
305
379
  return this.canDropGroup(hoveredNode, position);
306
380
  }
307
381
  const hasMaxLevelRestrictions = this.validateMaxHierarchyLevel(position);
@@ -318,14 +392,20 @@ class TreeDragDropDirective {
318
392
  message: 'igo.common.dragDrop.cannot.dropInsideItself'
319
393
  };
320
394
  }
395
+ const isHoverDescendant = this.isHoverDescendant(hoveredNode.id, hoveredNode);
396
+ if (isHoverDescendant) {
397
+ return {
398
+ canDrop: !isHoverDescendant,
399
+ message: 'igo.common.dragDrop.cannot.dropInsideItself'
400
+ };
401
+ }
321
402
  const hasMaxLevelRestrictions = this.validateMaxHierarchyLevel(position);
322
403
  if (hasMaxLevelRestrictions) {
323
404
  return hasMaxLevelRestrictions;
324
405
  }
325
- const isHoverDescendant = this.isHoverDescendant(hoveredNode.id);
326
406
  return {
327
- canDrop: !isHoverDescendant,
328
- message: isHoverDescendant && 'igo.common.dragDrop.cannot.dropInsideItself'
407
+ canDrop: true,
408
+ message: undefined
329
409
  };
330
410
  }
331
411
  validateMaxHierarchyLevel(position) {
@@ -334,9 +414,9 @@ class TreeDragDropDirective {
334
414
  return;
335
415
  }
336
416
  let level = position.type === 'inside' ? position.level + 1 : position.level;
337
- if (this.draggedNode.isGroup) {
417
+ if (this.isGroup(this.draggedNode)) {
338
418
  // We add an extra level +1 to avoid empty group in group
339
- level = level + (this.draggedNode.descendantLevels ?? 0) + 1;
419
+ level = level + +(this.getDescendantLevels(this.draggedNode) ?? 0) + 1;
340
420
  }
341
421
  if (level > maxLevel) {
342
422
  return {
@@ -346,21 +426,27 @@ class TreeDragDropDirective {
346
426
  };
347
427
  }
348
428
  }
349
- isHoverDescendant(id) {
350
- return this.treeControl()
351
- .getDescendants(this.draggedNode)
352
- .some((child) => child.id === id);
429
+ getDescendants(node) {
430
+ const children = this.childrenAccessor()(node) ?? [];
431
+ const descendants = [...children];
432
+ children.forEach((child) => {
433
+ descendants.push(...this.getDescendants(child));
434
+ });
435
+ return descendants;
436
+ }
437
+ isHoverDescendant(id, _hoveredNode) {
438
+ return this.getDescendants(this.draggedNode).some((child) => child.id === id);
353
439
  }
354
440
  getPosition(event, hoveredNode) {
355
- if (this.draggedNode.isGroup) {
356
- if (this.isHoverDescendant(hoveredNode.id)) {
441
+ if (this.isGroup(this.draggedNode)) {
442
+ if (this.isHoverDescendant(hoveredNode.id, hoveredNode)) {
357
443
  hoveredNode = this.draggedNode;
358
444
  }
359
445
  }
360
446
  let positionType = this.getPositionType(event, hoveredNode);
361
- const bellowOpenedGroup = hoveredNode.isGroup &&
447
+ const bellowOpenedGroup = this.isGroup(hoveredNode) &&
362
448
  positionType === 'below' &&
363
- this.treeControl().isExpanded(hoveredNode);
449
+ this.tree().isExpanded(hoveredNode);
364
450
  if (bellowOpenedGroup) {
365
451
  positionType = 'inside';
366
452
  }
@@ -384,7 +470,7 @@ class TreeDragDropDirective {
384
470
  const middle = rect.top + rect.height / 2;
385
471
  const y = event.y;
386
472
  const selfReferencing = this.draggedNode.id === hoveredNode.id;
387
- if (hoveredNode.isGroup && !selfReferencing) {
473
+ if (this.isGroup(hoveredNode) && !selfReferencing) {
388
474
  const tolerence = 5;
389
475
  if (y <= middle + tolerence && y >= middle - tolerence) {
390
476
  return 'inside';
@@ -394,63 +480,93 @@ class TreeDragDropDirective {
394
480
  return isBelow ? 'below' : 'above';
395
481
  }
396
482
  getPositionLevel(hoveredNode, type, x) {
397
- if (hoveredNode.level === 0) {
483
+ const hoveredNodeLevel = this.getNodeLevel(hoveredNode);
484
+ if (hoveredNodeLevel === 0) {
398
485
  return 0;
399
486
  }
400
487
  const ancestor = this.getNodeAncestors(hoveredNode.id);
488
+ if (!ancestor)
489
+ return hoveredNodeLevel;
401
490
  const children = this.getDirectDescendants(ancestor);
402
491
  const lastChild = [...children].pop();
403
- if (type === 'below' && lastChild.id === hoveredNode.id) {
492
+ if (type === 'below' && lastChild?.id === hoveredNode.id) {
404
493
  const target = this.getNodeElement(hoveredNode);
405
494
  const rect = target.getBoundingClientRect();
406
495
  const indentation = 24;
407
496
  const xMin = rect.x + indentation;
408
- const xMax = xMin + indentation * hoveredNode.level;
497
+ const xMax = xMin + indentation * hoveredNodeLevel;
409
498
  const isInsideSameGroup = x > xMax;
410
499
  if (!isInsideSameGroup) {
411
500
  const levelSubstracted = Math.round((xMax - x) / indentation);
412
- return Math.max(0, hoveredNode.level - levelSubstracted);
501
+ return Math.max(0, hoveredNodeLevel - levelSubstracted);
413
502
  }
414
503
  }
415
- return hoveredNode.level;
504
+ return hoveredNodeLevel;
416
505
  }
417
506
  /**
418
507
  * @param level if level is defined with go to the defined levle to find ancestor. Sinon on prend le current ancestor
419
508
  */
420
509
  getNodeAncestors(id, level) {
421
- const nodes = this.treeControl().dataNodes;
422
- const index = nodes.findIndex((node) => node.id === id);
423
- const targetLevel = level ?? Math.max(0, nodes[index].level - 1);
424
- return nodes
425
- .slice(0, index)
426
- .reverse()
427
- .find((node) => node.level === targetLevel);
510
+ const path = this.getAncestorsPath(id);
511
+ if (path.length === 0) {
512
+ return undefined;
513
+ }
514
+ if (level !== undefined) {
515
+ return path[level];
516
+ }
517
+ return path[path.length - 1];
518
+ }
519
+ getAncestorsPath(id) {
520
+ const nodes = this.nodes();
521
+ const roots = nodes.filter((n) => n.level === 0).map((n) => n.data);
522
+ for (const root of roots) {
523
+ const path = [];
524
+ if (this.findPath(root, id, path)) {
525
+ return path;
526
+ }
527
+ }
528
+ return [];
529
+ }
530
+ findPath(currentNode, targetId, path) {
531
+ if (String(currentNode.id) === String(targetId)) {
532
+ return true;
533
+ }
534
+ const children = this.childrenAccessor()(currentNode) ?? [];
535
+ for (const child of children) {
536
+ path.push(currentNode);
537
+ if (this.findPath(child, targetId, path)) {
538
+ return true;
539
+ }
540
+ path.pop();
541
+ }
542
+ return false;
543
+ }
544
+ getNodeLevel(node) {
545
+ const treeNode = this.findTreeNode(node.id);
546
+ return treeNode ? treeNode.level : 0;
428
547
  }
429
548
  getDirectDescendants(node) {
430
- const level = node.level + 1;
431
- return this.treeControl()
432
- .getDescendants(node)
433
- .filter((child) => child.level === level);
549
+ return this.childrenAccessor()(node) ?? [];
434
550
  }
435
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.6", ngImport: i0, type: TreeDragDropDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
436
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "20.3.6", type: TreeDragDropDirective, isStandalone: true, selector: "[igoTreeDragDrop]", inputs: { treeControl: { classPropertyName: "treeControl", publicName: "treeControl", isSignal: true, isRequired: true, transformFunction: null }, maxLevel: { classPropertyName: "maxLevel", publicName: "maxLevel", isSignal: true, isRequired: false, transformFunction: null }, treeDragDropIsDisabled: { classPropertyName: "treeDragDropIsDisabled", publicName: "treeDragDropIsDisabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dragStart: "dragStart", onDrop: "onDrop", onDropError: "onDropError" }, host: { listeners: { "dragover": "hostDragOver($event)", "drop": "hostDrop($event)" }, properties: { "class.--dragging": "this.dragging" } }, queries: [{ propertyName: "nodes", predicate: MatTreeNode, descendants: true, isSignal: true }], ngImport: i0 });
551
+ findTreeNode(id) {
552
+ return this.nodes().find((n) => String(n.data.id) === String(id));
553
+ }
554
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: TreeDragDropDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
555
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "20.3.18", type: TreeDragDropDirective, isStandalone: true, selector: "[igoTreeDragDrop]", inputs: { tree: { classPropertyName: "tree", publicName: "tree", isSignal: true, isRequired: true, transformFunction: null }, childrenAccessor: { classPropertyName: "childrenAccessor", publicName: "childrenAccessor", isSignal: true, isRequired: true, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null }, maxLevel: { classPropertyName: "maxLevel", publicName: "maxLevel", isSignal: true, isRequired: false, transformFunction: null }, treeDragDropIsDisabled: { classPropertyName: "treeDragDropIsDisabled", publicName: "treeDragDropIsDisabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dragStart: "dragStart", dropped: "dropped", droppedError: "droppedError" }, host: { listeners: { "dragover": "hostDragOver($event)", "dragleave": "hostDragLeave($event)", "drop": "hostDrop($event)" }, properties: { "class.--dragging": "dragging()" } }, queries: [{ propertyName: "nodes", predicate: MatTreeNode, descendants: true, isSignal: true }], ngImport: i0 });
437
556
  }
438
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.6", ngImport: i0, type: TreeDragDropDirective, decorators: [{
557
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: TreeDragDropDirective, decorators: [{
439
558
  type: Directive,
440
559
  args: [{
441
560
  selector: '[igoTreeDragDrop]',
442
- standalone: true
561
+ standalone: true,
562
+ host: {
563
+ '[class.--dragging]': 'dragging()',
564
+ '(dragover)': 'hostDragOver($event)',
565
+ '(dragleave)': 'hostDragLeave($event)',
566
+ '(drop)': 'hostDrop($event)'
567
+ }
443
568
  }]
444
- }], ctorParameters: () => [], propDecorators: { treeControl: [{ type: i0.Input, args: [{ isSignal: true, alias: "treeControl", required: true }] }], maxLevel: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxLevel", required: false }] }], treeDragDropIsDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "treeDragDropIsDisabled", required: false }] }], dragStart: [{ type: i0.Output, args: ["dragStart"] }], onDrop: [{ type: i0.Output, args: ["onDrop"] }], onDropError: [{ type: i0.Output, args: ["onDropError"] }], hostDragOver: [{
445
- type: HostListener,
446
- args: ['dragover', ['$event']]
447
- }], hostDrop: [{
448
- type: HostListener,
449
- args: ['drop', ['$event']]
450
- }], dragging: [{
451
- type: HostBinding,
452
- args: ['class.--dragging']
453
- }], nodes: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => MatTreeNode), { ...{ descendants: true }, isSignal: true }] }] } });
569
+ }], ctorParameters: () => [], propDecorators: { tree: [{ type: i0.Input, args: [{ isSignal: true, alias: "tree", required: true }] }], childrenAccessor: [{ type: i0.Input, args: [{ isSignal: true, alias: "childrenAccessor", required: true }] }], config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: true }] }], maxLevel: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxLevel", required: false }] }], treeDragDropIsDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "treeDragDropIsDisabled", required: false }] }], dragStart: [{ type: i0.Output, args: ["dragStart"] }], dropped: [{ type: i0.Output, args: ["dropped"] }], droppedError: [{ type: i0.Output, args: ["droppedError"] }], nodes: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => MatTreeNode), { ...{ descendants: true }, isSignal: true }] }] } });
454
570
 
455
571
  /**
456
572
  * @deprecated import the DragAndDropDirective directly
@@ -462,11 +578,11 @@ class IgoDrapDropModule {
462
578
  providers: []
463
579
  };
464
580
  }
465
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.6", ngImport: i0, type: IgoDrapDropModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
466
- static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.6", ngImport: i0, type: IgoDrapDropModule, imports: [DragAndDropDirective, TreeDragDropDirective], exports: [DragAndDropDirective, TreeDragDropDirective] });
467
- static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.6", ngImport: i0, type: IgoDrapDropModule });
581
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: IgoDrapDropModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
582
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.18", ngImport: i0, type: IgoDrapDropModule, imports: [DragAndDropDirective, TreeDragDropDirective], exports: [DragAndDropDirective, TreeDragDropDirective] });
583
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: IgoDrapDropModule });
468
584
  }
469
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.6", ngImport: i0, type: IgoDrapDropModule, decorators: [{
585
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: IgoDrapDropModule, decorators: [{
470
586
  type: NgModule,
471
587
  args: [{
472
588
  imports: [DragAndDropDirective, TreeDragDropDirective],