@acorex/cdk 20.0.0 → 20.0.1

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 (40) hide show
  1. package/drag-drop/index.d.ts +153 -22
  2. package/fesm2022/acorex-cdk-accordion.mjs +19 -19
  3. package/fesm2022/acorex-cdk-accordion.mjs.map +1 -1
  4. package/fesm2022/acorex-cdk-carousel.mjs +3 -3
  5. package/fesm2022/acorex-cdk-carousel.mjs.map +1 -1
  6. package/fesm2022/acorex-cdk-clipboard.mjs +6 -6
  7. package/fesm2022/acorex-cdk-clipboard.mjs.map +1 -1
  8. package/fesm2022/acorex-cdk-common.mjs +91 -91
  9. package/fesm2022/acorex-cdk-common.mjs.map +1 -1
  10. package/fesm2022/acorex-cdk-dom.mjs +3 -3
  11. package/fesm2022/acorex-cdk-dom.mjs.map +1 -1
  12. package/fesm2022/acorex-cdk-drag-drop.mjs +623 -162
  13. package/fesm2022/acorex-cdk-drag-drop.mjs.map +1 -1
  14. package/fesm2022/acorex-cdk-drawer.mjs +10 -10
  15. package/fesm2022/acorex-cdk-drawer.mjs.map +1 -1
  16. package/fesm2022/acorex-cdk-focus-trap.mjs +3 -3
  17. package/fesm2022/acorex-cdk-focus-trap.mjs.map +1 -1
  18. package/fesm2022/acorex-cdk-input-mask.mjs +70 -16
  19. package/fesm2022/acorex-cdk-input-mask.mjs.map +1 -1
  20. package/fesm2022/acorex-cdk-list-navigation.mjs +10 -10
  21. package/fesm2022/acorex-cdk-list-navigation.mjs.map +1 -1
  22. package/fesm2022/acorex-cdk-outline.mjs +13 -10
  23. package/fesm2022/acorex-cdk-outline.mjs.map +1 -1
  24. package/fesm2022/acorex-cdk-overlay.mjs +3 -3
  25. package/fesm2022/acorex-cdk-overlay.mjs.map +1 -1
  26. package/fesm2022/acorex-cdk-pan-view.mjs +3 -3
  27. package/fesm2022/acorex-cdk-pan-view.mjs.map +1 -1
  28. package/fesm2022/acorex-cdk-resizable.mjs +3 -3
  29. package/fesm2022/acorex-cdk-resizable.mjs.map +1 -1
  30. package/fesm2022/acorex-cdk-selection.mjs +10 -10
  31. package/fesm2022/acorex-cdk-selection.mjs.map +1 -1
  32. package/fesm2022/acorex-cdk-sliding-item.mjs +7 -7
  33. package/fesm2022/acorex-cdk-sliding-item.mjs.map +1 -1
  34. package/fesm2022/acorex-cdk-sticky.mjs +3 -3
  35. package/fesm2022/acorex-cdk-sticky.mjs.map +1 -1
  36. package/fesm2022/acorex-cdk-virtual-scroll.mjs +10 -10
  37. package/fesm2022/acorex-cdk-virtual-scroll.mjs.map +1 -1
  38. package/input-mask/index.d.ts +11 -3
  39. package/outline/index.d.ts +3 -2
  40. package/package.json +5 -5
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, ElementRef, signal, Directive, NgZone, DOCUMENT, Renderer2, ChangeDetectorRef, PLATFORM_ID, contentChild, input, output, computed, effect, RendererStyleFlags2, NgModule } from '@angular/core';
2
+ import { inject, ElementRef, signal, Directive, NgZone, Renderer2, ChangeDetectorRef, input, output, contentChildren, DOCUMENT, PLATFORM_ID, ViewContainerRef, contentChild, linkedSignal, computed, effect, RendererStyleFlags2, NgModule } from '@angular/core';
3
3
  import { isPlatformBrowser } from '@angular/common';
4
4
  import { clamp } from 'lodash-es';
5
5
  import { NXComponent } from '@acorex/cdk/common';
@@ -9,16 +9,346 @@ class AXDragHandleDirective {
9
9
  this.el = inject(ElementRef);
10
10
  this.element = signal(this.el.nativeElement);
11
11
  }
12
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: AXDragHandleDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
13
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.0.3", type: AXDragHandleDirective, isStandalone: true, selector: "[axDragHandle]", ngImport: i0 }); }
12
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: AXDragHandleDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
13
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.0.4", type: AXDragHandleDirective, isStandalone: true, selector: "[axDragHandle]", ngImport: i0 }); }
14
14
  }
15
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: AXDragHandleDirective, decorators: [{
15
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: AXDragHandleDirective, decorators: [{
16
16
  type: Directive,
17
17
  args: [{
18
18
  selector: '[axDragHandle]',
19
19
  }]
20
20
  }] });
21
21
 
22
+ /**
23
+ * @Directive axDropList
24
+ *
25
+ * Manages a list of draggable items (`axDrag`), enabling sorting within the list
26
+ * and transferring items between compatible lists. It handles the visual shifting
27
+ * of items during a drag operation to provide a clear preview of the drop location.
28
+ *
29
+ * This directive automatically detects `gap` from flexbox/grid layouts and handles
30
+ * items with variable sizes and margins.
31
+ */
32
+ class AXDropListDirective extends NXComponent {
33
+ constructor() {
34
+ super(...arguments);
35
+ this._zone = inject(NgZone);
36
+ this._renderer = inject(Renderer2);
37
+ this._cdr = inject(ChangeDetectorRef);
38
+ this._hostEl = inject(ElementRef);
39
+ // --- Public API: Inputs and Outputs ---
40
+ /** Whether sorting within this list is disabled. */
41
+ this.sortingDisabled = input(false);
42
+ /** The group this drop list belongs to. Dragging is only allowed between lists of the same group. */
43
+ this.dropListGroup = input();
44
+ /** The layout orientation of the list. */
45
+ this.dropListOrientation = input('vertical');
46
+ /** Emits when an item is dropped into the list. */
47
+ this.dropListDropped = output();
48
+ /** The `axDrag` directives that are direct children of this list. */
49
+ this._draggableItems = contentChildren(AXDragDirective, { descendants: false });
50
+ // --- Internal State Management ---
51
+ /** The native element of the drop list. */
52
+ this.element = this._hostEl.nativeElement;
53
+ /** The draggable item currently being moved over this list. */
54
+ this._activeDragItem = signal(null);
55
+ /** The calculated index where the placeholder/item should be. */
56
+ this._placeholderIndex = signal(-1);
57
+ /** A snapshot of the items' data and geometry at the start of the drag. */
58
+ this._cachedItems = signal([]);
59
+ /** The list's initial bounding box, used to calculate scroll delta. */
60
+ this._listInitialRect = signal(null);
61
+ /** The detected `gap` of the list for the current orientation. */
62
+ this._listGap = signal(0);
63
+ /** A signal-based alias for the orientation input for internal use. */
64
+ this._orientation = this.dropListOrientation;
65
+ }
66
+ ngOnInit() {
67
+ this.element.dataset['axDropList'] = 'true';
68
+ this.element.classList.add('ax-drop-list-sorting-transition');
69
+ }
70
+ ngAfterContentInit() {
71
+ this._cdr.detectChanges();
72
+ }
73
+ // --- Public Methods (for internal library use) ---
74
+ /** Checks if the given drag item is the one currently active in this list. */
75
+ isDragActiveForThisList(dragItem) {
76
+ return this._activeDragItem() === dragItem;
77
+ }
78
+ /**
79
+ * Prepares the list for sorting when a drag operation starts from within this list.
80
+ * @param dragItem The item that is being dragged.
81
+ */
82
+ prepareSort(dragItem) {
83
+ if (this.sortingDisabled() || this._activeDragItem())
84
+ return;
85
+ this._activeDragItem.set(dragItem);
86
+ this.element.classList.add('ax-drop-list-sorting-active');
87
+ requestAnimationFrame(() => {
88
+ this._zone.run(() => {
89
+ this._cacheGeometry();
90
+ const placeholderIdx = this._cachedItems().findIndex((data) => data.item === dragItem);
91
+ this._placeholderIndex.set(placeholderIdx);
92
+ });
93
+ });
94
+ }
95
+ /**
96
+ * Prepares the list for receiving an item that started dragging from another list.
97
+ * @param dragItem The item entering this list.
98
+ */
99
+ enter(dragItem) {
100
+ if (this.sortingDisabled() || this.isDragActiveForThisList(dragItem))
101
+ return;
102
+ this._activeDragItem.set(dragItem);
103
+ this.element.classList.add('ax-drop-list-sorting-active');
104
+ requestAnimationFrame(() => this._zone.run(() => this._cacheGeometry()));
105
+ }
106
+ /**
107
+ * Calculates the new placeholder index based on the pointer's position and applies visual shifts.
108
+ * @param event The pointer move event.
109
+ * @param dragItem The item being dragged.
110
+ */
111
+ sort(event, dragItem) {
112
+ if (!this.isDragActiveForThisList(dragItem) || this.sortingDisabled() || !this._listInitialRect())
113
+ return;
114
+ const pointerPosition = this._orientation() === 'vertical' ? event.clientY : event.clientX;
115
+ const newPlaceholderIndex = this._calculatePlaceholderIndex(pointerPosition);
116
+ if (this._placeholderIndex() !== newPlaceholderIndex) {
117
+ this._placeholderIndex.set(newPlaceholderIndex);
118
+ this._applyVisualShifts();
119
+ }
120
+ }
121
+ /**
122
+ * Finalizes the drop, emits the drop event, and resets the list's state.
123
+ * @param event The pointer up event.
124
+ * @param droppedItem The item that was dropped.
125
+ * @param sourceList The list where the drag originated.
126
+ */
127
+ finalizeSort(event, droppedItem, sourceList) {
128
+ if (!this.isDragActiveForThisList(droppedItem) || this.sortingDisabled()) {
129
+ this.resetSortStateAndStyles(sourceList);
130
+ return;
131
+ }
132
+ const activeItem = this._activeDragItem();
133
+ const targetSlotIndex = this._placeholderIndex();
134
+ if (!activeItem || targetSlotIndex === -1) {
135
+ this.resetSortStateAndStyles(sourceList);
136
+ return;
137
+ }
138
+ const previousIndex = sourceList._cachedItems().findIndex((d) => d.item === activeItem);
139
+ // Adjust the index for array mutation if moving an item to a later position in the same list.
140
+ const currentIndex = sourceList === this && previousIndex !== -1 && targetSlotIndex > previousIndex
141
+ ? targetSlotIndex - 1
142
+ : targetSlotIndex;
143
+ this.dropListDropped.emit({
144
+ nativeEvent: event,
145
+ sender: this,
146
+ item: activeItem,
147
+ previousIndex,
148
+ currentIndex,
149
+ container: this,
150
+ previousContainer: sourceList,
151
+ });
152
+ this.resetSortStateAndStyles(sourceList);
153
+ }
154
+ /** Resets the transforms on all items and cancels the current sort operation. */
155
+ cancelSort(dragItem) {
156
+ if (dragItem && !this.isDragActiveForThisList(dragItem))
157
+ return;
158
+ this._resetAllTransforms();
159
+ this.resetSortState();
160
+ }
161
+ /** Resets transforms but keeps the active state, used when moving between lists. */
162
+ cancelSortPreview() {
163
+ if (!this._activeDragItem())
164
+ return;
165
+ this._resetAllTransforms();
166
+ const originalIndex = this._cachedItems().findIndex((d) => d.item === this._activeDragItem());
167
+ this._placeholderIndex.set(originalIndex > -1 ? originalIndex : -1);
168
+ }
169
+ // --- Private Helper Methods ---
170
+ /** Caches the geometry of the list and its items at the start of a drag. */
171
+ _cacheGeometry() {
172
+ this._listInitialRect.set(this.element.getBoundingClientRect());
173
+ this._detectAndCacheListGap();
174
+ const items = this._draggableItems().map((itemDraggable) => {
175
+ const el = itemDraggable.element();
176
+ const style = window.getComputedStyle(el);
177
+ const rect = el.getBoundingClientRect();
178
+ return {
179
+ item: itemDraggable,
180
+ element: el,
181
+ initialRect: rect,
182
+ width: rect.width,
183
+ height: rect.height,
184
+ margins: {
185
+ top: parseFloat(style.marginTop),
186
+ bottom: parseFloat(style.marginBottom),
187
+ left: parseFloat(style.marginLeft),
188
+ right: parseFloat(style.marginRight),
189
+ },
190
+ };
191
+ });
192
+ this._cachedItems.set(items);
193
+ }
194
+ /** Detects and caches the `gap` property from the list's computed styles. */
195
+ _detectAndCacheListGap() {
196
+ const listStyle = window.getComputedStyle(this.element);
197
+ const gapValue = listStyle.getPropertyValue('gap');
198
+ if (gapValue && gapValue !== 'normal') {
199
+ const gapParts = gapValue.split(' ');
200
+ const rowGap = parseFloat(gapParts[0]);
201
+ const columnGap = parseFloat(gapParts[1] || gapParts[0]);
202
+ this._listGap.set(this._orientation() === 'vertical' ? rowGap : columnGap);
203
+ }
204
+ else {
205
+ this._listGap.set(0);
206
+ }
207
+ }
208
+ /**
209
+ * Determines the new placeholder index by comparing the pointer position against the
210
+ * midpoints of the other items in the list.
211
+ * @param pointerPosition The clientX or clientY of the pointer.
212
+ * @returns The calculated placeholder index.
213
+ */
214
+ _calculatePlaceholderIndex(pointerPosition) {
215
+ const activeItem = this._activeDragItem();
216
+ const listRect = this._listInitialRect();
217
+ const siblings = this._cachedItems().filter((d) => d.item !== activeItem);
218
+ const scrollDelta = this._orientation() === 'vertical'
219
+ ? this.element.getBoundingClientRect().top - listRect.top
220
+ : this.element.getBoundingClientRect().left - listRect.left;
221
+ let newIndexInSiblings = -1;
222
+ for (let i = 0; i < siblings.length; i++) {
223
+ const sibling = siblings[i];
224
+ const itemMidPoint = (this._orientation() === 'vertical' ? sibling.initialRect.top : sibling.initialRect.left) +
225
+ scrollDelta +
226
+ (this._orientation() === 'vertical' ? sibling.height : sibling.width) / 2;
227
+ if (pointerPosition < itemMidPoint) {
228
+ newIndexInSiblings = i;
229
+ break;
230
+ }
231
+ }
232
+ if (newIndexInSiblings === -1) {
233
+ newIndexInSiblings = siblings.length;
234
+ }
235
+ const originalIndex = this._cachedItems().findIndex((d) => d.item === activeItem);
236
+ // Map the index from the 'siblings' array back to the original `_cachedItems` array.
237
+ return originalIndex > -1 && newIndexInSiblings >= originalIndex ? newIndexInSiblings + 1 : newIndexInSiblings;
238
+ }
239
+ /** Applies `transform` styles to all items to create the visual sorting effect. */
240
+ _applyVisualShifts() {
241
+ const activeItem = this._activeDragItem();
242
+ const originalIndex = this._cachedItems().findIndex((d) => d.item === activeItem);
243
+ const isIntraListDrag = originalIndex > -1;
244
+ // A helper to get the total space an item occupies (size + margins).
245
+ const getItemSpace = (itemData) => this._orientation() === 'vertical'
246
+ ? itemData.height + itemData.margins.top + itemData.margins.bottom
247
+ : itemData.width + itemData.margins.left + itemData.margins.right;
248
+ let draggedItemSize = 0;
249
+ if (isIntraListDrag) {
250
+ draggedItemSize = getItemSpace(this._cachedItems()[originalIndex]);
251
+ }
252
+ else {
253
+ const rect = activeItem.elementRect();
254
+ if (rect) {
255
+ const style = window.getComputedStyle(activeItem.element());
256
+ draggedItemSize =
257
+ this._orientation() === 'vertical'
258
+ ? rect.height + parseFloat(style.marginTop) + parseFloat(style.marginBottom)
259
+ : rect.width + parseFloat(style.marginLeft) + parseFloat(style.marginRight);
260
+ }
261
+ }
262
+ this._cachedItems().forEach((data, index) => {
263
+ const transform = this._calculateTransform(index, originalIndex, draggedItemSize, getItemSpace);
264
+ this._renderer.setStyle(data.element, 'transform', transform ? `${this._orientation() === 'vertical' ? 'translateY' : 'translateX'}(${transform}px)` : '');
265
+ });
266
+ }
267
+ /**
268
+ * Calculates the required transform in pixels for a single item.
269
+ * @param index The index of the item to transform.
270
+ * @param originalIndex The original index of the dragged item (-1 if from another list).
271
+ * @param draggedItemSize The size (including margins) of the item being dragged.
272
+ * @param getItemSpace A helper function to get an item's size including margins.
273
+ * @returns The transform value in pixels.
274
+ */
275
+ _calculateTransform(index, originalIndex, draggedItemSize, getItemSpace) {
276
+ const targetIndex = this._placeholderIndex();
277
+ const listGap = this._listGap();
278
+ if (originalIndex > -1) {
279
+ // --- Intra-list Drag ---
280
+ if (index === originalIndex) {
281
+ // The dragged item moves by the sum of the sizes of the items it passes over, PLUS the gaps between them.
282
+ let offset = 0;
283
+ if (targetIndex > originalIndex) {
284
+ // Dragging down/right
285
+ for (let i = originalIndex + 1; i < targetIndex; i++) {
286
+ offset += getItemSpace(this._cachedItems()[i]) + listGap;
287
+ }
288
+ }
289
+ else {
290
+ // Dragging up/left
291
+ for (let i = targetIndex; i < originalIndex; i++) {
292
+ offset -= getItemSpace(this._cachedItems()[i]) + listGap;
293
+ }
294
+ }
295
+ return offset;
296
+ }
297
+ else {
298
+ // It's a sibling item that needs to make space.
299
+ // It moves by the size of the dragged item, plus ONE gap to fill the void.
300
+ const shift = draggedItemSize + listGap;
301
+ if (originalIndex < targetIndex && index > originalIndex && index < targetIndex) {
302
+ return -shift;
303
+ }
304
+ else if (originalIndex > targetIndex && index >= targetIndex && index < originalIndex) {
305
+ return shift;
306
+ }
307
+ }
308
+ }
309
+ else {
310
+ // --- Inter-list Drag (from another list) ---
311
+ if (index >= targetIndex) {
312
+ // An item from another list enters. Siblings shift by its size plus ONE gap.
313
+ return draggedItemSize + listGap;
314
+ }
315
+ }
316
+ return 0;
317
+ }
318
+ /** Resets the state of this list and the source list after a drop. */
319
+ resetSortStateAndStyles(sourceList) {
320
+ const listsToReset = new Set([this, sourceList]);
321
+ listsToReset.forEach((list) => {
322
+ if (list) {
323
+ list._resetAllTransforms();
324
+ list.resetSortState();
325
+ }
326
+ });
327
+ }
328
+ /** Removes all `transform` styles from the items in this list. */
329
+ _resetAllTransforms() {
330
+ this._cachedItems().forEach((data) => this._renderer.setStyle(data.element, 'transform', ''));
331
+ }
332
+ /** Resets the internal state of the directive to its initial values. */
333
+ resetSortState() {
334
+ this.element.classList.remove('ax-drop-list-sorting-active');
335
+ this._activeDragItem.set(null);
336
+ this._cachedItems.set([]);
337
+ this._placeholderIndex.set(-1);
338
+ this._listInitialRect.set(null);
339
+ this._listGap.set(0);
340
+ }
341
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: AXDropListDirective, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
342
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "20.0.4", type: AXDropListDirective, isStandalone: true, selector: "[axDropList]", inputs: { sortingDisabled: { classPropertyName: "sortingDisabled", publicName: "sortingDisabled", isSignal: true, isRequired: false, transformFunction: null }, dropListGroup: { classPropertyName: "dropListGroup", publicName: "dropListGroup", isSignal: true, isRequired: false, transformFunction: null }, dropListOrientation: { classPropertyName: "dropListOrientation", publicName: "dropListOrientation", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dropListDropped: "dropListDropped" }, queries: [{ propertyName: "_draggableItems", predicate: AXDragDirective, isSignal: true }], exportAs: ["axDropList"], usesInheritance: true, ngImport: i0 }); }
343
+ }
344
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: AXDropListDirective, decorators: [{
345
+ type: Directive,
346
+ args: [{
347
+ selector: '[axDropList]',
348
+ exportAs: 'axDropList',
349
+ }]
350
+ }] });
351
+
22
352
  class AXDragDirective {
23
353
  constructor() {
24
354
  this.zone = inject(NgZone);
@@ -26,42 +356,51 @@ class AXDragDirective {
26
356
  this.renderer = inject(Renderer2);
27
357
  this.cdr = inject(ChangeDetectorRef);
28
358
  this.platformId = inject(PLATFORM_ID);
359
+ this.viewContainerRef = inject(ViewContainerRef);
29
360
  this.el = inject(ElementRef);
30
361
  this.handleDirective = contentChild(AXDragHandleDirective);
31
362
  this.dragData = input();
32
363
  this.dragDisabled = input(false);
364
+ this.dragTransition = input(true);
33
365
  this.dragElementClone = input(false);
34
366
  this.dropZoneGroup = input();
35
367
  this.dragStartDelay = input();
36
368
  this.dragResetOnDblClick = input(true);
37
369
  this.dragLockAxis = input(null);
370
+ this.dragClonedTemplate = input();
38
371
  this.dragCursor = input('move');
39
372
  this.dragBoundary = input();
373
+ this.dragTransitionDuration = input(150);
40
374
  this.dragPositionChanged = output();
375
+ this.clonedElement = signal(null);
41
376
  this.currentAxis = signal({ x: 0, y: 0 });
42
377
  this.currentCloneAxis = signal({ x: 0, y: 0 });
43
- this.clonedElement = signal(null);
378
+ this.transitionDuration = linkedSignal(() => this.dragTransitionDuration());
44
379
  this.element = signal(this.el.nativeElement);
45
- this.elementOpacity = signal('1');
46
380
  this.isMoving = signal(false);
47
381
  this.isDragging = signal(false);
382
+ this.elementOpacity = signal('1');
48
383
  this.isDelayStarted = signal(false);
384
+ this.prevDropZone = signal(null);
49
385
  this.dragStartOffset = signal({ x: 0, y: 0 });
50
386
  this.clonePointerOffset = signal({ x: 0, y: 0 });
51
- this.prevDropZone = signal(null);
387
+ this.clonedElementViewRef = signal(null);
388
+ this._parentDropList = inject(AXDropListDirective, { optional: true, skipSelf: true, host: false });
389
+ this._currentDropList = signal(null);
390
+ this.createCloneElement = computed(() => this.dragElementClone() || !!this._parentDropList);
52
391
  this.boundaryElement = computed(() => {
53
392
  const boundary = this.dragBoundary();
54
393
  if (!boundary) {
55
394
  return null;
56
395
  }
57
396
  if (typeof boundary === 'string') {
58
- return this.el.nativeElement.closest(boundary);
397
+ return this.document.querySelector(boundary);
59
398
  }
60
399
  return boundary instanceof ElementRef ? boundary.nativeElement : boundary;
61
400
  });
62
401
  this.elementRect = computed(() => {
63
402
  if (!isPlatformBrowser(this.platformId)) {
64
- return null; // Or some default/mock DOMRect-like object if needed for type safety
403
+ return null;
65
404
  }
66
405
  return this.element().getBoundingClientRect();
67
406
  });
@@ -97,6 +436,9 @@ class AXDragDirective {
97
436
  this.handle().addEventListener('dblclick', this.boundHandleDblClick);
98
437
  this.handle().addEventListener('pointerdown', this.boundHandlePointerDown, { passive: false });
99
438
  });
439
+ if (this._parentDropList) {
440
+ this.setElementTransition(this.element());
441
+ }
100
442
  this.renderer.setStyle(this.element(), 'z-index', '1');
101
443
  this.elementOpacity.set(getComputedStyle(this.element()).opacity);
102
444
  }
@@ -106,27 +448,35 @@ class AXDragDirective {
106
448
  this.handle().removeEventListener('dblclick', this.boundHandleDblClick);
107
449
  this.handle().removeEventListener('pointerdown', this.boundHandlePointerDown);
108
450
  this.removeDocumentListeners();
109
- if (this.dragElementClone()) {
451
+ if (this.createCloneElement()) {
110
452
  this.removeCloneElement();
111
453
  }
454
+ if (this._parentDropList && this.isDragging()) {
455
+ this._parentDropList.cancelSort();
456
+ }
112
457
  }
113
458
  }
459
+ setElementTransition(element) {
460
+ this.renderer.setStyle(element, 'transition-property', 'transform, opacity, translate');
461
+ this.renderer.setStyle(element, 'transition-duration', `var(--ax-sys-transition-duration,${this.transitionDuration()}ms)`);
462
+ this.renderer.setStyle(element, 'transition-timing-function', 'var(--ax-sys-transition-timing-function)');
463
+ }
464
+ removeElementTransition(element) {
465
+ this.renderer.setStyle(element, 'transition-property', 'opacity');
466
+ }
114
467
  handlePointerDown(e) {
115
468
  if (!isPlatformBrowser(this.platformId))
116
469
  return;
117
470
  if (this.dragDisabled() || e.button !== 0)
118
471
  return;
119
- switch (this.dragCursor()) {
120
- case 'move':
121
- this.renderer.setStyle(this.element(), 'cursor', 'move');
122
- break;
123
- case 'grab':
124
- this.renderer.setStyle(this.element(), 'cursor', 'grabbing');
125
- break;
472
+ this.isDragging.set(true);
473
+ if (this.dragCursor() === 'move') {
474
+ this.renderer.setStyle(this.document.body, 'cursor', 'move');
475
+ }
476
+ else if (this.dragCursor() === 'grab') {
477
+ this.renderer.setStyle(this.document.body, 'cursor', 'grabbing');
126
478
  }
127
- // e.preventDefault();
128
479
  e.stopPropagation();
129
- this.isDragging.set(true);
130
480
  this.dragStartOffset.set({ x: e.clientX - this.currentAxis().x, y: e.clientY - this.currentAxis().y });
131
481
  this.renderer.setStyle(this.handle(), 'userSelect', 'none');
132
482
  this.handle().setPointerCapture(e.pointerId);
@@ -134,49 +484,76 @@ class AXDragDirective {
134
484
  if (this.dragStartDelay()) {
135
485
  this.isDelayStarted.set(true);
136
486
  setTimeout(() => {
137
- this.isDelayStarted.set(false);
487
+ if (this.isDragging()) {
488
+ this.isDelayStarted.set(false);
489
+ this.startDrag(e);
490
+ }
138
491
  }, this.dragStartDelay());
139
492
  }
140
- this.dropZoneHoverHandler(e);
141
- if (this.dragElementClone()) {
493
+ else {
494
+ this.startDrag(e);
495
+ }
496
+ }
497
+ startDrag(e) {
498
+ if (this._parentDropList) {
499
+ this._currentDropList.set(this._parentDropList);
500
+ this._parentDropList.prepareSort(this);
501
+ }
502
+ else {
503
+ this.dropZoneHoverHandler(e);
504
+ }
505
+ if (this.createCloneElement()) {
142
506
  const elementRect = this.element().getBoundingClientRect();
143
507
  this.clonePointerOffset.set({
144
508
  x: e.clientX - elementRect.left,
145
509
  y: e.clientY - elementRect.top,
146
510
  });
147
- this.createCloneElement(this.element());
511
+ this.createCloneElementHandler(this.element());
148
512
  }
149
513
  }
150
514
  handlePointerUp(e) {
515
+ const transform = this.element().style.transform;
516
+ let x = 0;
517
+ let y = 0;
518
+ if (transform) {
519
+ x = Number(transform.split('translateX(')[1]?.split('px)')[0]);
520
+ y = Number(transform.split('translateY(')[1]?.split('px)')[0]);
521
+ }
151
522
  if (!isPlatformBrowser(this.platformId))
152
523
  return;
153
- if (!this.isDragging()) {
524
+ if (!this.isDragging())
154
525
  return;
526
+ this.renderer.removeStyle(this.document.body, 'cursor');
527
+ const wasMoving = this.isMoving();
528
+ this.isDragging.set(false);
529
+ if (wasMoving) {
530
+ this.preventClicking();
155
531
  }
156
- if (this.handleDirective()) {
157
- this.renderer.removeStyle(this.element(), 'cursor');
532
+ const droppedIntoList = this._currentDropList();
533
+ if (droppedIntoList && this._parentDropList) {
534
+ droppedIntoList.finalizeSort(e, this, this._parentDropList);
158
535
  }
159
- if (this.dragCursor() === 'grab') {
160
- this.renderer.setStyle(this.element(), 'cursor', 'grab');
536
+ else if (this._parentDropList) {
537
+ this._parentDropList.cancelSort(this);
161
538
  }
162
- this.isDragging.set(false);
539
+ else {
540
+ this.dropZoneDropHandler(e);
541
+ }
542
+ this._currentDropList.set(null);
543
+ this.isMoving.set(false);
163
544
  this.renderer.removeStyle(this.handle(), 'userSelect');
164
- this.handle().releasePointerCapture(e.pointerId);
545
+ if (this.handle().hasPointerCapture(e.pointerId)) {
546
+ this.handle().releasePointerCapture(e.pointerId);
547
+ }
165
548
  this.removeDocumentListeners();
166
- if (this.isMoving()) {
167
- this.preventClicking();
168
- this.isMoving.set(false);
169
- this.dropZoneDropHandler(e);
549
+ if (this.createCloneElement()) {
550
+ const listUnderPointer = this.getDropListFromPoint(e.clientX, e.clientY);
551
+ this.removeCloneElementWithAnimation(x || 0, y || 0, listUnderPointer);
170
552
  }
171
- if (this.dragElementClone()) {
172
- this.removeCloneElement();
553
+ else {
554
+ this.renderer.setStyle(this.element(), 'opacity', this.elementOpacity());
173
555
  }
174
556
  }
175
- /**
176
- * Prevent click events immediately following pointerup, especially on touch devices
177
- * or fast drags where the underlying element might receive an unintended click.
178
- * Use a capturing listener added *after* pointerup and removed asynchronously.
179
- */
180
557
  preventClicking() {
181
558
  const blockClick = (event) => {
182
559
  event.preventDefault();
@@ -190,17 +567,13 @@ class AXDragDirective {
190
567
  this.setPosition(0, 0);
191
568
  }
192
569
  handlePointerMove(e) {
193
- if (!isPlatformBrowser(this.platformId))
570
+ if (!isPlatformBrowser(this.platformId) || !this.isDragging() || this.isDelayStarted())
194
571
  return;
195
- if (!this.isDragging())
196
- return;
197
- if (this.isDelayStarted()) {
198
- this.isDragging.set(false);
199
- return;
200
- }
201
572
  e.preventDefault();
202
- this.isMoving.set(true);
203
- if (this.dragElementClone()) {
573
+ if (!this.isMoving()) {
574
+ this.isMoving.set(true);
575
+ }
576
+ if (this.createCloneElement()) {
204
577
  const newCloneX = e.clientX - this.clonePointerOffset().x;
205
578
  const newCloneY = e.clientY - this.clonePointerOffset().y;
206
579
  this.setClonePosition(newCloneX, newCloneY);
@@ -210,73 +583,105 @@ class AXDragDirective {
210
583
  const newY = e.clientY - this.dragStartOffset().y;
211
584
  this.setPosition(newX, newY);
212
585
  }
213
- this.dropZoneHoverHandler(e);
586
+ if (this._parentDropList) {
587
+ this.handleDropListInteractions(e);
588
+ }
589
+ else {
590
+ this.dropZoneHoverHandler(e);
591
+ }
592
+ }
593
+ handleDropListInteractions(e) {
594
+ const listUnderPointer = this.getDropListFromPoint(e.clientX, e.clientY);
595
+ const previousList = this._currentDropList();
596
+ let targetList = null;
597
+ if (listUnderPointer && this.canDropInList(listUnderPointer)) {
598
+ targetList = listUnderPointer;
599
+ }
600
+ if (targetList !== previousList) {
601
+ if (previousList) {
602
+ previousList.cancelSortPreview();
603
+ if (previousList !== this._parentDropList) {
604
+ previousList.resetSortState();
605
+ }
606
+ }
607
+ if (targetList) {
608
+ targetList.enter(this);
609
+ }
610
+ this._currentDropList.set(targetList);
611
+ }
612
+ this._currentDropList()?.sort(e, this);
613
+ }
614
+ canDropInList(list) {
615
+ if (!list || list.sortingDisabled() || !this._parentDropList) {
616
+ return false;
617
+ }
618
+ if (list === this._parentDropList) {
619
+ return true;
620
+ }
621
+ const dragGroup = this._parentDropList.dropListGroup();
622
+ const targetGroup = list.dropListGroup();
623
+ return !!dragGroup && dragGroup === targetGroup;
214
624
  }
215
625
  dropZoneHoverHandler(e) {
216
626
  const dropZones = this.getDropZonesFromPoint(e.clientX, e.clientY);
217
- if (!dropZones.length && this.prevDropZone() && this.prevDropZone().isHovered()) {
218
- this.leavePrevDropZone(e);
219
- return;
220
- }
221
627
  const dropZone = dropZones[0];
222
- if (!this.dropZoneValidation(dropZone, e) || dropZone.isHovered()) {
628
+ if (!dropZone) {
629
+ if (this.prevDropZone()) {
630
+ this.leavePrevDropZone(e);
631
+ }
223
632
  return;
224
633
  }
225
634
  if (this.prevDropZone() && this.prevDropZone() !== dropZone) {
226
635
  this.leavePrevDropZone(e);
227
636
  }
228
- this.prevDropZone.set(dropZone);
229
- dropZone.onElementHover.emit({ sender: dropZone, dropped: this, nativeEvent: e, state: 'enter' });
230
- dropZone.isHovered.set(true);
637
+ if (this.dropZoneValidation(dropZone) && !dropZone.isHovered()) {
638
+ this.prevDropZone.set(dropZone);
639
+ dropZone.onElementHover.emit({ sender: dropZone, dropped: this, nativeEvent: e, state: 'enter' });
640
+ dropZone.isHovered.set(true);
641
+ }
231
642
  }
232
643
  dropZoneDropHandler(e) {
233
644
  const dropZones = this.getDropZonesFromPoint(e.clientX, e.clientY);
234
645
  const dropZone = dropZones[0];
235
- if (!this.dropZoneValidation(dropZone, e)) {
646
+ if (!this.dropZoneValidation(dropZone)) {
236
647
  return;
237
648
  }
238
649
  dropZone.isHovered.set(false);
239
650
  dropZone.onElementDrop.emit({ sender: dropZone, dropped: this, nativeEvent: e });
240
651
  }
241
652
  getDropZonesFromPoint(x, y) {
242
- const elementsFromPoint = this.document.elementsFromPoint(x, y);
243
- return elementsFromPoint
244
- .filter((el) => {
245
- if (el instanceof HTMLElement) {
246
- return el.dataset['dropZone'] === 'true';
247
- }
248
- return false;
249
- })
250
- .map((el) => {
251
- return el['__axContext__'];
252
- });
653
+ const elements = this.document.elementsFromPoint(x, y);
654
+ return elements
655
+ .filter((el) => el instanceof HTMLElement && el.dataset['axDropZone'] === 'true')
656
+ .map((el) => el['__axContext__']);
253
657
  }
254
- dropZoneValidation(dropZone, e) {
255
- // There is a dropzone
256
- if (!dropZone) {
658
+ getDropListFromPoint(x, y) {
659
+ const dropListElement = this.document
660
+ .elementsFromPoint(x, y)
661
+ .find((el) => el instanceof HTMLElement && el.dataset['axDropList'] === 'true');
662
+ return dropListElement ? dropListElement['__axContext__'] : null;
663
+ }
664
+ dropZoneValidation(dropZone) {
665
+ if (!dropZone)
257
666
  return false;
258
- }
259
- // They are in the same group
260
667
  const dragGroup = this.dropZoneGroup();
261
668
  const dropGroup = dropZone.dropZoneGroup();
262
- if (dragGroup !== dropGroup) {
263
- return false;
264
- }
265
- // Draggable element is under mouse
266
- const elementsFromPoint = this.document.elementsFromPoint(e.clientX, e.clientY);
267
- if (!elementsFromPoint.includes(this.element()) && !this.clonedElement()) {
669
+ if (dropGroup && dragGroup !== dropGroup) {
268
670
  return false;
269
671
  }
270
672
  return true;
271
673
  }
272
674
  leavePrevDropZone(e) {
273
- this.prevDropZone().onElementHover.emit({
274
- dropped: this,
275
- state: 'leave',
276
- nativeEvent: e,
277
- sender: this.prevDropZone(),
278
- });
279
- this.prevDropZone().isHovered.set(false);
675
+ if (this.prevDropZone()) {
676
+ this.prevDropZone().onElementHover.emit({
677
+ dropped: this,
678
+ state: 'leave',
679
+ nativeEvent: e,
680
+ sender: this.prevDropZone(),
681
+ });
682
+ this.prevDropZone().isHovered.set(false);
683
+ this.prevDropZone.set(null);
684
+ }
280
685
  }
281
686
  setPosition(x, y) {
282
687
  let constrainedX = x;
@@ -291,13 +696,10 @@ class AXDragDirective {
291
696
  constrainedX = clamp(x, minX, maxX);
292
697
  constrainedY = clamp(y, minY, maxY);
293
698
  }
294
- const lockAxis = this.dragLockAxis();
295
- if (lockAxis === 'x') {
296
- constrainedY = 0;
297
- }
298
- if (lockAxis === 'y') {
299
- constrainedX = 0;
300
- }
699
+ if (this.dragLockAxis() === 'x')
700
+ constrainedY = this.currentAxis().y;
701
+ if (this.dragLockAxis() === 'y')
702
+ constrainedX = this.currentAxis().x;
301
703
  this.currentAxis.set({ x: constrainedX, y: constrainedY });
302
704
  this.renderer.setStyle(this.element(), 'translate', `${constrainedX}px ${constrainedY}px`);
303
705
  this.dragPositionChanged.emit(this.currentAxis());
@@ -306,43 +708,34 @@ class AXDragDirective {
306
708
  let constrainedX = x;
307
709
  let constrainedY = y;
308
710
  const cloneEl = this.clonedElement();
309
- const boundaryRect = this.boundaryElement()?.getBoundingClientRect();
711
+ const boundaryRect = this.boundaryRect();
310
712
  if (boundaryRect && cloneEl) {
311
713
  const cloneWidth = cloneEl.offsetWidth;
312
714
  const cloneHeight = cloneEl.offsetHeight;
313
- const minAllowedX = boundaryRect.left;
314
- const maxAllowedX = boundaryRect.right - cloneWidth;
315
- const minAllowedY = boundaryRect.top;
316
- const maxAllowedY = boundaryRect.bottom - cloneHeight;
317
- constrainedX = clamp(x, minAllowedX, maxAllowedX);
318
- constrainedY = clamp(y, minAllowedY, maxAllowedY);
319
- }
320
- const lockAxis = this.dragLockAxis();
321
- if (lockAxis === 'x') {
322
- constrainedY = 0;
323
- }
324
- if (lockAxis === 'y') {
325
- constrainedX = 0;
715
+ constrainedX = clamp(x, boundaryRect.left, boundaryRect.right - cloneWidth);
716
+ constrainedY = clamp(y, boundaryRect.top, boundaryRect.bottom - cloneHeight);
326
717
  }
718
+ if (this.dragLockAxis() === 'x')
719
+ constrainedY = this.currentCloneAxis().y;
720
+ if (this.dragLockAxis() === 'y')
721
+ constrainedX = this.currentCloneAxis().x;
327
722
  this.currentCloneAxis.set({ x: constrainedX, y: constrainedY });
328
- this.renderer.setStyle(this.clonedElement(), 'translate', `${constrainedX}px ${constrainedY}px`);
723
+ this.renderer.setStyle(cloneEl, 'translate', `${constrainedX}px ${constrainedY}px`);
329
724
  this.dragPositionChanged.emit(this.currentCloneAxis());
330
725
  }
331
- createCloneElement(originalElement) {
726
+ createCloneElementHandler(originalElement) {
332
727
  if (!isPlatformBrowser(this.platformId)) {
333
728
  this.clonedElement.set(null);
334
729
  return null;
335
730
  }
336
- const clonedElement = originalElement.cloneNode(true);
731
+ let clonedElement;
732
+ const customTemplate = this.dragClonedTemplate();
337
733
  const applyComputedStylesRecursive = (source, target) => {
338
734
  if (!isPlatformBrowser(this.platformId))
339
735
  return;
340
736
  const computedStyles = window.getComputedStyle(source);
341
737
  if (computedStyles.cssText && target.style.cssText !== undefined) {
342
- // Check if cssText is supported and writable
343
- // More efficient path if cssText is fully supported
344
738
  let tempCssText = computedStyles.cssText;
345
- // Remove problematic properties for the ROOT clone before assigning
346
739
  if (target === clonedElement) {
347
740
  tempCssText = tempCssText
348
741
  .replace(/position:[^;]+;/gi, '')
@@ -353,34 +746,21 @@ class AXDragDirective {
353
746
  .replace(/width:[^;]+;/gi, '')
354
747
  .replace(/height:[^;]+;/gi, '')
355
748
  .replace(/margin[^;]*:[^;]+;/gi, '')
749
+ .replace(/transition[^;]*:[^;]+;/gi, '')
356
750
  .replace(/transform:[^;]+;/gi, '')
357
751
  .replace(/translate:[^;]+;/gi, '')
358
752
  .replace(/z-index:[^;]+;/gi, '')
359
753
  .replace(/opacity:[^;]+;/gi, '');
360
754
  }
361
- // For ALL elements in the clone tree, ensure pointer-events is not copied from source,
362
- // as the root clone will have 'pointer-events: none' and we want that to cascade.
363
755
  tempCssText = tempCssText.replace(/pointer-events:[^;]+;/gi, '');
364
- // Prepend existing inline styles (from cloneNode) to the computed styles.
365
- // This gives inline styles higher precedence if there's a conflict not covered by the removals above.
366
- // However, for most cases, we want computed styles to define the look.
367
- // A safer bet might be to set properties individually or fully overwrite.
368
- // For simplicity now, let's assume this ordering is acceptable or refine if needed.
369
- // target.style.cssText = tempCssText + target.style.cssText;
370
- // SAFER: Overwrite with computed, then re-apply critical ones.
371
756
  target.style.cssText = tempCssText;
372
757
  }
373
758
  else {
374
- // Fallback for browsers where cssText is not reliable or for more granular control
375
759
  for (let i = 0; i < computedStyles.length; i++) {
376
760
  const propName = computedStyles[i];
377
- // Universal exclusion:
378
- // For ALL elements in the clone tree (root and children), we don't want to copy 'pointer-events'
379
- // because the root clonedElement will have 'pointer-events: none' set later, and we want that to cascade.
380
761
  if (propName === 'pointer-events') {
381
762
  continue;
382
763
  }
383
- // Specific exclusions for the ROOT clone only, as these are set manually later.
384
764
  if (target === clonedElement &&
385
765
  (propName === 'position' ||
386
766
  propName === 'top' ||
@@ -389,27 +769,22 @@ class AXDragDirective {
389
769
  propName === 'bottom' ||
390
770
  propName === 'width' ||
391
771
  propName === 'height' ||
392
- propName.startsWith('margin') || // Catches margin, margin-top, etc.
772
+ propName.startsWith('margin') ||
773
+ propName.startsWith('transition') ||
393
774
  propName === 'transform' ||
394
775
  propName === 'translate' ||
395
776
  propName === 'z-index' ||
396
777
  propName === 'opacity')) {
397
778
  continue;
398
779
  }
399
- // cssText += `${propName}: ${computedStyles.getPropertyValue(propName)}; `; // Building cssText string
400
- // More robust: set property directly
401
780
  try {
402
781
  target.style.setProperty(propName, computedStyles.getPropertyValue(propName), computedStyles.getPropertyPriority(propName));
403
782
  }
404
783
  catch (e) {
405
- // console.warn(`Could not set style property ${propName} on cloned element`, e);
784
+ console.log(e);
406
785
  }
407
786
  }
408
- // if (!target.style.cssText && cssText) { // only apply if cssText was not directly set
409
- // target.style.cssText = cssText + target.style.cssText;
410
- // }
411
787
  }
412
- // Recursively apply to children
413
788
  const sourceChildren = Array.from(source.children);
414
789
  const targetChildren = Array.from(target.children);
415
790
  for (let i = 0; i < sourceChildren.length; i++) {
@@ -418,43 +793,95 @@ class AXDragDirective {
418
793
  }
419
794
  }
420
795
  };
421
- applyComputedStylesRecursive(originalElement, clonedElement);
796
+ if (customTemplate) {
797
+ const viewRef = this.viewContainerRef.createEmbeddedView(customTemplate);
798
+ this.clonedElementViewRef.set(viewRef);
799
+ if (viewRef.rootNodes.length > 0 && viewRef.rootNodes[0] instanceof HTMLElement) {
800
+ clonedElement = viewRef.rootNodes[0];
801
+ const viewIndex = this.viewContainerRef.indexOf(viewRef);
802
+ if (viewIndex !== -1) {
803
+ this.viewContainerRef.detach(viewIndex);
804
+ }
805
+ }
806
+ else {
807
+ if (this.clonedElementViewRef()) {
808
+ this.clonedElementViewRef().destroy();
809
+ this.clonedElementViewRef.set(null);
810
+ }
811
+ console.warn('AXDragDirective: dragClonedTemplate did not produce a valid HTMLElement root node. Falling back to default cloning.');
812
+ clonedElement = originalElement.cloneNode(true);
813
+ applyComputedStylesRecursive(originalElement, clonedElement);
814
+ }
815
+ }
816
+ else {
817
+ clonedElement = originalElement.cloneNode(true);
818
+ applyComputedStylesRecursive(originalElement, clonedElement);
819
+ }
422
820
  if (clonedElement.id) {
423
821
  this.renderer.removeAttribute(clonedElement, 'id');
424
822
  }
425
- this.renderer.setStyle(originalElement, 'opacity', '0.75');
823
+ this.renderer.setStyle(originalElement, 'opacity', '0.5');
426
824
  const originalRect = originalElement.getBoundingClientRect();
427
825
  this.renderer.setStyle(clonedElement, 'position', 'fixed', RendererStyleFlags2.Important);
428
826
  this.renderer.setStyle(clonedElement, 'left', '0px');
429
827
  this.renderer.setStyle(clonedElement, 'top', '0px');
430
- this.renderer.setStyle(clonedElement, 'width', `${originalRect.width}px`);
431
- this.renderer.setStyle(clonedElement, 'height', `${originalRect.height}px`);
828
+ if (!customTemplate) {
829
+ this.renderer.setStyle(clonedElement, 'width', `${originalRect.width}px`);
830
+ this.renderer.setStyle(clonedElement, 'height', `${originalRect.height}px`);
831
+ }
432
832
  this.renderer.setStyle(clonedElement, 'margin', '0');
433
833
  this.renderer.setStyle(clonedElement, 'box-sizing', 'border-box');
434
834
  this.renderer.setStyle(clonedElement, 'opacity', '0.75');
435
835
  this.renderer.setStyle(clonedElement, 'z-index', '10000');
436
- // This is the crucial part for the ROOT clone.
437
- // Because we prevented 'pointer-events' from being copied in applyComputedStylesRecursive,
438
- // this style will effectively apply to the entire clone tree.
439
836
  this.renderer.setStyle(clonedElement, 'pointer-events', 'none', RendererStyleFlags2.Important);
440
837
  this.renderer.setStyle(clonedElement, 'user-select', 'none');
441
838
  this.renderer.setStyle(clonedElement, 'touch-action', 'none');
442
839
  this.renderer.setStyle(clonedElement, 'translate', `${originalRect.left}px ${originalRect.top}px`);
840
+ this.renderer.removeStyle(clonedElement, 'transition');
841
+ this.renderer.removeStyle(clonedElement, 'transition-property');
443
842
  this.renderer.appendChild(this.document.body, clonedElement);
444
843
  this.clonedElement.set(clonedElement);
445
- this.currentCloneAxis.set({ x: originalRect.left, y: originalRect.top });
844
+ this.setClonePosition(originalRect.left, originalRect.top);
446
845
  return clonedElement;
447
846
  }
847
+ removeCloneElementWithAnimation(x, y, dropList) {
848
+ dropList?._draggableItems().forEach((item) => {
849
+ this.removeElementTransition(item.element());
850
+ });
851
+ const clone = this.clonedElement();
852
+ if (!clone)
853
+ return;
854
+ this.renderer.setStyle(this.element(), 'opacity', this.elementOpacity());
855
+ const elementRect = this.element().getBoundingClientRect();
856
+ if (elementRect) {
857
+ this.setElementTransition(clone);
858
+ this.renderer.setStyle(clone, 'opacity', '0');
859
+ this.setClonePosition(elementRect.left + x, elementRect.top + y);
860
+ }
861
+ if (!this.dragTransition()) {
862
+ this.removeCloneElement();
863
+ }
864
+ else {
865
+ setTimeout(() => {
866
+ this.removeCloneElement();
867
+ dropList?._draggableItems().forEach((item) => {
868
+ this.setElementTransition(item.element());
869
+ });
870
+ }, this.transitionDuration());
871
+ }
872
+ }
448
873
  removeCloneElement() {
449
874
  if (!isPlatformBrowser(this.platformId))
450
875
  return;
451
- this.renderer.setStyle(this.element(), 'opacity', this.elementOpacity());
452
876
  const clone = this.clonedElement();
453
- if (clone && clone.parentNode === this.document.body) {
454
- this.renderer.removeChild(this.document.body, clone);
877
+ if (clone?.parentNode) {
878
+ this.renderer.removeChild(clone.parentNode, clone);
455
879
  }
456
880
  this.clonedElement.set(null);
457
- this.currentCloneAxis.set({ x: 0, y: 0 });
881
+ if (this.clonedElementViewRef()) {
882
+ this.clonedElementViewRef().destroy();
883
+ this.clonedElementViewRef.set(null);
884
+ }
458
885
  this.cdr.markForCheck();
459
886
  }
460
887
  addDocumentListeners() {
@@ -475,10 +902,10 @@ class AXDragDirective {
475
902
  this.document.removeEventListener('pointercancel', this.boundHandlePointerUp);
476
903
  });
477
904
  }
478
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: AXDragDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
479
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "20.0.3", type: AXDragDirective, isStandalone: true, selector: "[axDrag]", inputs: { dragData: { classPropertyName: "dragData", publicName: "dragData", isSignal: true, isRequired: false, transformFunction: null }, dragDisabled: { classPropertyName: "dragDisabled", publicName: "dragDisabled", isSignal: true, isRequired: false, transformFunction: null }, dragElementClone: { classPropertyName: "dragElementClone", publicName: "dragElementClone", isSignal: true, isRequired: false, transformFunction: null }, dropZoneGroup: { classPropertyName: "dropZoneGroup", publicName: "dropZoneGroup", isSignal: true, isRequired: false, transformFunction: null }, dragStartDelay: { classPropertyName: "dragStartDelay", publicName: "dragStartDelay", isSignal: true, isRequired: false, transformFunction: null }, dragResetOnDblClick: { classPropertyName: "dragResetOnDblClick", publicName: "dragResetOnDblClick", isSignal: true, isRequired: false, transformFunction: null }, dragLockAxis: { classPropertyName: "dragLockAxis", publicName: "dragLockAxis", isSignal: true, isRequired: false, transformFunction: null }, dragCursor: { classPropertyName: "dragCursor", publicName: "dragCursor", isSignal: true, isRequired: false, transformFunction: null }, dragBoundary: { classPropertyName: "dragBoundary", publicName: "dragBoundary", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dragPositionChanged: "dragPositionChanged" }, queries: [{ propertyName: "handleDirective", first: true, predicate: AXDragHandleDirective, descendants: true, isSignal: true }], ngImport: i0 }); }
905
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: AXDragDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
906
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "20.0.4", type: AXDragDirective, isStandalone: true, selector: "[axDrag]", inputs: { dragData: { classPropertyName: "dragData", publicName: "dragData", isSignal: true, isRequired: false, transformFunction: null }, dragDisabled: { classPropertyName: "dragDisabled", publicName: "dragDisabled", isSignal: true, isRequired: false, transformFunction: null }, dragTransition: { classPropertyName: "dragTransition", publicName: "dragTransition", isSignal: true, isRequired: false, transformFunction: null }, dragElementClone: { classPropertyName: "dragElementClone", publicName: "dragElementClone", isSignal: true, isRequired: false, transformFunction: null }, dropZoneGroup: { classPropertyName: "dropZoneGroup", publicName: "dropZoneGroup", isSignal: true, isRequired: false, transformFunction: null }, dragStartDelay: { classPropertyName: "dragStartDelay", publicName: "dragStartDelay", isSignal: true, isRequired: false, transformFunction: null }, dragResetOnDblClick: { classPropertyName: "dragResetOnDblClick", publicName: "dragResetOnDblClick", isSignal: true, isRequired: false, transformFunction: null }, dragLockAxis: { classPropertyName: "dragLockAxis", publicName: "dragLockAxis", isSignal: true, isRequired: false, transformFunction: null }, dragClonedTemplate: { classPropertyName: "dragClonedTemplate", publicName: "dragClonedTemplate", isSignal: true, isRequired: false, transformFunction: null }, dragCursor: { classPropertyName: "dragCursor", publicName: "dragCursor", isSignal: true, isRequired: false, transformFunction: null }, dragBoundary: { classPropertyName: "dragBoundary", publicName: "dragBoundary", isSignal: true, isRequired: false, transformFunction: null }, dragTransitionDuration: { classPropertyName: "dragTransitionDuration", publicName: "dragTransitionDuration", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dragPositionChanged: "dragPositionChanged" }, queries: [{ propertyName: "handleDirective", first: true, predicate: AXDragHandleDirective, descendants: true, isSignal: true }], ngImport: i0 }); }
480
907
  }
481
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: AXDragDirective, decorators: [{
908
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: AXDragDirective, decorators: [{
482
909
  type: Directive,
483
910
  args: [{
484
911
  selector: '[axDrag]',
@@ -495,12 +922,12 @@ class AXDropZoneDirective extends NXComponent {
495
922
  this.onElementHover = output();
496
923
  }
497
924
  ngOnInit() {
498
- this.element().dataset['dropZone'] = 'true';
925
+ this.element().dataset['axDropZone'] = 'true';
499
926
  }
500
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: AXDropZoneDirective, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
501
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.0.3", type: AXDropZoneDirective, isStandalone: true, selector: "[axDropZone]", inputs: { dropZoneGroup: { classPropertyName: "dropZoneGroup", publicName: "dropZoneGroup", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onElementDrop: "onElementDrop", onElementHover: "onElementHover" }, exportAs: ["axDropZone"], usesInheritance: true, ngImport: i0 }); }
927
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: AXDropZoneDirective, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
928
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.0.4", type: AXDropZoneDirective, isStandalone: true, selector: "[axDropZone]", inputs: { dropZoneGroup: { classPropertyName: "dropZoneGroup", publicName: "dropZoneGroup", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onElementDrop: "onElementDrop", onElementHover: "onElementHover" }, exportAs: ["axDropZone"], usesInheritance: true, ngImport: i0 }); }
502
929
  }
503
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: AXDropZoneDirective, decorators: [{
930
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: AXDropZoneDirective, decorators: [{
504
931
  type: Directive,
505
932
  args: [{
506
933
  selector: '[axDropZone]',
@@ -510,11 +937,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImpor
510
937
 
511
938
  const COMPONENT = [AXDragDirective, AXDragHandleDirective, AXDropZoneDirective];
512
939
  class AXDragDropModule {
513
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: AXDragDropModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
514
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.0.3", ngImport: i0, type: AXDragDropModule, imports: [AXDragDirective, AXDragHandleDirective, AXDropZoneDirective], exports: [AXDragDirective, AXDragHandleDirective, AXDropZoneDirective] }); }
515
- static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: AXDragDropModule }); }
940
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: AXDragDropModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
941
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.0.4", ngImport: i0, type: AXDragDropModule, imports: [AXDragDirective, AXDragHandleDirective, AXDropZoneDirective], exports: [AXDragDirective, AXDragHandleDirective, AXDropZoneDirective] }); }
942
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: AXDragDropModule }); }
516
943
  }
517
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: AXDragDropModule, decorators: [{
944
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: AXDragDropModule, decorators: [{
518
945
  type: NgModule,
519
946
  args: [{
520
947
  imports: [...COMPONENT],
@@ -523,9 +950,43 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImpor
523
950
  }]
524
951
  }] });
525
952
 
953
+ /**
954
+ * Moves an item one index in an array to another.
955
+ * @param array Array in which to move the item.
956
+ * @param fromIndex Starting index of the item.
957
+ * @param toIndex Index to which the item should be moved.
958
+ */
959
+ function moveItemInArray(array, fromIndex, toIndex) {
960
+ const from = clamp(fromIndex, array.length - 1);
961
+ const to = clamp(toIndex, array.length - 1);
962
+ if (from === to) {
963
+ return;
964
+ }
965
+ const target = array[from];
966
+ const delta = to < from ? -1 : 1;
967
+ for (let i = from; i !== to; i += delta) {
968
+ array[i] = array[i + delta];
969
+ }
970
+ array[to] = target;
971
+ }
972
+ /**
973
+ * Moves an item from one array to another.
974
+ * @param currentArray Array from which to transfer the item.
975
+ * @param targetArray Array into which to put the item.
976
+ * @param currentIndex Index of the item in its current array.
977
+ * @param targetIndex Index at which to insert the item.
978
+ */
979
+ function transferArrayItem(currentArray, targetArray, currentIndex, targetIndex) {
980
+ const from = clamp(currentIndex, currentArray.length - 1);
981
+ const to = clamp(targetIndex, targetArray.length);
982
+ if (currentArray.length) {
983
+ targetArray.splice(to, 0, currentArray.splice(from, 1)[0]);
984
+ }
985
+ }
986
+
526
987
  /**
527
988
  * Generated bundle index. Do not edit.
528
989
  */
529
990
 
530
- export { AXDragDirective, AXDragDropModule, AXDragHandleDirective, AXDropZoneDirective };
991
+ export { AXDragDirective, AXDragDropModule, AXDragHandleDirective, AXDropListDirective, AXDropZoneDirective, moveItemInArray, transferArrayItem };
531
992
  //# sourceMappingURL=acorex-cdk-drag-drop.mjs.map