ngx-kit 8.0.1 → 8.1.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/ngx-kit-core.mjs +1 -1
- package/fesm2022/ngx-kit-core.mjs.map +1 -1
- package/fesm2022/ngx-kit-drag-resize.mjs +291 -178
- package/fesm2022/ngx-kit-drag-resize.mjs.map +1 -1
- package/fesm2022/ngx-kit-infinite-scroll.mjs +4 -1
- package/fesm2022/ngx-kit-infinite-scroll.mjs.map +1 -1
- package/fesm2022/ngx-kit-message.mjs +43 -91
- package/fesm2022/ngx-kit-message.mjs.map +1 -1
- package/package.json +1 -1
- package/types/ngx-kit-drag-resize.d.ts +53 -33
- package/types/ngx-kit-message.d.ts +9 -25
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { signal, EventEmitter, Injectable, InjectionToken, model, input, output,
|
|
2
|
+
import { signal, EventEmitter, Injectable, InjectionToken, inject, ApplicationRef, Directive, model, input, output, Renderer2, effect, ContentChild, Input, HostListener, Output, ElementRef } from '@angular/core';
|
|
3
3
|
import { DOCUMENT } from '@angular/common';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -79,103 +79,87 @@ function adjustForZoom(value) {
|
|
|
79
79
|
return zoom ? value / zoom : value;
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
/**
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
82
|
+
/** Above any app chrome (modals, sticky headers) but below the browser's own UI. */
|
|
83
|
+
const PREVIEW_Z_INDEX = '2147483000';
|
|
84
|
+
class DragPreviewRef {
|
|
85
|
+
tpl;
|
|
86
|
+
/** Set by `ngxDragPreview` so the embedded view can join Angular's change-detection tree. */
|
|
87
|
+
appRef;
|
|
88
|
+
element;
|
|
89
|
+
isCustom = false;
|
|
90
|
+
_view;
|
|
91
|
+
attach(dragEl, rect) {
|
|
92
|
+
const doc = dragEl.ownerDocument;
|
|
93
|
+
if (this.tpl) {
|
|
94
|
+
this._view = this.tpl.createEmbeddedView({});
|
|
95
|
+
this.appRef?.attachView(this._view);
|
|
96
|
+
// Render bindings inside the embedded view before we move its DOM nodes.
|
|
97
|
+
this._view.detectChanges();
|
|
98
|
+
const element = this._view.rootNodes.find((node) => node.nodeType === Node.ELEMENT_NODE);
|
|
99
|
+
if (!element) {
|
|
100
|
+
this.appRef?.detachView(this._view);
|
|
101
|
+
this._view.destroy();
|
|
102
|
+
this._view = undefined;
|
|
103
|
+
throw new Error('ngxDragPreview template must contain exactly one HTMLElement root node ');
|
|
104
|
+
}
|
|
105
|
+
this.element = element;
|
|
106
|
+
this.isCustom = true;
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
this.isCustom = false;
|
|
110
|
+
const preview = dragEl.cloneNode(true);
|
|
111
|
+
this.element = preview;
|
|
112
|
+
// Avoid duplicated ids in the document.
|
|
113
|
+
this.element.removeAttribute('id');
|
|
114
|
+
this.element.querySelectorAll('[id]').forEach((n) => n.removeAttribute('id'));
|
|
115
|
+
this.element.classList.add('ngx-drag-preview');
|
|
116
|
+
this.element.setAttribute('aria-hidden', 'true');
|
|
117
|
+
this.element.setAttribute('inert', '');
|
|
118
|
+
Object.assign(this.element.style, {
|
|
119
|
+
width: `${rect.width}px`,
|
|
120
|
+
height: `${rect.height}px`,
|
|
121
|
+
margin: '0',
|
|
122
|
+
boxSizing: 'border-box',
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
Object.assign(this.element.style, {
|
|
126
|
+
position: 'fixed',
|
|
127
|
+
top: `${rect.top}px`,
|
|
128
|
+
bottom: 'auto',
|
|
129
|
+
pointerEvents: 'none',
|
|
130
|
+
transition: 'none',
|
|
131
|
+
animation: 'none',
|
|
132
|
+
transform: 'none',
|
|
133
|
+
visibility: 'visible',
|
|
134
|
+
display: this.element.style.display === 'none' ? '' : this.element.style.display,
|
|
135
|
+
willChange: 'transform',
|
|
136
|
+
zIndex: PREVIEW_Z_INDEX,
|
|
137
|
+
});
|
|
138
|
+
if (isRtl(doc.body)) {
|
|
139
|
+
Object.assign(this.element.style, {
|
|
140
|
+
right: `${window.innerWidth - rect.right}px`,
|
|
141
|
+
left: 'auto',
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
Object.assign(this.element.style, {
|
|
146
|
+
left: `${rect.left}px`,
|
|
147
|
+
right: 'auto',
|
|
148
|
+
});
|
|
103
149
|
}
|
|
150
|
+
doc.body.appendChild(this.element);
|
|
151
|
+
return this.element;
|
|
104
152
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
const count = Math.min(sourceChildren.length, targetChildren.length);
|
|
114
|
-
for (let i = 0; i < count; i++) {
|
|
115
|
-
copyStyleValues(sourceChildren[i], targetChildren[i]);
|
|
116
|
-
copyDescendants(sourceChildren[i], targetChildren[i]);
|
|
153
|
+
detach() {
|
|
154
|
+
this.element?.remove();
|
|
155
|
+
if (this._view) {
|
|
156
|
+
this.appRef?.detachView(this._view);
|
|
157
|
+
this._view.destroy();
|
|
158
|
+
this._view = undefined;
|
|
159
|
+
}
|
|
160
|
+
this.element = undefined;
|
|
117
161
|
}
|
|
118
162
|
}
|
|
119
|
-
/** Backward-compatible helper retained for consumers of older versions. */
|
|
120
|
-
function copyEssentialStyles(source, target) {
|
|
121
|
-
copyComputedStyle(source, target);
|
|
122
|
-
target.style.setProperty('box-sizing', 'border-box');
|
|
123
|
-
}
|
|
124
|
-
function combineTransforms(transform, initialTransform) {
|
|
125
|
-
return initialTransform && initialTransform !== 'none'
|
|
126
|
-
? transform + ' ' + initialTransform
|
|
127
|
-
: transform;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/** Above any app chrome (modals, sticky headers) but below the browser's own UI. */
|
|
131
|
-
const PREVIEW_Z_INDEX = '2147483000';
|
|
132
|
-
/**
|
|
133
|
-
* Creates the visual that follows the pointer while an item of a drop list is dragged.
|
|
134
|
-
*
|
|
135
|
-
* It is appended to `<body>` with `position: fixed`, so no ancestor of the original item
|
|
136
|
-
* (`overflow: hidden`, scroll containers, clipping, transformed/positioned parents) can clip
|
|
137
|
-
* or offset it. Computed styles are copied recursively first, because once the clone leaves
|
|
138
|
-
* its list every selector that depended on an ancestor (`.column .card {}`) and every
|
|
139
|
-
* inherited property (font, colour, `direction`) would otherwise be lost.
|
|
140
|
-
*
|
|
141
|
-
* Only used for drop-list drags. Free drag never calls this.
|
|
142
|
-
*/
|
|
143
|
-
function cloneDragElementInBody(dragEl, rect, pointerX, pointerY) {
|
|
144
|
-
const doc = dragEl.ownerDocument;
|
|
145
|
-
const preview = dragEl.cloneNode(true);
|
|
146
|
-
// Avoid duplicated ids in the document.
|
|
147
|
-
preview.removeAttribute('id');
|
|
148
|
-
preview.querySelectorAll('[id]').forEach((n) => n.removeAttribute('id'));
|
|
149
|
-
preview.classList.add('ngx-drag-preview');
|
|
150
|
-
preview.setAttribute('aria-hidden', 'true');
|
|
151
|
-
preview.setAttribute('inert', '');
|
|
152
|
-
copyComputedStyleTree(dragEl, preview);
|
|
153
|
-
Object.assign(preview.style, {
|
|
154
|
-
position: 'fixed',
|
|
155
|
-
top: `${rect.top}px`,
|
|
156
|
-
left: `${rect.left}px`,
|
|
157
|
-
right: 'auto',
|
|
158
|
-
bottom: 'auto',
|
|
159
|
-
width: `${rect.width}px`,
|
|
160
|
-
height: `${rect.height}px`,
|
|
161
|
-
margin: '0',
|
|
162
|
-
pointerEvents: 'none',
|
|
163
|
-
boxSizing: 'border-box',
|
|
164
|
-
transition: 'none',
|
|
165
|
-
animation: 'none',
|
|
166
|
-
transform: 'none',
|
|
167
|
-
visibility: 'visible',
|
|
168
|
-
display: preview.style.display === 'none' ? '' : preview.style.display,
|
|
169
|
-
willChange: 'transform',
|
|
170
|
-
zIndex: PREVIEW_Z_INDEX,
|
|
171
|
-
});
|
|
172
|
-
doc.body.appendChild(preview);
|
|
173
|
-
return {
|
|
174
|
-
element: preview,
|
|
175
|
-
offsetX: pointerX - rect.left,
|
|
176
|
-
offsetY: pointerY - rect.top,
|
|
177
|
-
};
|
|
178
|
-
}
|
|
179
163
|
|
|
180
164
|
let zIndexCounter = 1000;
|
|
181
165
|
class DragRef {
|
|
@@ -196,6 +180,7 @@ class DragRef {
|
|
|
196
180
|
placeholder;
|
|
197
181
|
originDropList = null;
|
|
198
182
|
originIndex = -1;
|
|
183
|
+
preview;
|
|
199
184
|
isDragging = signal(false, /* @ts-ignore */
|
|
200
185
|
...(ngDevMode ? [{ debugName: "isDragging" }] : /* istanbul ignore next */ []));
|
|
201
186
|
position = signal({ x: 0, y: 0 }, /* @ts-ignore */
|
|
@@ -208,9 +193,6 @@ class DragRef {
|
|
|
208
193
|
moveDx = 0;
|
|
209
194
|
moveDy = 0;
|
|
210
195
|
scrollCompensation = { x: 0, y: 0 };
|
|
211
|
-
preview;
|
|
212
|
-
previewOffsetX = 0;
|
|
213
|
-
previewOffsetY = 0;
|
|
214
196
|
sourceVisibility = '';
|
|
215
197
|
sourceDisplay = '';
|
|
216
198
|
sourcePointerEvents = '';
|
|
@@ -283,12 +265,8 @@ class DragRef {
|
|
|
283
265
|
*/
|
|
284
266
|
if (list) {
|
|
285
267
|
this.listDrag = true;
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
const preview = cloneDragElementInBody(this.el, this.startRect, pointer.x, pointer.y);
|
|
289
|
-
this.preview = preview.element;
|
|
290
|
-
this.previewOffsetX = preview.offsetX;
|
|
291
|
-
this.previewOffsetY = preview.offsetY;
|
|
268
|
+
this.preview ??= new DragPreviewRef();
|
|
269
|
+
this.preview.attach(this.el, this.startRect);
|
|
292
270
|
this.el.style.visibility = 'hidden';
|
|
293
271
|
this.el.style.display = 'none';
|
|
294
272
|
this.el.style.pointerEvents = 'none';
|
|
@@ -350,7 +328,7 @@ class DragRef {
|
|
|
350
328
|
this.isDragging.set(false);
|
|
351
329
|
this.placeholder?.detach();
|
|
352
330
|
this.placeholder = undefined;
|
|
353
|
-
this.preview?.
|
|
331
|
+
this.preview?.detach();
|
|
354
332
|
this.preview = undefined;
|
|
355
333
|
this.el.classList.remove('ngx-draggable--dragging');
|
|
356
334
|
this.el.style.visibility = this.sourceVisibility;
|
|
@@ -564,7 +542,7 @@ class DragRef {
|
|
|
564
542
|
const event = target?._finish(this, true) ?? null;
|
|
565
543
|
for (const l of this.cachedLists)
|
|
566
544
|
l._release(this);
|
|
567
|
-
this.preview?.
|
|
545
|
+
this.preview?.detach();
|
|
568
546
|
this.preview = undefined;
|
|
569
547
|
this.placeholder = undefined;
|
|
570
548
|
this.activeDropList = null;
|
|
@@ -584,9 +562,9 @@ class DragRef {
|
|
|
584
562
|
target.onDrop.emit(event);
|
|
585
563
|
}
|
|
586
564
|
updatePreview() {
|
|
587
|
-
if (!this.preview)
|
|
565
|
+
if (!this.preview || !this.preview.element)
|
|
588
566
|
return;
|
|
589
|
-
this.preview.style.transform = `translate3d(${this.moveDx}px, ${this.moveDy}px, 0)`;
|
|
567
|
+
this.preview.element.style.transform = `translate3d(${this.moveDx}px, ${this.moveDy}px, 0)`;
|
|
590
568
|
}
|
|
591
569
|
}
|
|
592
570
|
/** Is `list` nested (at any depth) inside `ancestor`, per the parent/child list tree? */
|
|
@@ -598,18 +576,64 @@ function isDescendantOfList(list, ancestor) {
|
|
|
598
576
|
return false;
|
|
599
577
|
}
|
|
600
578
|
|
|
579
|
+
class ElementHelper {
|
|
580
|
+
static collectionHas(a, b) {
|
|
581
|
+
//helper function (see below)
|
|
582
|
+
for (var i = 0, len = a.length; i < len; i++) {
|
|
583
|
+
if (a[i] == b)
|
|
584
|
+
return true;
|
|
585
|
+
}
|
|
586
|
+
return false;
|
|
587
|
+
}
|
|
588
|
+
static findParentBySelector(elm, selector) {
|
|
589
|
+
var all = document.querySelectorAll(selector);
|
|
590
|
+
var cur = elm.parentNode;
|
|
591
|
+
while (cur && !ElementHelper.collectionHas(all, cur)) {
|
|
592
|
+
//keep going up until you find a match
|
|
593
|
+
cur = cur.parentNode; //go up
|
|
594
|
+
}
|
|
595
|
+
return cur; //will return null if not found
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
function getFirstLevelDraggables(container) {
|
|
599
|
+
const all = Array.from(container.querySelectorAll('.ngx-draggable:not(.dragging)'));
|
|
600
|
+
const firstLevel = [];
|
|
601
|
+
for (const el of all) {
|
|
602
|
+
let parent = el.parentElement;
|
|
603
|
+
let isNested = false;
|
|
604
|
+
while (parent && parent !== container) {
|
|
605
|
+
if (parent.classList.contains('ngx-draggable')) {
|
|
606
|
+
isNested = true;
|
|
607
|
+
break;
|
|
608
|
+
}
|
|
609
|
+
parent = parent.parentElement;
|
|
610
|
+
}
|
|
611
|
+
if (!isNested) {
|
|
612
|
+
firstLevel.push(el);
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
return firstLevel;
|
|
616
|
+
}
|
|
617
|
+
function isElementNode(node) {
|
|
618
|
+
return node?.nodeType === Node.ELEMENT_NODE;
|
|
619
|
+
}
|
|
620
|
+
function isDocumentNode(node) {
|
|
621
|
+
return node?.nodeType === Node.DOCUMENT_NODE;
|
|
622
|
+
}
|
|
623
|
+
function isShadowRootNode(node) {
|
|
624
|
+
return node?.nodeType === Node.DOCUMENT_FRAGMENT_NODE && 'host' in node;
|
|
625
|
+
}
|
|
626
|
+
function getOwnerWindow(node) {
|
|
627
|
+
return node?.ownerDocument?.defaultView ?? null;
|
|
628
|
+
}
|
|
629
|
+
function isWindow(value) {
|
|
630
|
+
return (value != null &&
|
|
631
|
+
typeof value === 'object' &&
|
|
632
|
+
'window' in value &&
|
|
633
|
+
value.window === value);
|
|
634
|
+
}
|
|
635
|
+
|
|
601
636
|
class PlaceHolderRef {
|
|
602
|
-
/**
|
|
603
|
-
* Custom placeholder content, from `*ngxPlaceholder` inside the `ngxDropList`. When unset,
|
|
604
|
-
* `attach()` falls back to a shallow clone of the dragged element (previous behaviour).
|
|
605
|
-
*
|
|
606
|
-
* Example:
|
|
607
|
-
*
|
|
608
|
-
* <div ngxDropList>
|
|
609
|
-
* <span class="my-placeholder" *ngxPlaceholder></span>
|
|
610
|
-
* ...
|
|
611
|
-
* </div>
|
|
612
|
-
*/
|
|
613
637
|
tpl;
|
|
614
638
|
/** Set by `NgxPlaceholder` so the embedded view can join Angular's change-detection tree. */
|
|
615
639
|
appRef;
|
|
@@ -626,7 +650,7 @@ class PlaceHolderRef {
|
|
|
626
650
|
this.appRef?.attachView(this._view);
|
|
627
651
|
// Render bindings inside the embedded view before we move its DOM nodes.
|
|
628
652
|
this._view.detectChanges();
|
|
629
|
-
const element = this._view.rootNodes.find((node) => node
|
|
653
|
+
const element = this._view.rootNodes.find((node) => isElementNode(node));
|
|
630
654
|
if (!element) {
|
|
631
655
|
this.appRef?.detachView(this._view);
|
|
632
656
|
this._view.destroy();
|
|
@@ -1142,14 +1166,15 @@ class SortSession {
|
|
|
1142
1166
|
let slot = -1;
|
|
1143
1167
|
let allOthers = 0;
|
|
1144
1168
|
for (const node of Array.from(this.container.children)) {
|
|
1145
|
-
if (!(node
|
|
1169
|
+
if (!isElementNode(node))
|
|
1146
1170
|
continue;
|
|
1147
|
-
const
|
|
1148
|
-
|
|
1171
|
+
const el = node;
|
|
1172
|
+
const isSlot = el === this.placeholder;
|
|
1173
|
+
if (!isSlot && !this.itemElements.has(el))
|
|
1149
1174
|
continue;
|
|
1150
1175
|
const modelIdx = isSlot ? -1 : allOthers++;
|
|
1151
|
-
const rect =
|
|
1152
|
-
const off = this.applied.get(
|
|
1176
|
+
const rect = el.getBoundingClientRect();
|
|
1177
|
+
const off = this.applied.get(el);
|
|
1153
1178
|
const box = toBox(rect);
|
|
1154
1179
|
if (off) {
|
|
1155
1180
|
// Strip our own displacement so the snapshot always describes the *undisplaced* layout.
|
|
@@ -1165,14 +1190,14 @@ class SortSession {
|
|
|
1165
1190
|
slot = entries.length;
|
|
1166
1191
|
else
|
|
1167
1192
|
otherModelIndex.push(modelIdx);
|
|
1168
|
-
const known = previous.get(
|
|
1193
|
+
const known = previous.get(el);
|
|
1169
1194
|
entries.push(known ?? {
|
|
1170
|
-
el:
|
|
1195
|
+
el: el,
|
|
1171
1196
|
isSlot,
|
|
1172
|
-
base: initialTransform(
|
|
1173
|
-
savedTransform:
|
|
1174
|
-
savedTransition:
|
|
1175
|
-
savedWillChange:
|
|
1197
|
+
base: initialTransform(el),
|
|
1198
|
+
savedTransform: el.style.transform,
|
|
1199
|
+
savedTransition: el.style.transition,
|
|
1200
|
+
savedWillChange: el.style.willChange,
|
|
1176
1201
|
});
|
|
1177
1202
|
boxes.push(box);
|
|
1178
1203
|
}
|
|
@@ -1752,12 +1777,15 @@ class DropListRef {
|
|
|
1752
1777
|
const els = [];
|
|
1753
1778
|
const boxes = [];
|
|
1754
1779
|
for (const node of Array.from(this.el.children)) {
|
|
1755
|
-
if (!(node
|
|
1780
|
+
if (!isElementNode(node))
|
|
1781
|
+
continue;
|
|
1782
|
+
const el = node;
|
|
1783
|
+
if (!others.has(el))
|
|
1756
1784
|
continue;
|
|
1757
|
-
const r =
|
|
1785
|
+
const r = el.getBoundingClientRect();
|
|
1758
1786
|
if (r.width === 0 && r.height === 0)
|
|
1759
1787
|
continue;
|
|
1760
|
-
els.push(
|
|
1788
|
+
els.push(el);
|
|
1761
1789
|
boxes.push(toBox(r));
|
|
1762
1790
|
}
|
|
1763
1791
|
if (!els.length)
|
|
@@ -1782,15 +1810,16 @@ class DropListRef {
|
|
|
1782
1810
|
byElement.set(d.el, d);
|
|
1783
1811
|
let index = 0;
|
|
1784
1812
|
for (const node of Array.from(this.el.children)) {
|
|
1785
|
-
if (!(node
|
|
1813
|
+
if (!isElementNode(node))
|
|
1786
1814
|
continue;
|
|
1787
|
-
|
|
1815
|
+
const el = node;
|
|
1816
|
+
if (el === this.placeholder?.element)
|
|
1788
1817
|
continue;
|
|
1789
|
-
if (
|
|
1818
|
+
if (el.classList.contains('ngx-drag-placeholder'))
|
|
1790
1819
|
continue;
|
|
1791
|
-
if (
|
|
1820
|
+
if (el.classList.contains('ngx-drag-preview'))
|
|
1792
1821
|
continue;
|
|
1793
|
-
const ref = byElement.get(
|
|
1822
|
+
const ref = byElement.get(el);
|
|
1794
1823
|
if (!ref)
|
|
1795
1824
|
continue;
|
|
1796
1825
|
if (ref === item)
|
|
@@ -1887,19 +1916,6 @@ class DragDropService {
|
|
|
1887
1916
|
...(ngDevMode ? [{ debugName: "dropLists" }] : /* istanbul ignore next */ []));
|
|
1888
1917
|
activeDrag = signal(null, /* @ts-ignore */
|
|
1889
1918
|
...(ngDevMode ? [{ debugName: "activeDrag" }] : /* istanbul ignore next */ []));
|
|
1890
|
-
/**
|
|
1891
|
-
* DOM-position registries, used to find the nearest enclosing list/group by walking real
|
|
1892
|
-
* ancestor elements instead of Angular's element-injector tree.
|
|
1893
|
-
*
|
|
1894
|
-
* This matters for `ngTemplateOutlet`-based recursive trees (a list of items whose own
|
|
1895
|
-
* children are rendered by re-invoking the SAME `<ng-template>`, as in a tree/outliner UI):
|
|
1896
|
-
* each invocation gets a FRESH embedded view whose injector context is wherever the outlet
|
|
1897
|
-
* was written in the template, not wherever its content ends up in the DOM. So `inject(TOKEN,
|
|
1898
|
-
* {skipSelf})` from one recursion level can never see a provider from another level — the
|
|
1899
|
-
* only fix within Angular's own DI is to manually thread `ngTemplateOutletInjector` through
|
|
1900
|
-
* every recursive call, which isn't reasonable to require of every consumer of this library.
|
|
1901
|
-
* A plain DOM walk has no such limitation: it only cares where elements actually ended up.
|
|
1902
|
-
*/
|
|
1903
1919
|
listsByEl = new Map();
|
|
1904
1920
|
groupsByEl = new Map();
|
|
1905
1921
|
registerDragItem(ref) {
|
|
@@ -1928,19 +1944,59 @@ class DragDropService {
|
|
|
1928
1944
|
}
|
|
1929
1945
|
/** Nearest registered drop list starting at (and including) `start`, walking up the DOM. */
|
|
1930
1946
|
findAncestorDropList(start) {
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
if (
|
|
1934
|
-
|
|
1947
|
+
let node = start;
|
|
1948
|
+
while (node) {
|
|
1949
|
+
if (isElementNode(node)) {
|
|
1950
|
+
const found = this.listsByEl.get(node);
|
|
1951
|
+
if (found) {
|
|
1952
|
+
return found;
|
|
1953
|
+
}
|
|
1954
|
+
}
|
|
1955
|
+
if (isShadowRootNode(node) && 'host' in node) {
|
|
1956
|
+
node = node.host;
|
|
1957
|
+
continue;
|
|
1958
|
+
}
|
|
1959
|
+
if (isDocumentNode(node)) {
|
|
1960
|
+
const frame = node.defaultView?.frameElement;
|
|
1961
|
+
if (frame) {
|
|
1962
|
+
node = frame;
|
|
1963
|
+
continue;
|
|
1964
|
+
}
|
|
1965
|
+
break;
|
|
1966
|
+
}
|
|
1967
|
+
node = node.parentNode;
|
|
1935
1968
|
}
|
|
1936
1969
|
return null;
|
|
1937
1970
|
}
|
|
1938
1971
|
/** Nearest registered drop-list group starting at (and including) `start`, walking up the DOM. */
|
|
1939
1972
|
findAncestorGroup(start) {
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1973
|
+
let node = start;
|
|
1974
|
+
while (node) {
|
|
1975
|
+
// HTMLElement / SVGElement / ...
|
|
1976
|
+
if (isElementNode(node)) {
|
|
1977
|
+
const found = this.groupsByEl.get(node);
|
|
1978
|
+
if (found) {
|
|
1979
|
+
return found;
|
|
1980
|
+
}
|
|
1981
|
+
}
|
|
1982
|
+
// ShadowRoot
|
|
1983
|
+
// ShadowRoot یک DocumentFragment است و در iframe ممکن است
|
|
1984
|
+
if (isShadowRootNode(node) && 'host' in node && node.host) {
|
|
1985
|
+
node = node.host;
|
|
1986
|
+
continue;
|
|
1987
|
+
}
|
|
1988
|
+
// iframe Document
|
|
1989
|
+
// 9 === DOCUMENT_NODE
|
|
1990
|
+
if (node.nodeType === 9) {
|
|
1991
|
+
const frame = node.defaultView?.frameElement;
|
|
1992
|
+
if (frame) {
|
|
1993
|
+
node = frame;
|
|
1994
|
+
continue;
|
|
1995
|
+
}
|
|
1996
|
+
// root document
|
|
1997
|
+
break;
|
|
1998
|
+
}
|
|
1999
|
+
node = node.parentNode;
|
|
1944
2000
|
}
|
|
1945
2001
|
return null;
|
|
1946
2002
|
}
|
|
@@ -2049,15 +2105,16 @@ class AutoScroller {
|
|
|
2049
2105
|
this.raf = 0;
|
|
2050
2106
|
return;
|
|
2051
2107
|
}
|
|
2052
|
-
|
|
2053
|
-
|
|
2108
|
+
const container = this.container;
|
|
2109
|
+
if (isWindow(container)) {
|
|
2110
|
+
container.scrollBy(this.speed.x, this.speed.y);
|
|
2054
2111
|
}
|
|
2055
2112
|
else {
|
|
2056
|
-
|
|
2057
|
-
|
|
2113
|
+
container.scrollLeft += this.speed.x;
|
|
2114
|
+
container.scrollTop += this.speed.y;
|
|
2058
2115
|
}
|
|
2059
|
-
//
|
|
2060
|
-
//
|
|
2116
|
+
// Pointer ثابت مانده ولی محتوا اسکرول شده؛
|
|
2117
|
+
// بنابراین موقعیت placeholder/sort را دوباره محاسبه کن.
|
|
2061
2118
|
this.onTick?.();
|
|
2062
2119
|
this.raf = requestAnimationFrame(this.tick);
|
|
2063
2120
|
};
|
|
@@ -2070,7 +2127,7 @@ function edgeSpeed(pos, min, max, edge, maxSpeed) {
|
|
|
2070
2127
|
return 0;
|
|
2071
2128
|
}
|
|
2072
2129
|
function getScrollRect(container) {
|
|
2073
|
-
if (container
|
|
2130
|
+
if (isWindow(container)) {
|
|
2074
2131
|
return { left: 0, top: 0, right: window.innerWidth, bottom: window.innerHeight };
|
|
2075
2132
|
}
|
|
2076
2133
|
return container.getBoundingClientRect();
|
|
@@ -2080,19 +2137,53 @@ function findScrollableAncestor(el) {
|
|
|
2080
2137
|
while (node) {
|
|
2081
2138
|
const style = getComputedStyle(node);
|
|
2082
2139
|
const scrollable = /(auto|scroll|overlay)/.test(style.overflowY + style.overflowX);
|
|
2083
|
-
if (scrollable && node.scrollHeight > node.clientHeight)
|
|
2140
|
+
if (scrollable && node.scrollHeight > node.clientHeight) {
|
|
2084
2141
|
return node;
|
|
2142
|
+
}
|
|
2085
2143
|
node = node.parentElement;
|
|
2086
2144
|
}
|
|
2087
|
-
return window;
|
|
2145
|
+
return el.ownerDocument.defaultView ?? window;
|
|
2088
2146
|
}
|
|
2089
2147
|
function getScrollPosition(container) {
|
|
2090
|
-
if (container
|
|
2148
|
+
if (isWindow(container)) {
|
|
2091
2149
|
return { left: window.scrollX, top: window.scrollY };
|
|
2092
2150
|
}
|
|
2093
2151
|
return { left: container.scrollLeft, top: container.scrollTop };
|
|
2094
2152
|
}
|
|
2095
2153
|
|
|
2154
|
+
const NGX_DRAG_PREVIEW = new InjectionToken('ngx_drag_preview');
|
|
2155
|
+
/**
|
|
2156
|
+
* Custom preview content, from `*ngxDragPreview` inside the `ngxDraggable`.
|
|
2157
|
+
*
|
|
2158
|
+
* @example
|
|
2159
|
+
* ```html
|
|
2160
|
+
* <div ngxDropList>
|
|
2161
|
+
* <div ngxDraggable>
|
|
2162
|
+
* <span class="my-preview" *ngxDragPreview></span>
|
|
2163
|
+
* ...
|
|
2164
|
+
* </div>
|
|
2165
|
+
* </div>
|
|
2166
|
+
* ```
|
|
2167
|
+
*/
|
|
2168
|
+
class NgxDragPreview {
|
|
2169
|
+
tpl;
|
|
2170
|
+
_ref = new DragPreviewRef();
|
|
2171
|
+
constructor(tpl) {
|
|
2172
|
+
this.tpl = tpl;
|
|
2173
|
+
this._ref.tpl = tpl;
|
|
2174
|
+
this._ref.appRef = inject(ApplicationRef);
|
|
2175
|
+
}
|
|
2176
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: NgxDragPreview, deps: [{ token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive });
|
|
2177
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.4", type: NgxDragPreview, isStandalone: true, selector: "[ngxDragPreview]", providers: [{ provide: NGX_DRAG_PREVIEW, useExisting: NgxDragPreview }], ngImport: i0 });
|
|
2178
|
+
}
|
|
2179
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: NgxDragPreview, decorators: [{
|
|
2180
|
+
type: Directive,
|
|
2181
|
+
args: [{
|
|
2182
|
+
selector: '[ngxDragPreview]',
|
|
2183
|
+
providers: [{ provide: NGX_DRAG_PREVIEW, useExisting: NgxDragPreview }],
|
|
2184
|
+
}]
|
|
2185
|
+
}], ctorParameters: () => [{ type: i0.TemplateRef }] });
|
|
2186
|
+
|
|
2096
2187
|
/** Pointer events already claimed by an (inner) draggable. */
|
|
2097
2188
|
const claimedPointerEvents = new WeakSet();
|
|
2098
2189
|
const NGX_DRAGGABLE = new InjectionToken('ngx-draggable');
|
|
@@ -2124,6 +2215,7 @@ class NgxDraggable {
|
|
|
2124
2215
|
set data(v) {
|
|
2125
2216
|
this._ref.data = v;
|
|
2126
2217
|
}
|
|
2218
|
+
customPreview;
|
|
2127
2219
|
dragStart = output();
|
|
2128
2220
|
dragMove = output();
|
|
2129
2221
|
dragEnd = output();
|
|
@@ -2177,6 +2269,11 @@ class NgxDraggable {
|
|
|
2177
2269
|
this.removeDown = this.renderer.listen(this.host.nativeElement, 'pointerdown', (e) => this.pointerDown(e));
|
|
2178
2270
|
this.removeKeydown = this.renderer.listen(this.host.nativeElement, 'keydown', (e) => this.keyDown(e));
|
|
2179
2271
|
}
|
|
2272
|
+
ngAfterContentInit() {
|
|
2273
|
+
if (this.customPreview) {
|
|
2274
|
+
this._ref.preview = this.customPreview._ref;
|
|
2275
|
+
}
|
|
2276
|
+
}
|
|
2180
2277
|
ngOnDestroy() {
|
|
2181
2278
|
this.removeDown?.();
|
|
2182
2279
|
this.removeMove?.();
|
|
@@ -2206,12 +2303,13 @@ class NgxDraggable {
|
|
|
2206
2303
|
e.preventDefault();
|
|
2207
2304
|
this.down = true;
|
|
2208
2305
|
this.pointerId = e.pointerId;
|
|
2306
|
+
this._ref.el.setPointerCapture(this.pointerId);
|
|
2209
2307
|
this.start = { x: e.clientX, y: e.clientY };
|
|
2210
2308
|
this._ref.boundary = this.boundary();
|
|
2211
2309
|
this._ref.lockAxis = this.lockAxis();
|
|
2212
2310
|
this._ref.pointerDown(this.start);
|
|
2213
|
-
this.removeMove = this.renderer.listen(this.
|
|
2214
|
-
this.removeUp = this.renderer.listen(this.
|
|
2311
|
+
this.removeMove = this.renderer.listen(this._ref.el, 'pointermove', (ev) => this.pointerMove(ev));
|
|
2312
|
+
this.removeUp = this.renderer.listen(this._ref.el, 'pointerup', (ev) => this.pointerUp(ev));
|
|
2215
2313
|
this.removeEscape = this.renderer.listen(this.doc, 'keydown', (ev) => {
|
|
2216
2314
|
if (ev.key === 'Escape' && this.dragging())
|
|
2217
2315
|
this.cancel();
|
|
@@ -2289,6 +2387,9 @@ class NgxDraggable {
|
|
|
2289
2387
|
pointerUp(e) {
|
|
2290
2388
|
if (!this.down || e.pointerId !== this.pointerId)
|
|
2291
2389
|
return;
|
|
2390
|
+
if (this._ref.el.hasPointerCapture(this.pointerId)) {
|
|
2391
|
+
this._ref.el.releasePointerCapture(this.pointerId);
|
|
2392
|
+
}
|
|
2292
2393
|
if (this.dragging()) {
|
|
2293
2394
|
// Also when released OUTSIDE every list: endDrag() rolls the drag back and cleans up.
|
|
2294
2395
|
if (this._ref.isListDrag) {
|
|
@@ -2385,14 +2486,16 @@ class NgxDraggable {
|
|
|
2385
2486
|
isOnHandle(target) {
|
|
2386
2487
|
if (!this.dragHandle())
|
|
2387
2488
|
return true;
|
|
2489
|
+
// TODO notsafe instanseof: node.nodeType === Node.ELEMENT_NODE
|
|
2388
2490
|
return target instanceof HTMLElement && !!target.closest(this.dragHandle());
|
|
2389
2491
|
}
|
|
2390
2492
|
isInteractive(target) {
|
|
2493
|
+
// TODO notsafe instanseof: node.nodeType === Node.ELEMENT_NODE
|
|
2391
2494
|
return (target instanceof HTMLElement &&
|
|
2392
2495
|
!!target.closest('button,a,input,textarea,select,[data-no-drag]'));
|
|
2393
2496
|
}
|
|
2394
2497
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: NgxDraggable, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive });
|
|
2395
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.4", type: NgxDraggable, isStandalone: true, selector: "[NgxDraggable],[ngxDraggable]", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, boundary: { classPropertyName: "boundary", publicName: "boundary", isSignal: true, isRequired: false, transformFunction: null }, dragRootElement: { classPropertyName: "dragRootElement", publicName: "dragRootElement", isSignal: true, isRequired: false, transformFunction: null }, dragHandle: { classPropertyName: "dragHandle", publicName: "dragHandle", isSignal: true, isRequired: false, transformFunction: null }, lockAxis: { classPropertyName: "lockAxis", publicName: "lockAxis", isSignal: true, isRequired: false, transformFunction: null }, dragThreshold: { classPropertyName: "dragThreshold", publicName: "dragThreshold", isSignal: true, isRequired: false, transformFunction: null }, keyboardStep: { classPropertyName: "keyboardStep", publicName: "keyboardStep", isSignal: true, isRequired: false, transformFunction: null }, autoScroll: { classPropertyName: "autoScroll", publicName: "autoScroll", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: false, isRequired: false, transformFunction: null } }, outputs: { disabled: "disabledChange", dragRootElement: "dragRootElementChange", dragHandle: "dragHandleChange", dragStart: "dragStart", dragMove: "dragMove", dragEnd: "dragEnd" }, host: { properties: { "style.touch-action": "\"none\"", "attr.tabindex": "disabled() ? null : 0", "attr.aria-grabbed": "dragging()", "class.disable-drag": "disabled()" }, classAttribute: "ngx-draggable" }, providers: [{ provide: NGX_DRAGGABLE, useExisting: NgxDraggable }], ngImport: i0 });
|
|
2498
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.4", type: NgxDraggable, isStandalone: true, selector: "[NgxDraggable],[ngxDraggable]", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, boundary: { classPropertyName: "boundary", publicName: "boundary", isSignal: true, isRequired: false, transformFunction: null }, dragRootElement: { classPropertyName: "dragRootElement", publicName: "dragRootElement", isSignal: true, isRequired: false, transformFunction: null }, dragHandle: { classPropertyName: "dragHandle", publicName: "dragHandle", isSignal: true, isRequired: false, transformFunction: null }, lockAxis: { classPropertyName: "lockAxis", publicName: "lockAxis", isSignal: true, isRequired: false, transformFunction: null }, dragThreshold: { classPropertyName: "dragThreshold", publicName: "dragThreshold", isSignal: true, isRequired: false, transformFunction: null }, keyboardStep: { classPropertyName: "keyboardStep", publicName: "keyboardStep", isSignal: true, isRequired: false, transformFunction: null }, autoScroll: { classPropertyName: "autoScroll", publicName: "autoScroll", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: false, isRequired: false, transformFunction: null } }, outputs: { disabled: "disabledChange", dragRootElement: "dragRootElementChange", dragHandle: "dragHandleChange", dragStart: "dragStart", dragMove: "dragMove", dragEnd: "dragEnd" }, host: { properties: { "style.touch-action": "\"none\"", "attr.tabindex": "disabled() ? null : 0", "attr.aria-grabbed": "dragging()", "class.disable-drag": "disabled()" }, classAttribute: "ngx-draggable" }, providers: [{ provide: NGX_DRAGGABLE, useExisting: NgxDraggable }], queries: [{ propertyName: "customPreview", first: true, predicate: NgxDragPreview, descendants: true }], ngImport: i0 });
|
|
2396
2499
|
}
|
|
2397
2500
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: NgxDraggable, decorators: [{
|
|
2398
2501
|
type: Directive,
|
|
@@ -2410,6 +2513,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImpor
|
|
|
2410
2513
|
}], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }, { type: i0.Output, args: ["disabledChange"] }], boundary: [{ type: i0.Input, args: [{ isSignal: true, alias: "boundary", required: false }] }], dragRootElement: [{ type: i0.Input, args: [{ isSignal: true, alias: "dragRootElement", required: false }] }, { type: i0.Output, args: ["dragRootElementChange"] }], dragHandle: [{ type: i0.Input, args: [{ isSignal: true, alias: "dragHandle", required: false }] }, { type: i0.Output, args: ["dragHandleChange"] }], lockAxis: [{ type: i0.Input, args: [{ isSignal: true, alias: "lockAxis", required: false }] }], dragThreshold: [{ type: i0.Input, args: [{ isSignal: true, alias: "dragThreshold", required: false }] }], keyboardStep: [{ type: i0.Input, args: [{ isSignal: true, alias: "keyboardStep", required: false }] }], autoScroll: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoScroll", required: false }] }], data: [{
|
|
2411
2514
|
type: Input,
|
|
2412
2515
|
args: ['data']
|
|
2516
|
+
}], customPreview: [{
|
|
2517
|
+
type: ContentChild,
|
|
2518
|
+
args: [NgxDragPreview]
|
|
2413
2519
|
}], dragStart: [{ type: i0.Output, args: ["dragStart"] }], dragMove: [{ type: i0.Output, args: ["dragMove"] }], dragEnd: [{ type: i0.Output, args: ["dragEnd"] }] } });
|
|
2414
2520
|
|
|
2415
2521
|
const ALL_DIRECTIONS = ['n', 'ne', 'e', 'se', 's', 'sw', 'w', 'nw'];
|
|
@@ -2716,6 +2822,7 @@ class NgxResizable {
|
|
|
2716
2822
|
/**
|
|
2717
2823
|
* Explicit resize handle has priority.
|
|
2718
2824
|
*/
|
|
2825
|
+
// TODO notsafe instanceof:node.nodeType === Node.ELEMENT_NODE
|
|
2719
2826
|
const handle = e.target instanceof HTMLElement
|
|
2720
2827
|
? e.target.closest('[data-ngx-resize-handle]')
|
|
2721
2828
|
: null;
|
|
@@ -2788,6 +2895,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImpor
|
|
|
2788
2895
|
}] } });
|
|
2789
2896
|
|
|
2790
2897
|
const NGX_PLACEHOLDER = new InjectionToken('ngx-place-holder');
|
|
2898
|
+
/**
|
|
2899
|
+
* Custom placeholder content, from `*ngxPlaceholder` inside the `ngxDropList`.
|
|
2900
|
+
*
|
|
2901
|
+
* @example
|
|
2902
|
+
* ```html
|
|
2903
|
+
* <div ngxDropList>
|
|
2904
|
+
* <span class="my-placeholder" *ngxPlaceholder></span>
|
|
2905
|
+
* ...
|
|
2906
|
+
* </div>
|
|
2907
|
+
* ```
|
|
2908
|
+
*/
|
|
2791
2909
|
class NgxPlaceholder {
|
|
2792
2910
|
tpl;
|
|
2793
2911
|
_ref = new PlaceHolderRef();
|
|
@@ -2833,11 +2951,6 @@ class NgxDropList {
|
|
|
2833
2951
|
}
|
|
2834
2952
|
ngOnInit() {
|
|
2835
2953
|
this._ref.el = this.el.nativeElement;
|
|
2836
|
-
// Found by walking the real DOM (not Angular's element-injector tree): a list rendered by a
|
|
2837
|
-
// recursively-invoked `ngTemplateOutlet` (a tree/outliner UI, where every level re-uses the
|
|
2838
|
-
// SAME `<ng-template>`) gets a fresh injector context per invocation, so `inject(TOKEN,
|
|
2839
|
-
// {skipSelf})` can never see a provider from another recursion level — the DOM position is
|
|
2840
|
-
// what actually determines nesting/grouping for this library's purposes anyway.
|
|
2841
2954
|
const parentEl = this.el.nativeElement.parentElement;
|
|
2842
2955
|
const group = this.service.findAncestorGroup(parentEl);
|
|
2843
2956
|
const parent = this.service.findAncestorDropList(parentEl);
|
|
@@ -2952,5 +3065,5 @@ function clamp(v, max) {
|
|
|
2952
3065
|
* Generated bundle index. Do not edit.
|
|
2953
3066
|
*/
|
|
2954
3067
|
|
|
2955
|
-
export { AutoScroller, DragDropService, DragRef, DropListGroupRef, DropListRef, NGX_DRAGGABLE, NGX_DROPLIST, NGX_DROPLIST_GROUP, NGX_PLACEHOLDER, NgxDraggable, NgxDropList, NgxDropListGroup, NgxPlaceholder, NgxResizable, PlaceHolderRef, adjustForZoom, checkBoundX, checkBoundY, clampResizeWithinBoundary, copyArrayItem, findScrollableAncestor, getPageZoom, getScrollPosition, isRtl, moveItemInArray, resolveLogicalDirection, transferArrayItem };
|
|
3068
|
+
export { AutoScroller, DragDropService, DragRef, DropListGroupRef, DropListRef, NGX_DRAGGABLE, NGX_DRAG_PREVIEW, NGX_DROPLIST, NGX_DROPLIST_GROUP, NGX_PLACEHOLDER, NgxDragPreview, NgxDraggable, NgxDropList, NgxDropListGroup, NgxPlaceholder, NgxResizable, PlaceHolderRef, adjustForZoom, checkBoundX, checkBoundY, clampResizeWithinBoundary, copyArrayItem, findScrollableAncestor, getPageZoom, getScrollPosition, isRtl, moveItemInArray, resolveLogicalDirection, transferArrayItem };
|
|
2956
3069
|
//# sourceMappingURL=ngx-kit-drag-resize.mjs.map
|