@acorex/cdk 22.0.0 → 22.0.1-next.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/acorex-cdk-carousel.mjs +22 -4
- package/fesm2022/acorex-cdk-carousel.mjs.map +1 -1
- package/fesm2022/acorex-cdk-common.mjs +78 -2
- package/fesm2022/acorex-cdk-common.mjs.map +1 -1
- package/fesm2022/acorex-cdk-drag-drop.mjs +182 -51
- package/fesm2022/acorex-cdk-drag-drop.mjs.map +1 -1
- package/fesm2022/acorex-cdk-full-screen.mjs +24 -145
- package/fesm2022/acorex-cdk-full-screen.mjs.map +1 -1
- package/fesm2022/acorex-cdk-gesture.mjs +34 -5
- package/fesm2022/acorex-cdk-gesture.mjs.map +1 -1
- package/fesm2022/acorex-cdk-highlight.mjs +108 -0
- package/fesm2022/acorex-cdk-highlight.mjs.map +1 -0
- package/fesm2022/acorex-cdk-horizontal-scroll.mjs +102 -42
- package/fesm2022/acorex-cdk-horizontal-scroll.mjs.map +1 -1
- package/fesm2022/acorex-cdk-shimmer.mjs +220 -0
- package/fesm2022/acorex-cdk-shimmer.mjs.map +1 -0
- package/package.json +10 -6
- package/shimmer/README.md +11 -0
- package/types/acorex-cdk-carousel.d.ts +2 -0
- package/types/acorex-cdk-common.d.ts +18 -1
- package/types/acorex-cdk-drag-drop.d.ts +28 -3
- package/types/acorex-cdk-full-screen.d.ts +18 -43
- package/types/acorex-cdk-gesture.d.ts +13 -1
- package/types/acorex-cdk-highlight.d.ts +54 -0
- package/types/acorex-cdk-horizontal-scroll.d.ts +23 -9
- package/types/acorex-cdk-shimmer.d.ts +68 -0
- package/fesm2022/acorex-cdk-double-click.mjs +0 -178
- package/fesm2022/acorex-cdk-double-click.mjs.map +0 -1
- package/types/acorex-cdk-double-click.d.ts +0 -66
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { inject, ElementRef, signal, Directive, NgZone, Renderer2, ChangeDetectorRef, PLATFORM_ID, input, output, contentChildren, DOCUMENT, ViewContainerRef, contentChild,
|
|
2
|
+
import { inject, ElementRef, signal, Directive, NgZone, Renderer2, ChangeDetectorRef, PLATFORM_ID, input, output, contentChildren, linkedSignal, DOCUMENT, ViewContainerRef, contentChild, 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';
|
|
6
|
+
import { AXHtmlUtil } from '@acorex/core/utils';
|
|
6
7
|
|
|
7
8
|
class AXDragHandleDirective {
|
|
8
9
|
constructor() {
|
|
@@ -52,6 +53,8 @@ class AXDropListDirective extends NXComponent {
|
|
|
52
53
|
...(ngDevMode ? [{ debugName: "dropListOrientation" }] : /* istanbul ignore next */ []));
|
|
53
54
|
/** Emits when an item is dropped into the list. */
|
|
54
55
|
this.dropListDropped = output();
|
|
56
|
+
/** Emits when the sort preview transforms change during an active drag. */
|
|
57
|
+
this.sortPreviewChanged = output();
|
|
55
58
|
/** The `axDrag` directives that are direct children of this list. */
|
|
56
59
|
this._draggableItems = contentChildren(AXDragDirective, { ...(ngDevMode ? { debugName: "_draggableItems" } : /* istanbul ignore next */ {}), descendants: false });
|
|
57
60
|
// --- Internal State Management ---
|
|
@@ -72,8 +75,15 @@ class AXDropListDirective extends NXComponent {
|
|
|
72
75
|
/** The detected `gap` of the list for the current orientation. */
|
|
73
76
|
this._listGap = signal(0, /* @ts-ignore */
|
|
74
77
|
...(ngDevMode ? [{ debugName: "_listGap" }] : /* istanbul ignore next */ []));
|
|
75
|
-
/**
|
|
76
|
-
this.
|
|
78
|
+
/** Whether the list is in RTL direction (cached at drag start). */
|
|
79
|
+
this._isRtl = signal(false, /* @ts-ignore */
|
|
80
|
+
...(ngDevMode ? [{ debugName: "_isRtl" }] : /* istanbul ignore next */ []));
|
|
81
|
+
/** Internal orientation state; can be overridden programmatically by host components. */
|
|
82
|
+
this.orientation = linkedSignal(() => this.dropListOrientation(), /* @ts-ignore */
|
|
83
|
+
...(ngDevMode ? [{ debugName: "orientation" }] : /* istanbul ignore next */ []));
|
|
84
|
+
/** Internal sorting-disabled state; can be overridden programmatically by host components. */
|
|
85
|
+
this.isSortingDisabled = linkedSignal(() => this.sortingDisabled(), /* @ts-ignore */
|
|
86
|
+
...(ngDevMode ? [{ debugName: "isSortingDisabled" }] : /* istanbul ignore next */ []));
|
|
77
87
|
/** DOM placeholder element for inter-list drags */
|
|
78
88
|
this._placeholderElement = null;
|
|
79
89
|
}
|
|
@@ -97,12 +107,16 @@ class AXDropListDirective extends NXComponent {
|
|
|
97
107
|
isDragActiveForThisList(dragItem) {
|
|
98
108
|
return this._activeDragItem() === dragItem;
|
|
99
109
|
}
|
|
110
|
+
/** Whether the list is horizontal and in RTL direction. */
|
|
111
|
+
isHorizontalRtl() {
|
|
112
|
+
return this.orientation() === 'horizontal' && this._isRtl();
|
|
113
|
+
}
|
|
100
114
|
/**
|
|
101
115
|
* Prepares the list for sorting when a drag operation starts from within this list.
|
|
102
116
|
* @param dragItem The item that is being dragged.
|
|
103
117
|
*/
|
|
104
118
|
prepareSort(dragItem) {
|
|
105
|
-
if (!this.axDropList() || this.
|
|
119
|
+
if (!this.axDropList() || this.isSortingDisabled() || this._activeDragItem() || dragItem.isDragDisabled())
|
|
106
120
|
return;
|
|
107
121
|
this._activeDragItem.set(dragItem);
|
|
108
122
|
this.element.classList.add('ax-drop-list-sorting-active');
|
|
@@ -119,7 +133,7 @@ class AXDropListDirective extends NXComponent {
|
|
|
119
133
|
* @param dragItem The item entering this list.
|
|
120
134
|
*/
|
|
121
135
|
enter(dragItem) {
|
|
122
|
-
if (!this.axDropList() || this.
|
|
136
|
+
if (!this.axDropList() || this.isSortingDisabled() || this.isDragActiveForThisList(dragItem))
|
|
123
137
|
return;
|
|
124
138
|
// Clean up any existing placeholder from previous list
|
|
125
139
|
this._removePlaceholderElement();
|
|
@@ -135,10 +149,10 @@ class AXDropListDirective extends NXComponent {
|
|
|
135
149
|
sort(event, dragItem) {
|
|
136
150
|
if (!this.axDropList() ||
|
|
137
151
|
!this.isDragActiveForThisList(dragItem) ||
|
|
138
|
-
this.
|
|
152
|
+
this.isSortingDisabled() ||
|
|
139
153
|
!this._listInitialRect())
|
|
140
154
|
return;
|
|
141
|
-
const pointerPosition = this.
|
|
155
|
+
const pointerPosition = this.orientation() === 'vertical' ? event.clientY : event.clientX;
|
|
142
156
|
const newPlaceholderIndex = this._calculatePlaceholderIndex(pointerPosition);
|
|
143
157
|
if (this._placeholderIndex() !== newPlaceholderIndex) {
|
|
144
158
|
this._placeholderIndex.set(newPlaceholderIndex);
|
|
@@ -152,7 +166,7 @@ class AXDropListDirective extends NXComponent {
|
|
|
152
166
|
* @param sourceList The list where the drag originated.
|
|
153
167
|
*/
|
|
154
168
|
finalizeSort(event, droppedItem, sourceList) {
|
|
155
|
-
if (!this.axDropList() || !this.isDragActiveForThisList(droppedItem) || this.
|
|
169
|
+
if (!this.axDropList() || !this.isDragActiveForThisList(droppedItem) || this.isSortingDisabled()) {
|
|
156
170
|
this.resetSortStateAndStyles(sourceList);
|
|
157
171
|
return;
|
|
158
172
|
}
|
|
@@ -197,8 +211,11 @@ class AXDropListDirective extends NXComponent {
|
|
|
197
211
|
/** Caches the geometry of the list and its items at the start of a drag. */
|
|
198
212
|
_cacheGeometry() {
|
|
199
213
|
this._listInitialRect.set(this.element.getBoundingClientRect());
|
|
214
|
+
this._isRtl.set(AXHtmlUtil.isRtl(this.element));
|
|
200
215
|
this._detectAndCacheListGap();
|
|
201
|
-
const items = this._draggableItems()
|
|
216
|
+
const items = [...this._draggableItems()]
|
|
217
|
+
.sort((a, b) => a.element().compareDocumentPosition(b.element()) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1)
|
|
218
|
+
.map((itemDraggable) => {
|
|
202
219
|
const el = itemDraggable.element();
|
|
203
220
|
const style = window.getComputedStyle(el);
|
|
204
221
|
const rect = el.getBoundingClientRect();
|
|
@@ -226,7 +243,7 @@ class AXDropListDirective extends NXComponent {
|
|
|
226
243
|
const gapParts = gapValue.split(' ');
|
|
227
244
|
const rowGap = parseFloat(gapParts[0]);
|
|
228
245
|
const columnGap = parseFloat(gapParts[1] || gapParts[0]);
|
|
229
|
-
this._listGap.set(this.
|
|
246
|
+
this._listGap.set(this.orientation() === 'vertical' ? rowGap : columnGap);
|
|
230
247
|
}
|
|
231
248
|
else {
|
|
232
249
|
this._listGap.set(0);
|
|
@@ -246,16 +263,19 @@ class AXDropListDirective extends NXComponent {
|
|
|
246
263
|
const cachedItems = this._cachedItems();
|
|
247
264
|
const originalIndex = cachedItems.findIndex((d) => d.item === activeItem);
|
|
248
265
|
const siblings = cachedItems.filter((d) => d.item !== activeItem);
|
|
249
|
-
const scrollDelta = this.
|
|
266
|
+
const scrollDelta = this.orientation() === 'vertical'
|
|
250
267
|
? this.element.getBoundingClientRect().top - listRect.top
|
|
251
268
|
: this.element.getBoundingClientRect().left - listRect.left;
|
|
252
269
|
let newIndexInSiblings = -1;
|
|
253
270
|
for (let i = 0; i < siblings.length; i++) {
|
|
254
271
|
const sibling = siblings[i];
|
|
255
|
-
const itemMidPoint = (this.
|
|
272
|
+
const itemMidPoint = (this.orientation() === 'vertical' ? sibling.initialRect.top : sibling.initialRect.left) +
|
|
256
273
|
scrollDelta +
|
|
257
|
-
(this.
|
|
258
|
-
|
|
274
|
+
(this.orientation() === 'vertical' ? sibling.height : sibling.width) / 2;
|
|
275
|
+
const isBeforeSibling = this.isHorizontalRtl()
|
|
276
|
+
? pointerPosition > itemMidPoint
|
|
277
|
+
: pointerPosition < itemMidPoint;
|
|
278
|
+
if (isBeforeSibling) {
|
|
259
279
|
newIndexInSiblings = i;
|
|
260
280
|
break;
|
|
261
281
|
}
|
|
@@ -274,7 +294,7 @@ class AXDropListDirective extends NXComponent {
|
|
|
274
294
|
const end = Math.max(originalIndex, potentialPlaceholderIndex);
|
|
275
295
|
for (let i = start; i < end; i++) {
|
|
276
296
|
const itemData = cachedItems[i];
|
|
277
|
-
if (itemData.item !== activeItem && itemData.item.
|
|
297
|
+
if (itemData.item !== activeItem && itemData.item.isDragDisabled()) {
|
|
278
298
|
// We've hit a disabled "wall". Stop the placeholder at the boundary.
|
|
279
299
|
if (potentialPlaceholderIndex > originalIndex) {
|
|
280
300
|
return i; // Dragging down/right: stop *before* the wall.
|
|
@@ -301,19 +321,24 @@ class AXDropListDirective extends NXComponent {
|
|
|
301
321
|
else {
|
|
302
322
|
// --- INTRA-LIST DRAG: Use transforms (works well for same-list reordering) ---
|
|
303
323
|
this._removePlaceholderElement();
|
|
304
|
-
const getItemSpace = (itemData) => this.
|
|
324
|
+
const getItemSpace = (itemData) => this.orientation() === 'vertical'
|
|
305
325
|
? itemData.height + itemData.margins.top + itemData.margins.bottom
|
|
306
326
|
: itemData.width + itemData.margins.left + itemData.margins.right;
|
|
307
327
|
const draggedItemSize = isIntraListDrag ? getItemSpace(this._cachedItems()[originalIndex]) : 0;
|
|
328
|
+
const axisSign = this.isHorizontalRtl() ? -1 : 1;
|
|
308
329
|
this._cachedItems().forEach((data, index) => {
|
|
309
|
-
if (data.item.
|
|
330
|
+
if (data.item.isDragDisabled()) {
|
|
310
331
|
this._renderer.removeStyle(data.element, 'transform');
|
|
311
332
|
return;
|
|
312
333
|
}
|
|
313
334
|
const transform = this._calculateTransform(index, originalIndex, draggedItemSize, getItemSpace);
|
|
314
|
-
|
|
335
|
+
const signedTransform = transform * axisSign;
|
|
336
|
+
this._renderer.setStyle(data.element, 'transform', transform
|
|
337
|
+
? `${this.orientation() === 'vertical' ? 'translateY' : 'translateX'}(${signedTransform}px)`
|
|
338
|
+
: '');
|
|
315
339
|
});
|
|
316
340
|
}
|
|
341
|
+
this.sortPreviewChanged.emit();
|
|
317
342
|
}
|
|
318
343
|
/** Creates or moves the placeholder element for inter-list drags */
|
|
319
344
|
_updatePlaceholderElement(activeItem, targetIndex) {
|
|
@@ -423,6 +448,7 @@ class AXDropListDirective extends NXComponent {
|
|
|
423
448
|
_resetAllTransforms() {
|
|
424
449
|
this._cachedItems().forEach((data) => this._renderer.setStyle(data.element, 'transform', ''));
|
|
425
450
|
this._removePlaceholderElement(); // Clean up inter-list placeholder
|
|
451
|
+
this.sortPreviewChanged.emit();
|
|
426
452
|
}
|
|
427
453
|
/** Resets the internal state of the directive to its initial values. */
|
|
428
454
|
resetSortState() {
|
|
@@ -434,7 +460,7 @@ class AXDropListDirective extends NXComponent {
|
|
|
434
460
|
this._listGap.set(0);
|
|
435
461
|
}
|
|
436
462
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXDropListDirective, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
|
|
437
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "22.0.8", type: AXDropListDirective, isStandalone: true, selector: "[axDropList]", inputs: { axDropList: { classPropertyName: "axDropList", publicName: "axDropList", isSignal: true, isRequired: false, transformFunction: null }, 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 }); }
|
|
463
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "22.0.8", type: AXDropListDirective, isStandalone: true, selector: "[axDropList]", inputs: { axDropList: { classPropertyName: "axDropList", publicName: "axDropList", isSignal: true, isRequired: false, transformFunction: null }, 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", sortPreviewChanged: "sortPreviewChanged" }, queries: [{ propertyName: "_draggableItems", predicate: AXDragDirective, isSignal: true }], exportAs: ["axDropList"], usesInheritance: true, ngImport: i0 }); }
|
|
438
464
|
}
|
|
439
465
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXDropListDirective, decorators: [{
|
|
440
466
|
type: Directive,
|
|
@@ -442,7 +468,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
442
468
|
selector: '[axDropList]',
|
|
443
469
|
exportAs: 'axDropList',
|
|
444
470
|
}]
|
|
445
|
-
}], propDecorators: { axDropList: [{ type: i0.Input, args: [{ isSignal: true, alias: "axDropList", required: false }] }], sortingDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "sortingDisabled", required: false }] }], dropListGroup: [{ type: i0.Input, args: [{ isSignal: true, alias: "dropListGroup", required: false }] }], dropListOrientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "dropListOrientation", required: false }] }], dropListDropped: [{ type: i0.Output, args: ["dropListDropped"] }], _draggableItems: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => AXDragDirective), { ...{ descendants: false }, isSignal: true }] }] } });
|
|
471
|
+
}], propDecorators: { axDropList: [{ type: i0.Input, args: [{ isSignal: true, alias: "axDropList", required: false }] }], sortingDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "sortingDisabled", required: false }] }], dropListGroup: [{ type: i0.Input, args: [{ isSignal: true, alias: "dropListGroup", required: false }] }], dropListOrientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "dropListOrientation", required: false }] }], dropListDropped: [{ type: i0.Output, args: ["dropListDropped"] }], sortPreviewChanged: [{ type: i0.Output, args: ["sortPreviewChanged"] }], _draggableItems: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => AXDragDirective), { ...{ descendants: false }, isSignal: true }] }] } });
|
|
446
472
|
|
|
447
473
|
// Zone detection constants for nested drop lists (tree nodes)
|
|
448
474
|
const ZONE_TOP_THRESHOLD = 0.3; // Top 30% triggers reorder BEFORE
|
|
@@ -484,6 +510,18 @@ class AXDragDirective {
|
|
|
484
510
|
...(ngDevMode ? [undefined, { debugName: "dragBoundary" }] : /* istanbul ignore next */ []));
|
|
485
511
|
this.dragTransitionDuration = input(150, /* @ts-ignore */
|
|
486
512
|
...(ngDevMode ? [{ debugName: "dragTransitionDuration" }] : /* istanbul ignore next */ []));
|
|
513
|
+
this.isDragDisabled = linkedSignal(() => this.dragDisabled(), /* @ts-ignore */
|
|
514
|
+
...(ngDevMode ? [{ debugName: "isDragDisabled" }] : /* istanbul ignore next */ []));
|
|
515
|
+
this.lockAxis = linkedSignal(() => this.dragLockAxis(), /* @ts-ignore */
|
|
516
|
+
...(ngDevMode ? [{ debugName: "lockAxis" }] : /* istanbul ignore next */ []));
|
|
517
|
+
this.dragBoundaryOverride = linkedSignal(() => this.dragBoundary(), /* @ts-ignore */
|
|
518
|
+
...(ngDevMode ? [{ debugName: "dragBoundaryOverride" }] : /* istanbul ignore next */ []));
|
|
519
|
+
this.startDelay = linkedSignal(() => this.dragStartDelay() ?? 0, /* @ts-ignore */
|
|
520
|
+
...(ngDevMode ? [{ debugName: "startDelay" }] : /* istanbul ignore next */ []));
|
|
521
|
+
this.dragTouchAction = linkedSignal(() => 'none', /* @ts-ignore */
|
|
522
|
+
...(ngDevMode ? [{ debugName: "dragTouchAction" }] : /* istanbul ignore next */ []));
|
|
523
|
+
this.dragCursorOverride = linkedSignal(() => this.dragCursor(), /* @ts-ignore */
|
|
524
|
+
...(ngDevMode ? [{ debugName: "dragCursorOverride" }] : /* istanbul ignore next */ []));
|
|
487
525
|
this.dragPositionChanged = output();
|
|
488
526
|
this.isMoving = signal(false, /* @ts-ignore */
|
|
489
527
|
...(ngDevMode ? [{ debugName: "isMoving" }] : /* istanbul ignore next */ []));
|
|
@@ -511,19 +549,25 @@ class AXDragDirective {
|
|
|
511
549
|
...(ngDevMode ? [{ debugName: "prevDropZone" }] : /* istanbul ignore next */ []));
|
|
512
550
|
this.dragStartOffset = signal({ x: 0, y: 0 }, /* @ts-ignore */
|
|
513
551
|
...(ngDevMode ? [{ debugName: "dragStartOffset" }] : /* istanbul ignore next */ []));
|
|
552
|
+
this.pointerDownPosition = signal({ x: 0, y: 0 }, /* @ts-ignore */
|
|
553
|
+
...(ngDevMode ? [{ debugName: "pointerDownPosition" }] : /* istanbul ignore next */ []));
|
|
514
554
|
this.clonePointerOffset = signal({ x: 0, y: 0 }, /* @ts-ignore */
|
|
515
555
|
...(ngDevMode ? [{ debugName: "clonePointerOffset" }] : /* istanbul ignore next */ []));
|
|
516
556
|
this.clonedElementViewRef = signal(null, /* @ts-ignore */
|
|
517
557
|
...(ngDevMode ? [{ debugName: "clonedElementViewRef" }] : /* istanbul ignore next */ []));
|
|
518
558
|
this.rafId = null;
|
|
519
559
|
this.pendingPointerEvent = null;
|
|
560
|
+
this.savedBodyCursor = null;
|
|
561
|
+
this.holdDelayTimer = null;
|
|
562
|
+
this.holdDelayReady = signal(false, /* @ts-ignore */
|
|
563
|
+
...(ngDevMode ? [{ debugName: "holdDelayReady" }] : /* istanbul ignore next */ []));
|
|
520
564
|
this._parentDropList = inject(AXDropListDirective, { optional: true, skipSelf: true, host: false });
|
|
521
565
|
this._currentDropList = signal(null, /* @ts-ignore */
|
|
522
566
|
...(ngDevMode ? [{ debugName: "_currentDropList" }] : /* istanbul ignore next */ []));
|
|
523
567
|
this.createCloneElement = computed(() => this.dragElementClone() || !!this._parentDropList, /* @ts-ignore */
|
|
524
568
|
...(ngDevMode ? [{ debugName: "createCloneElement" }] : /* istanbul ignore next */ []));
|
|
525
569
|
this.boundaryElement = computed(() => {
|
|
526
|
-
const boundary = this.
|
|
570
|
+
const boundary = this.dragBoundaryOverride();
|
|
527
571
|
if (!boundary) {
|
|
528
572
|
return null;
|
|
529
573
|
}
|
|
@@ -556,17 +600,25 @@ class AXDragDirective {
|
|
|
556
600
|
this.listenersAttached = signal(null, /* @ts-ignore */
|
|
557
601
|
...(ngDevMode ? [{ debugName: "listenersAttached" }] : /* istanbul ignore next */ []));
|
|
558
602
|
this.#dragDisabledEffect = effect(() => {
|
|
559
|
-
|
|
603
|
+
const cursor = this.dragCursorOverride();
|
|
604
|
+
const disabled = this.isDragDisabled();
|
|
605
|
+
const handle = this.handle();
|
|
606
|
+
if (disabled || cursor === 'none') {
|
|
607
|
+
if (!this.isMoving() && !this.holdDelayReady()) {
|
|
608
|
+
this.renderer.removeStyle(handle, 'cursor');
|
|
609
|
+
}
|
|
610
|
+
if (disabled) {
|
|
611
|
+
this.renderer.removeStyle(handle, 'touch-action');
|
|
612
|
+
}
|
|
613
|
+
else {
|
|
614
|
+
this.renderer.setStyle(handle, 'touch-action', this.dragTouchAction());
|
|
615
|
+
}
|
|
560
616
|
return;
|
|
561
617
|
}
|
|
562
|
-
if (!this.
|
|
563
|
-
this.renderer.setStyle(
|
|
564
|
-
this.renderer.setStyle(this.handle(), 'touch-action', 'none');
|
|
565
|
-
}
|
|
566
|
-
else {
|
|
567
|
-
this.renderer.removeStyle(this.handle(), 'cursor');
|
|
568
|
-
this.renderer.removeStyle(this.handle(), 'touch-action');
|
|
618
|
+
if (!this.isMoving() && !this.holdDelayReady()) {
|
|
619
|
+
this.renderer.setStyle(handle, 'cursor', cursor);
|
|
569
620
|
}
|
|
621
|
+
this.renderer.setStyle(handle, 'touch-action', this.dragTouchAction());
|
|
570
622
|
}, /* @ts-ignore */
|
|
571
623
|
...(ngDevMode ? [{ debugName: "#dragDisabledEffect" }] : /* istanbul ignore next */ []));
|
|
572
624
|
this.#handleChangeEffect = effect(() => {
|
|
@@ -597,7 +649,6 @@ class AXDragDirective {
|
|
|
597
649
|
if (this._parentDropList) {
|
|
598
650
|
this.setElementTransition(this.element());
|
|
599
651
|
}
|
|
600
|
-
this.renderer.setStyle(this.element(), 'z-index', '1');
|
|
601
652
|
this.elementOpacity.set(getComputedStyle(this.element()).opacity);
|
|
602
653
|
}
|
|
603
654
|
}
|
|
@@ -615,7 +666,56 @@ class AXDragDirective {
|
|
|
615
666
|
if (this._parentDropList && this.isDragging()) {
|
|
616
667
|
this._parentDropList.cancelSort();
|
|
617
668
|
}
|
|
669
|
+
this.clearActiveDragCursor();
|
|
670
|
+
this.clearHoldDelayTimer();
|
|
671
|
+
this.renderer.removeStyle(this.element(), 'z-index');
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
resolveDropCursor(canDrop) {
|
|
675
|
+
if (this.dragCursorOverride() === 'grab') {
|
|
676
|
+
return canDrop ? 'grabbing' : 'not-allowed';
|
|
618
677
|
}
|
|
678
|
+
return canDrop ? 'move' : 'not-allowed';
|
|
679
|
+
}
|
|
680
|
+
setActiveDragCursor(cursor) {
|
|
681
|
+
if (!isPlatformBrowser(this.platformId))
|
|
682
|
+
return;
|
|
683
|
+
if (this.savedBodyCursor === null) {
|
|
684
|
+
this.savedBodyCursor = this.document.body.style.cursor;
|
|
685
|
+
}
|
|
686
|
+
this.document.body.style.cursor = cursor;
|
|
687
|
+
}
|
|
688
|
+
clearActiveDragCursor() {
|
|
689
|
+
if (!isPlatformBrowser(this.platformId) || this.savedBodyCursor === null)
|
|
690
|
+
return;
|
|
691
|
+
this.document.body.style.cursor = this.savedBodyCursor;
|
|
692
|
+
this.savedBodyCursor = null;
|
|
693
|
+
}
|
|
694
|
+
clearHoldDelayTimer() {
|
|
695
|
+
if (this.holdDelayTimer !== null) {
|
|
696
|
+
clearTimeout(this.holdDelayTimer);
|
|
697
|
+
this.holdDelayTimer = null;
|
|
698
|
+
}
|
|
699
|
+
this.holdDelayReady.set(false);
|
|
700
|
+
}
|
|
701
|
+
scheduleHoldDelayFeedback() {
|
|
702
|
+
this.clearHoldDelayTimer();
|
|
703
|
+
const delay = this.startDelay();
|
|
704
|
+
if (delay <= 0 || this.dragCursorOverride() !== 'grab') {
|
|
705
|
+
return;
|
|
706
|
+
}
|
|
707
|
+
this.holdDelayTimer = setTimeout(() => {
|
|
708
|
+
this.holdDelayTimer = null;
|
|
709
|
+
if (!this.isDragging() || this.isMoving() || this.isDragDisabled()) {
|
|
710
|
+
return;
|
|
711
|
+
}
|
|
712
|
+
this.holdDelayReady.set(true);
|
|
713
|
+
this.renderer.setStyle(this.handle(), 'cursor', 'grabbing');
|
|
714
|
+
this.setActiveDragCursor('grabbing');
|
|
715
|
+
}, delay);
|
|
716
|
+
}
|
|
717
|
+
setElementDropCursor(element, cursor) {
|
|
718
|
+
this.renderer.setStyle(element, 'cursor', cursor);
|
|
619
719
|
}
|
|
620
720
|
setElementTransition(element) {
|
|
621
721
|
this.renderer.setStyle(element, 'transition-property', 'transform, opacity, translate');
|
|
@@ -628,24 +728,23 @@ class AXDragDirective {
|
|
|
628
728
|
handlePointerDown(e) {
|
|
629
729
|
if (!isPlatformBrowser(this.platformId))
|
|
630
730
|
return;
|
|
631
|
-
if (!this.axDrag() || this.
|
|
731
|
+
if (!this.axDrag() || this.isDragDisabled() || e.button !== 0 || this._parentDropList?.isSortingDisabled())
|
|
632
732
|
return;
|
|
633
733
|
this.isDragging.set(true);
|
|
634
734
|
this.movedAfterDelay.set(false);
|
|
635
|
-
if (this.
|
|
735
|
+
if (this.dragCursorOverride() === 'move') {
|
|
636
736
|
this.renderer.setStyle(this.handle(), 'cursor', 'move');
|
|
637
737
|
}
|
|
638
|
-
else if (this.dragCursor() === 'grab') {
|
|
639
|
-
this.renderer.setStyle(this.handle(), 'cursor', 'grabbing');
|
|
640
|
-
}
|
|
641
738
|
this.dragStartOffset.set({ x: e.clientX - this.currentAxis().x, y: e.clientY - this.currentAxis().y });
|
|
739
|
+
this.pointerDownPosition.set({ x: e.clientX, y: e.clientY });
|
|
642
740
|
this.renderer.setStyle(this.handle(), 'userSelect', 'none');
|
|
643
741
|
this.activePointerId.set(e.pointerId);
|
|
644
742
|
this.addDocumentListeners();
|
|
645
743
|
this.dragStartTime.set(Date.now());
|
|
744
|
+
this.scheduleHoldDelayFeedback();
|
|
646
745
|
}
|
|
647
746
|
handleDblClick() {
|
|
648
|
-
if (!this.dragResetOnDblClick() || this.
|
|
747
|
+
if (!this.dragResetOnDblClick() || this.isDragDisabled())
|
|
649
748
|
return;
|
|
650
749
|
this.setPosition(0, 0);
|
|
651
750
|
}
|
|
@@ -653,17 +752,26 @@ class AXDragDirective {
|
|
|
653
752
|
if (!this.isDragging() || !isPlatformBrowser(this.platformId) || e.pointerId !== this.activePointerId()) {
|
|
654
753
|
return;
|
|
655
754
|
}
|
|
656
|
-
e.preventDefault();
|
|
657
755
|
if (!this.isMoving()) {
|
|
658
|
-
const delay = this.
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
756
|
+
const delay = this.startDelay();
|
|
757
|
+
const down = this.pointerDownPosition();
|
|
758
|
+
const movedX = e.clientX - down.x;
|
|
759
|
+
const movedY = e.clientY - down.y;
|
|
760
|
+
const movedDistance = Math.sqrt(movedX * movedX + movedY * movedY);
|
|
761
|
+
if (delay > 0 && !this.holdDelayReady() && Date.now() - this.dragStartTime() < delay) {
|
|
762
|
+
if (movedDistance > 8) {
|
|
763
|
+
this.abortDragSequence();
|
|
764
|
+
}
|
|
765
|
+
return;
|
|
662
766
|
}
|
|
767
|
+
e.preventDefault();
|
|
663
768
|
this.isMoving.set(true);
|
|
664
769
|
this.handle().setPointerCapture(e.pointerId);
|
|
665
770
|
this.startDrag(e);
|
|
666
771
|
}
|
|
772
|
+
else {
|
|
773
|
+
e.preventDefault();
|
|
774
|
+
}
|
|
667
775
|
// Run position updates outside Angular zone for better performance
|
|
668
776
|
this.zone.runOutsideAngular(() => {
|
|
669
777
|
if (this.createCloneElement()) {
|
|
@@ -694,7 +802,24 @@ class AXDragDirective {
|
|
|
694
802
|
this.dropZoneHoverHandler(e);
|
|
695
803
|
}
|
|
696
804
|
}
|
|
805
|
+
abortDragSequence() {
|
|
806
|
+
this.clearHoldDelayTimer();
|
|
807
|
+
this.isDragging.set(false);
|
|
808
|
+
this.isMoving.set(false);
|
|
809
|
+
this.activePointerId.set(null);
|
|
810
|
+
this.removeDocumentListeners();
|
|
811
|
+
this.renderer.removeStyle(this.handle(), 'userSelect');
|
|
812
|
+
if (this.dragCursorOverride() === 'grab') {
|
|
813
|
+
this.renderer.setStyle(this.handle(), 'cursor', 'grab');
|
|
814
|
+
}
|
|
815
|
+
this.clearActiveDragCursor();
|
|
816
|
+
}
|
|
697
817
|
startDrag(e) {
|
|
818
|
+
if (this.dragCursorOverride() === 'grab') {
|
|
819
|
+
this.renderer.setStyle(this.handle(), 'cursor', 'grabbing');
|
|
820
|
+
this.setActiveDragCursor('grabbing');
|
|
821
|
+
}
|
|
822
|
+
this.renderer.setStyle(this.element(), 'z-index', '1');
|
|
698
823
|
// Add CDK-style classes
|
|
699
824
|
this.renderer.addClass(this.element(), 'ax-dragging');
|
|
700
825
|
this.renderer.addClass(this.element(), 'ax-drag-placeholder');
|
|
@@ -722,9 +847,11 @@ class AXDragDirective {
|
|
|
722
847
|
if (e.pointerId !== this.activePointerId() || !isPlatformBrowser(this.platformId) || !this.isDragging()) {
|
|
723
848
|
return;
|
|
724
849
|
}
|
|
725
|
-
|
|
850
|
+
this.clearHoldDelayTimer();
|
|
851
|
+
if (this.dragCursorOverride() === 'grab') {
|
|
726
852
|
this.renderer.setStyle(this.handle(), 'cursor', 'grab');
|
|
727
853
|
}
|
|
854
|
+
this.clearActiveDragCursor();
|
|
728
855
|
const wasMoving = this.isMoving();
|
|
729
856
|
this.isMoving.set(false);
|
|
730
857
|
this.isDragging.set(false);
|
|
@@ -738,6 +865,7 @@ class AXDragDirective {
|
|
|
738
865
|
this.renderer.removeStyle(this.handle(), 'userSelect');
|
|
739
866
|
return;
|
|
740
867
|
}
|
|
868
|
+
this.renderer.removeStyle(this.element(), 'z-index');
|
|
741
869
|
this.preventClicking();
|
|
742
870
|
const transform = this.element().style.transform;
|
|
743
871
|
let x = 0;
|
|
@@ -792,12 +920,15 @@ class AXDragDirective {
|
|
|
792
920
|
// Update cursor based on whether drop is allowed
|
|
793
921
|
if (listUnderPointer) {
|
|
794
922
|
const cloneEl = this.clonedElement();
|
|
795
|
-
const cursor = canDrop
|
|
796
|
-
if (
|
|
797
|
-
this.
|
|
923
|
+
const cursor = this.resolveDropCursor(!!canDrop);
|
|
924
|
+
if (this.dragCursorOverride() === 'grab') {
|
|
925
|
+
this.setActiveDragCursor(cursor);
|
|
926
|
+
}
|
|
927
|
+
else if (cloneEl) {
|
|
928
|
+
this.setElementDropCursor(cloneEl, cursor);
|
|
798
929
|
}
|
|
799
930
|
else {
|
|
800
|
-
this.
|
|
931
|
+
this.setElementDropCursor(this.element(), cursor);
|
|
801
932
|
}
|
|
802
933
|
}
|
|
803
934
|
if (targetList !== previousList) {
|
|
@@ -815,7 +946,7 @@ class AXDragDirective {
|
|
|
815
946
|
this._currentDropList()?.sort(e, this);
|
|
816
947
|
}
|
|
817
948
|
canDropInList(list) {
|
|
818
|
-
if (!list || list.
|
|
949
|
+
if (!list || list.isSortingDisabled() || !this._parentDropList) {
|
|
819
950
|
return false;
|
|
820
951
|
}
|
|
821
952
|
if (list === this._parentDropList) {
|
|
@@ -959,9 +1090,9 @@ class AXDragDirective {
|
|
|
959
1090
|
constrainedX = clamp(x, minX, maxX);
|
|
960
1091
|
constrainedY = clamp(y, minY, maxY);
|
|
961
1092
|
}
|
|
962
|
-
if (this.
|
|
1093
|
+
if (this.lockAxis() === 'x')
|
|
963
1094
|
constrainedY = this.currentAxis().y;
|
|
964
|
-
if (this.
|
|
1095
|
+
if (this.lockAxis() === 'y')
|
|
965
1096
|
constrainedX = this.currentAxis().x;
|
|
966
1097
|
// Direct DOM manipulation without triggering change detection
|
|
967
1098
|
this.renderer.setStyle(this.element(), 'translate', `${constrainedX}px ${constrainedY}px`);
|
|
@@ -983,9 +1114,9 @@ class AXDragDirective {
|
|
|
983
1114
|
constrainedX = clamp(x, boundaryRect.left, boundaryRect.right - cloneWidth);
|
|
984
1115
|
constrainedY = clamp(y, boundaryRect.top, boundaryRect.bottom - cloneHeight);
|
|
985
1116
|
}
|
|
986
|
-
if (this.
|
|
1117
|
+
if (this.lockAxis() === 'x')
|
|
987
1118
|
constrainedY = this.currentCloneAxis().y;
|
|
988
|
-
if (this.
|
|
1119
|
+
if (this.lockAxis() === 'y')
|
|
989
1120
|
constrainedX = this.currentCloneAxis().x;
|
|
990
1121
|
// Direct DOM manipulation without triggering change detection
|
|
991
1122
|
this.renderer.setStyle(cloneEl, 'translate', `${constrainedX}px ${constrainedY}px`);
|