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

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 +46 -33
  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 +227 -110
  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,107 @@ 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
+ // Use a Set or just manage classes manually since SelectionModel was providing simple toggle
102
+ // But we can stick to simple class logic
103
+ highlightedNode;
104
+ tree = input.required(...(ngDevMode ? [{ debugName: "tree" }] : []));
105
+ childrenAccessor = input.required(...(ngDevMode ? [{ debugName: "childrenAccessor" }] : []));
106
+ config = input.required(...(ngDevMode ? [{ debugName: "config" }] : []));
102
107
  /** The default is 5 */
103
108
  maxLevel = input(5, ...(ngDevMode ? [{ debugName: "maxLevel" }] : []));
104
109
  treeDragDropIsDisabled = input(false, ...(ngDevMode ? [{ debugName: "treeDragDropIsDisabled", transform: booleanAttribute }] : [{
105
110
  transform: booleanAttribute
106
111
  }]));
107
112
  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();
113
+ dropped = output();
114
+ droppedError = output();
112
115
  hostDragOver(event) {
113
116
  event.preventDefault();
114
117
  }
118
+ hostDragLeave(event) {
119
+ const rect = this.elementRef.nativeElement.getBoundingClientRect();
120
+ if (event.clientY < rect.top ||
121
+ event.clientY >= rect.bottom ||
122
+ event.clientX < rect.left ||
123
+ event.clientX >= rect.right) {
124
+ this.dragLeave();
125
+ }
126
+ }
115
127
  hostDrop(event) {
116
128
  this.drop(event);
117
129
  }
118
- dragging;
130
+ dragging = signal(false, ...(ngDevMode ? [{ debugName: "dragging" }] : []));
119
131
  nodes = contentChildren(MatTreeNode, ...(ngDevMode ? [{ debugName: "nodes", descendants: true }] : [{ descendants: true }]));
120
132
  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');
133
+ this.dropped.subscribe(() => this.dragEnd());
134
+ effect(() => {
135
+ const disabled = this.treeDragDropIsDisabled();
136
+ disabled ? this.removeAllListener() : this.addAllListener();
137
+ });
138
+ effect(() => {
139
+ const current = this.dropLineTarget();
140
+ const parent = this.elementRef.nativeElement.parentElement;
141
+ if (!current) {
142
+ untracked(() => {
143
+ const previous = this.previousDropLine();
144
+ if (previous !== null) {
145
+ this.renderer.removeChild(parent, previous);
146
+ this.previousDropLine.set(null);
147
+ }
148
+ });
125
149
  }
126
- if (change.added.length) {
127
- this.addNodeClass(change.added[0].id, '--drag-hover');
150
+ else {
151
+ this.renderer.appendChild(parent, current);
128
152
  }
129
153
  });
130
154
  effect(() => {
131
- const disabled = this.treeDragDropIsDisabled();
132
- disabled ? this.removeAllListener() : this.addAllListener();
155
+ const targetNode = this.dropNodeTarget();
156
+ const position = this.dropPosition();
157
+ const dropLineTarget = this.dropLineTarget();
158
+ if (targetNode) {
159
+ this.setHighlightedNode(targetNode);
160
+ if (position) {
161
+ if (dropLineTarget) {
162
+ this.updateDropTargetLinePosition(position, dropLineTarget);
163
+ }
164
+ this.handleGroupExpansion(targetNode, position.type === 'inside');
165
+ }
166
+ }
133
167
  });
134
168
  }
169
+ get isGroup() {
170
+ return this.config().isGroup;
171
+ }
172
+ get getDescendantLevels() {
173
+ return this.config().descendantLevels;
174
+ }
135
175
  ngOnDestroy() {
136
176
  this.removeAllListener();
177
+ this.removeDropTargetLine();
137
178
  if (this.nodesEffect) {
138
- // EffectRef provides destroy() to stop the effect
139
179
  this.nodesEffect.destroy();
140
180
  this.nodesEffect = undefined;
141
181
  }
142
182
  }
143
183
  onDragStart(node) {
144
- this.dragging = true;
184
+ this.addDropTargetLine();
185
+ this.dragging.set(true);
145
186
  this.draggedNode = node;
146
187
  this.addNodeClass(node.id, '--dragged');
147
188
  this.dragStart.emit(node);
148
189
  }
149
190
  dragEnd() {
150
- this.dragging = false;
191
+ this.dragging.set(false);
151
192
  if (this.draggedNode) {
152
193
  this.removeNodeClass(this.draggedNode.id, '--dragged');
153
194
  this.draggedNode = null;
@@ -158,71 +199,81 @@ class TreeDragDropDirective {
158
199
  dragOver(node, event) {
159
200
  event.preventDefault();
160
201
  event.stopPropagation();
161
- this.dropNodeTarget = node;
202
+ this.dropNodeTarget.set(node);
162
203
  const position = this.getPosition(event, node);
163
- this.updateDropTargetLinePosition(position);
164
- this.setHighlightedNode(node);
165
- this.handleGroupExpansion(node, position.type === 'inside');
204
+ this.dropPosition.set(position);
166
205
  }
167
206
  dragLeave() {
168
207
  clearTimeout(this.expandTimeout);
169
208
  this.expandTimeout = null;
170
- this.highlightedNode.clear();
209
+ if (this.highlightedNode) {
210
+ this.removeNodeClass(this.highlightedNode.id, '--drag-hover');
211
+ this.highlightedNode = undefined;
212
+ }
171
213
  }
172
214
  drop(event) {
173
- if (!this.dropNodeTarget || this.treeDragDropIsDisabled()) {
215
+ let nodeTarget = this.dropNodeTarget();
216
+ if (!nodeTarget || this.treeDragDropIsDisabled()) {
174
217
  return;
175
218
  }
176
- const dropPosition = this.getPosition(event, this.dropNodeTarget);
177
- const validation = this.canDropNode(this.dropNodeTarget, dropPosition);
219
+ const dropPosition = this.getPosition(event, nodeTarget);
220
+ const validation = this.canDropNode(nodeTarget, dropPosition);
178
221
  if (!validation.canDrop) {
179
- this.onDropError.emit(validation);
222
+ this.droppedError.emit(validation);
180
223
  return;
181
224
  }
225
+ let targetNodeLevel = this.getNodeLevel(nodeTarget);
182
226
  // Allow to drop a last child outside is group. We refer to it's ancestor for the target
183
227
  if (dropPosition.type === 'below' &&
184
- dropPosition.level !== this.dropNodeTarget.level) {
185
- this.dropNodeTarget = this.getNodeAncestors(this.dropNodeTarget.id, dropPosition.level);
228
+ dropPosition.level !== targetNodeLevel) {
229
+ const ancestor = this.getNodeAncestors(nodeTarget.id, dropPosition.level);
230
+ this.dropNodeTarget.set(ancestor);
231
+ nodeTarget = ancestor;
232
+ targetNodeLevel = this.getNodeLevel(nodeTarget);
186
233
  }
187
- if (this.dropNodeTarget.isGroup) {
234
+ if (this.isGroup(nodeTarget)) {
188
235
  if (dropPosition.type === 'inside') {
189
- const isExpanded = this.treeControl().isExpanded(this.dropNodeTarget);
236
+ const isExpanded = this.tree().isExpanded(nodeTarget);
190
237
  if (isExpanded) {
191
- const children = this.getDirectDescendants(this.dropNodeTarget);
238
+ const children = this.getDirectDescendants(nodeTarget);
192
239
  if (children[0]?.id === this.draggedNode.id) {
193
240
  return;
194
241
  }
195
242
  }
196
- this.treeControl().expand(this.dropNodeTarget);
197
- return this.onDrop.emit({
243
+ this.tree().expand(nodeTarget);
244
+ return this.dropped.emit({
198
245
  node: this.draggedNode,
199
- ref: this.dropNodeTarget,
246
+ ref: nodeTarget,
200
247
  position: dropPosition.type
201
248
  });
202
249
  }
203
250
  }
204
251
  if (dropPosition.type === 'below' &&
205
- dropPosition.level !== this.dropNodeTarget.level) {
206
- const ancestor = this.getNodeAncestors(this.dropNodeTarget.id);
207
- return this.onDrop.emit({
252
+ dropPosition.level !== targetNodeLevel) {
253
+ const ancestor = this.getNodeAncestors(nodeTarget.id);
254
+ return this.dropped.emit({
208
255
  node: this.draggedNode,
209
256
  ref: ancestor,
210
257
  position: dropPosition.type
211
258
  });
212
259
  }
213
- this.onDrop.emit({
260
+ this.dropped.emit({
214
261
  node: this.draggedNode,
215
- ref: this.dropNodeTarget,
262
+ ref: nodeTarget,
216
263
  position: dropPosition.type
217
264
  });
218
265
  }
219
266
  addNodeClass(id, className) {
220
- const node = this.nodes().find((node) => node.data.id === id);
221
- this.renderer.addClass(node['_elementRef'].nativeElement, className);
267
+ const node = this.findTreeNode(id);
268
+ if (node) {
269
+ this.renderer.addClass(node['_elementRef'].nativeElement, className);
270
+ }
222
271
  }
223
272
  removeNodeClass(id, className) {
224
- const node = this.nodes().find((node) => node.data.id === id);
225
- this.renderer.removeClass(node['_elementRef'].nativeElement, className);
273
+ const node = this.findTreeNode(id);
274
+ if (node) {
275
+ this.renderer.removeClass(node['_elementRef'].nativeElement, className);
276
+ }
226
277
  }
227
278
  addAllListener() {
228
279
  if (this.treeDragDropIsDisabled()) {
@@ -256,52 +307,70 @@ class TreeDragDropDirective {
256
307
  this.nodesListeners = null;
257
308
  }
258
309
  setHighlightedNode(node) {
259
- const toHighlight = node.isGroup ? node : this.getNodeAncestors(node.id);
260
- toHighlight
261
- ? this.highlightedNode.select(toHighlight)
262
- : this.highlightedNode.clear();
310
+ const toHighlight = this.isGroup(node)
311
+ ? node
312
+ : this.getNodeAncestors(node.id);
313
+ if (this.highlightedNode && this.highlightedNode.id !== toHighlight?.id) {
314
+ this.removeNodeClass(this.highlightedNode.id, '--drag-hover');
315
+ this.highlightedNode = undefined;
316
+ }
317
+ if (toHighlight) {
318
+ this.highlightedNode = toHighlight;
319
+ this.addNodeClass(toHighlight.id, '--drag-hover');
320
+ }
321
+ else if (this.highlightedNode) {
322
+ this.removeNodeClass(this.highlightedNode.id, '--drag-hover');
323
+ this.highlightedNode = undefined;
324
+ }
263
325
  }
264
326
  addDropTargetLine() {
265
327
  const target = this.renderer.createElement('div');
266
328
  target.classList.add('drop-target-line');
267
329
  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);
330
+ this.dropLineTarget.set(target);
270
331
  }
271
332
  removeDropTargetLine() {
272
- if (!this.dropLineTarget) {
273
- return;
333
+ const target = this.dropLineTarget();
334
+ if (target) {
335
+ this.previousDropLine.set(target);
336
+ this.dropLineTarget.set(null);
274
337
  }
275
- this.renderer.removeChild(this.elementRef.nativeElement.parentElement, this.dropLineTarget);
276
- this.dropLineTarget = null;
277
338
  }
278
- updateDropTargetLinePosition(position) {
279
- if (!this.dropLineTarget) {
280
- this.addDropTargetLine();
281
- }
339
+ hideDropTargetLine() {
340
+ const target = this.dropLineTarget();
341
+ this.renderer.setStyle(target, 'display', 'none');
342
+ }
343
+ showDropTargetLine() {
344
+ const target = this.dropLineTarget();
345
+ this.renderer.setStyle(target, 'display', 'block');
346
+ }
347
+ updateDropTargetLinePosition(position, dropLineTarget) {
282
348
  if (position.type === 'inside') {
283
- return this.removeDropTargetLine();
349
+ return this.hideDropTargetLine();
284
350
  }
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)');
351
+ else {
352
+ this.showDropTargetLine();
353
+ }
354
+ this.renderer.setStyle(dropLineTarget, 'margin-left', position.level * 24 + 20 + 'px');
355
+ this.renderer.setStyle(dropLineTarget, 'transform', 'translate3d(0,' + position.y + 'px, 0)');
287
356
  }
288
357
  handleGroupExpansion(node, isInside) {
289
358
  if (!isInside) {
290
359
  return this.dragLeave();
291
360
  }
292
- const isOpen = this.treeControl().isExpanded(node);
361
+ const isOpen = this.tree().isExpanded(node);
293
362
  if (!isOpen && !this.expandTimeout) {
294
363
  this.expandTimeout = window.setTimeout(() => {
295
- this.treeControl().expand(node);
364
+ this.tree().expand(node);
296
365
  }, 1200);
297
366
  }
298
367
  }
299
368
  getNodeElement(node) {
300
- const treeNode = this.nodes().find((n) => n.data.id === node.id);
369
+ const treeNode = this.findTreeNode(node.id);
301
370
  return treeNode?.['_elementRef'].nativeElement;
302
371
  }
303
372
  canDropNode(hoveredNode, position) {
304
- if (this.draggedNode.isGroup) {
373
+ if (this.isGroup(this.draggedNode)) {
305
374
  return this.canDropGroup(hoveredNode, position);
306
375
  }
307
376
  const hasMaxLevelRestrictions = this.validateMaxHierarchyLevel(position);
@@ -318,14 +387,20 @@ class TreeDragDropDirective {
318
387
  message: 'igo.common.dragDrop.cannot.dropInsideItself'
319
388
  };
320
389
  }
390
+ const isHoverDescendant = this.isHoverDescendant(hoveredNode.id, hoveredNode);
391
+ if (isHoverDescendant) {
392
+ return {
393
+ canDrop: !isHoverDescendant,
394
+ message: 'igo.common.dragDrop.cannot.dropInsideItself'
395
+ };
396
+ }
321
397
  const hasMaxLevelRestrictions = this.validateMaxHierarchyLevel(position);
322
398
  if (hasMaxLevelRestrictions) {
323
399
  return hasMaxLevelRestrictions;
324
400
  }
325
- const isHoverDescendant = this.isHoverDescendant(hoveredNode.id);
326
401
  return {
327
- canDrop: !isHoverDescendant,
328
- message: isHoverDescendant && 'igo.common.dragDrop.cannot.dropInsideItself'
402
+ canDrop: true,
403
+ message: undefined
329
404
  };
330
405
  }
331
406
  validateMaxHierarchyLevel(position) {
@@ -334,9 +409,9 @@ class TreeDragDropDirective {
334
409
  return;
335
410
  }
336
411
  let level = position.type === 'inside' ? position.level + 1 : position.level;
337
- if (this.draggedNode.isGroup) {
412
+ if (this.isGroup(this.draggedNode)) {
338
413
  // We add an extra level +1 to avoid empty group in group
339
- level = level + (this.draggedNode.descendantLevels ?? 0) + 1;
414
+ level = level + +(this.getDescendantLevels(this.draggedNode) ?? 0) + 1;
340
415
  }
341
416
  if (level > maxLevel) {
342
417
  return {
@@ -346,21 +421,27 @@ class TreeDragDropDirective {
346
421
  };
347
422
  }
348
423
  }
349
- isHoverDescendant(id) {
350
- return this.treeControl()
351
- .getDescendants(this.draggedNode)
352
- .some((child) => child.id === id);
424
+ getDescendants(node) {
425
+ const children = this.childrenAccessor()(node) ?? [];
426
+ const descendants = [...children];
427
+ children.forEach((child) => {
428
+ descendants.push(...this.getDescendants(child));
429
+ });
430
+ return descendants;
431
+ }
432
+ isHoverDescendant(id, _hoveredNode) {
433
+ return this.getDescendants(this.draggedNode).some((child) => child.id === id);
353
434
  }
354
435
  getPosition(event, hoveredNode) {
355
- if (this.draggedNode.isGroup) {
356
- if (this.isHoverDescendant(hoveredNode.id)) {
436
+ if (this.isGroup(this.draggedNode)) {
437
+ if (this.isHoverDescendant(hoveredNode.id, hoveredNode)) {
357
438
  hoveredNode = this.draggedNode;
358
439
  }
359
440
  }
360
441
  let positionType = this.getPositionType(event, hoveredNode);
361
- const bellowOpenedGroup = hoveredNode.isGroup &&
442
+ const bellowOpenedGroup = this.isGroup(hoveredNode) &&
362
443
  positionType === 'below' &&
363
- this.treeControl().isExpanded(hoveredNode);
444
+ this.tree().isExpanded(hoveredNode);
364
445
  if (bellowOpenedGroup) {
365
446
  positionType = 'inside';
366
447
  }
@@ -384,7 +465,7 @@ class TreeDragDropDirective {
384
465
  const middle = rect.top + rect.height / 2;
385
466
  const y = event.y;
386
467
  const selfReferencing = this.draggedNode.id === hoveredNode.id;
387
- if (hoveredNode.isGroup && !selfReferencing) {
468
+ if (this.isGroup(hoveredNode) && !selfReferencing) {
388
469
  const tolerence = 5;
389
470
  if (y <= middle + tolerence && y >= middle - tolerence) {
390
471
  return 'inside';
@@ -394,56 +475,92 @@ class TreeDragDropDirective {
394
475
  return isBelow ? 'below' : 'above';
395
476
  }
396
477
  getPositionLevel(hoveredNode, type, x) {
397
- if (hoveredNode.level === 0) {
478
+ const hoveredNodeLevel = this.getNodeLevel(hoveredNode);
479
+ if (hoveredNodeLevel === 0) {
398
480
  return 0;
399
481
  }
400
482
  const ancestor = this.getNodeAncestors(hoveredNode.id);
483
+ if (!ancestor)
484
+ return hoveredNodeLevel;
401
485
  const children = this.getDirectDescendants(ancestor);
402
486
  const lastChild = [...children].pop();
403
- if (type === 'below' && lastChild.id === hoveredNode.id) {
487
+ if (type === 'below' && lastChild?.id === hoveredNode.id) {
404
488
  const target = this.getNodeElement(hoveredNode);
405
489
  const rect = target.getBoundingClientRect();
406
490
  const indentation = 24;
407
491
  const xMin = rect.x + indentation;
408
- const xMax = xMin + indentation * hoveredNode.level;
492
+ const xMax = xMin + indentation * hoveredNodeLevel;
409
493
  const isInsideSameGroup = x > xMax;
410
494
  if (!isInsideSameGroup) {
411
495
  const levelSubstracted = Math.round((xMax - x) / indentation);
412
- return Math.max(0, hoveredNode.level - levelSubstracted);
496
+ return Math.max(0, hoveredNodeLevel - levelSubstracted);
413
497
  }
414
498
  }
415
- return hoveredNode.level;
499
+ return hoveredNodeLevel;
416
500
  }
417
501
  /**
418
502
  * @param level if level is defined with go to the defined levle to find ancestor. Sinon on prend le current ancestor
419
503
  */
420
504
  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);
505
+ const path = this.getAncestorsPath(id);
506
+ if (path.length === 0) {
507
+ return undefined;
508
+ }
509
+ if (level !== undefined) {
510
+ return path[level];
511
+ }
512
+ return path[path.length - 1];
513
+ }
514
+ getAncestorsPath(id) {
515
+ const nodes = this.nodes();
516
+ const roots = nodes.filter((n) => n.level === 0).map((n) => n.data);
517
+ for (const root of roots) {
518
+ const path = [];
519
+ if (this.findPath(root, id, path)) {
520
+ return path;
521
+ }
522
+ }
523
+ return [];
524
+ }
525
+ findPath(currentNode, targetId, path) {
526
+ if (String(currentNode.id) === String(targetId)) {
527
+ return true;
528
+ }
529
+ const children = this.childrenAccessor()(currentNode) ?? [];
530
+ for (const child of children) {
531
+ path.push(currentNode);
532
+ if (this.findPath(child, targetId, path)) {
533
+ return true;
534
+ }
535
+ path.pop();
536
+ }
537
+ return false;
538
+ }
539
+ getNodeLevel(node) {
540
+ const treeNode = this.findTreeNode(node.id);
541
+ return treeNode ? treeNode.level : 0;
428
542
  }
429
543
  getDirectDescendants(node) {
430
- const level = node.level + 1;
431
- return this.treeControl()
432
- .getDescendants(node)
433
- .filter((child) => child.level === level);
544
+ return this.childrenAccessor()(node) ?? [];
434
545
  }
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 });
546
+ findTreeNode(id) {
547
+ return this.nodes().find((n) => String(n.data.id) === String(id));
548
+ }
549
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: TreeDragDropDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
550
+ 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": "this.dragging" } }, queries: [{ propertyName: "nodes", predicate: MatTreeNode, descendants: true, isSignal: true }], ngImport: i0 });
437
551
  }
438
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.6", ngImport: i0, type: TreeDragDropDirective, decorators: [{
552
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: TreeDragDropDirective, decorators: [{
439
553
  type: Directive,
440
554
  args: [{
441
555
  selector: '[igoTreeDragDrop]',
442
556
  standalone: true
443
557
  }]
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: [{
558
+ }], 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"] }], hostDragOver: [{
445
559
  type: HostListener,
446
560
  args: ['dragover', ['$event']]
561
+ }], hostDragLeave: [{
562
+ type: HostListener,
563
+ args: ['dragleave', ['$event']]
447
564
  }], hostDrop: [{
448
565
  type: HostListener,
449
566
  args: ['drop', ['$event']]
@@ -462,11 +579,11 @@ class IgoDrapDropModule {
462
579
  providers: []
463
580
  };
464
581
  }
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 });
582
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: IgoDrapDropModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
583
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.18", ngImport: i0, type: IgoDrapDropModule, imports: [DragAndDropDirective, TreeDragDropDirective], exports: [DragAndDropDirective, TreeDragDropDirective] });
584
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: IgoDrapDropModule });
468
585
  }
469
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.6", ngImport: i0, type: IgoDrapDropModule, decorators: [{
586
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: IgoDrapDropModule, decorators: [{
470
587
  type: NgModule,
471
588
  args: [{
472
589
  imports: [DragAndDropDirective, TreeDragDropDirective],