ngx-kit 8.0.2 → 8.2.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-dialog.mjs +2 -2
- package/fesm2022/ngx-kit-dialog.mjs.map +1 -1
- package/fesm2022/ngx-kit-drag-resize.mjs +277 -174
- 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/fesm2022/ngx-kit-tooltip.mjs +432 -0
- package/fesm2022/ngx-kit-tooltip.mjs.map +1 -0
- package/package.json +5 -1
- package/styles/all.css +125 -35
- package/styles/tootip.css +120 -0
- package/tooltip/README.md +1 -0
- package/types/ngx-kit-drag-resize.d.ts +52 -32
- package/types/ngx-kit-message.d.ts +9 -25
- package/types/ngx-kit-tooltip.d.ts +88 -0
|
@@ -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
|
+
});
|
|
103
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
|
+
});
|
|
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))
|
|
1756
1781
|
continue;
|
|
1757
|
-
const
|
|
1782
|
+
const el = node;
|
|
1783
|
+
if (!others.has(el))
|
|
1784
|
+
continue;
|
|
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) {
|
|
@@ -1930,13 +1946,25 @@ class DragDropService {
|
|
|
1930
1946
|
findAncestorDropList(start) {
|
|
1931
1947
|
let node = start;
|
|
1932
1948
|
while (node) {
|
|
1933
|
-
if (node
|
|
1949
|
+
if (isElementNode(node)) {
|
|
1934
1950
|
const found = this.listsByEl.get(node);
|
|
1935
1951
|
if (found) {
|
|
1936
1952
|
return found;
|
|
1937
1953
|
}
|
|
1938
1954
|
}
|
|
1939
|
-
|
|
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;
|
|
1940
1968
|
}
|
|
1941
1969
|
return null;
|
|
1942
1970
|
}
|
|
@@ -1944,13 +1972,31 @@ class DragDropService {
|
|
|
1944
1972
|
findAncestorGroup(start) {
|
|
1945
1973
|
let node = start;
|
|
1946
1974
|
while (node) {
|
|
1947
|
-
|
|
1975
|
+
// HTMLElement / SVGElement / ...
|
|
1976
|
+
if (isElementNode(node)) {
|
|
1948
1977
|
const found = this.groupsByEl.get(node);
|
|
1949
1978
|
if (found) {
|
|
1950
1979
|
return found;
|
|
1951
1980
|
}
|
|
1952
1981
|
}
|
|
1953
|
-
|
|
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;
|
|
1954
2000
|
}
|
|
1955
2001
|
return null;
|
|
1956
2002
|
}
|
|
@@ -2059,15 +2105,16 @@ class AutoScroller {
|
|
|
2059
2105
|
this.raf = 0;
|
|
2060
2106
|
return;
|
|
2061
2107
|
}
|
|
2062
|
-
|
|
2063
|
-
|
|
2108
|
+
const container = this.container;
|
|
2109
|
+
if (isWindow(container)) {
|
|
2110
|
+
container.scrollBy(this.speed.x, this.speed.y);
|
|
2064
2111
|
}
|
|
2065
2112
|
else {
|
|
2066
|
-
|
|
2067
|
-
|
|
2113
|
+
container.scrollLeft += this.speed.x;
|
|
2114
|
+
container.scrollTop += this.speed.y;
|
|
2068
2115
|
}
|
|
2069
|
-
//
|
|
2070
|
-
//
|
|
2116
|
+
// Pointer ثابت مانده ولی محتوا اسکرول شده؛
|
|
2117
|
+
// بنابراین موقعیت placeholder/sort را دوباره محاسبه کن.
|
|
2071
2118
|
this.onTick?.();
|
|
2072
2119
|
this.raf = requestAnimationFrame(this.tick);
|
|
2073
2120
|
};
|
|
@@ -2080,7 +2127,7 @@ function edgeSpeed(pos, min, max, edge, maxSpeed) {
|
|
|
2080
2127
|
return 0;
|
|
2081
2128
|
}
|
|
2082
2129
|
function getScrollRect(container) {
|
|
2083
|
-
if (container
|
|
2130
|
+
if (isWindow(container)) {
|
|
2084
2131
|
return { left: 0, top: 0, right: window.innerWidth, bottom: window.innerHeight };
|
|
2085
2132
|
}
|
|
2086
2133
|
return container.getBoundingClientRect();
|
|
@@ -2090,19 +2137,53 @@ function findScrollableAncestor(el) {
|
|
|
2090
2137
|
while (node) {
|
|
2091
2138
|
const style = getComputedStyle(node);
|
|
2092
2139
|
const scrollable = /(auto|scroll|overlay)/.test(style.overflowY + style.overflowX);
|
|
2093
|
-
if (scrollable && node.scrollHeight > node.clientHeight)
|
|
2140
|
+
if (scrollable && node.scrollHeight > node.clientHeight) {
|
|
2094
2141
|
return node;
|
|
2142
|
+
}
|
|
2095
2143
|
node = node.parentElement;
|
|
2096
2144
|
}
|
|
2097
|
-
return window;
|
|
2145
|
+
return el.ownerDocument.defaultView ?? window;
|
|
2098
2146
|
}
|
|
2099
2147
|
function getScrollPosition(container) {
|
|
2100
|
-
if (container
|
|
2148
|
+
if (isWindow(container)) {
|
|
2101
2149
|
return { left: window.scrollX, top: window.scrollY };
|
|
2102
2150
|
}
|
|
2103
2151
|
return { left: container.scrollLeft, top: container.scrollTop };
|
|
2104
2152
|
}
|
|
2105
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
|
+
|
|
2106
2187
|
/** Pointer events already claimed by an (inner) draggable. */
|
|
2107
2188
|
const claimedPointerEvents = new WeakSet();
|
|
2108
2189
|
const NGX_DRAGGABLE = new InjectionToken('ngx-draggable');
|
|
@@ -2134,6 +2215,7 @@ class NgxDraggable {
|
|
|
2134
2215
|
set data(v) {
|
|
2135
2216
|
this._ref.data = v;
|
|
2136
2217
|
}
|
|
2218
|
+
customPreview;
|
|
2137
2219
|
dragStart = output();
|
|
2138
2220
|
dragMove = output();
|
|
2139
2221
|
dragEnd = output();
|
|
@@ -2187,6 +2269,11 @@ class NgxDraggable {
|
|
|
2187
2269
|
this.removeDown = this.renderer.listen(this.host.nativeElement, 'pointerdown', (e) => this.pointerDown(e));
|
|
2188
2270
|
this.removeKeydown = this.renderer.listen(this.host.nativeElement, 'keydown', (e) => this.keyDown(e));
|
|
2189
2271
|
}
|
|
2272
|
+
ngAfterContentInit() {
|
|
2273
|
+
if (this.customPreview) {
|
|
2274
|
+
this._ref.preview = this.customPreview._ref;
|
|
2275
|
+
}
|
|
2276
|
+
}
|
|
2190
2277
|
ngOnDestroy() {
|
|
2191
2278
|
this.removeDown?.();
|
|
2192
2279
|
this.removeMove?.();
|
|
@@ -2216,12 +2303,13 @@ class NgxDraggable {
|
|
|
2216
2303
|
e.preventDefault();
|
|
2217
2304
|
this.down = true;
|
|
2218
2305
|
this.pointerId = e.pointerId;
|
|
2306
|
+
this._ref.el.setPointerCapture(this.pointerId);
|
|
2219
2307
|
this.start = { x: e.clientX, y: e.clientY };
|
|
2220
2308
|
this._ref.boundary = this.boundary();
|
|
2221
2309
|
this._ref.lockAxis = this.lockAxis();
|
|
2222
2310
|
this._ref.pointerDown(this.start);
|
|
2223
|
-
this.removeMove = this.renderer.listen(this.
|
|
2224
|
-
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));
|
|
2225
2313
|
this.removeEscape = this.renderer.listen(this.doc, 'keydown', (ev) => {
|
|
2226
2314
|
if (ev.key === 'Escape' && this.dragging())
|
|
2227
2315
|
this.cancel();
|
|
@@ -2299,6 +2387,9 @@ class NgxDraggable {
|
|
|
2299
2387
|
pointerUp(e) {
|
|
2300
2388
|
if (!this.down || e.pointerId !== this.pointerId)
|
|
2301
2389
|
return;
|
|
2390
|
+
if (this._ref.el.hasPointerCapture(this.pointerId)) {
|
|
2391
|
+
this._ref.el.releasePointerCapture(this.pointerId);
|
|
2392
|
+
}
|
|
2302
2393
|
if (this.dragging()) {
|
|
2303
2394
|
// Also when released OUTSIDE every list: endDrag() rolls the drag back and cleans up.
|
|
2304
2395
|
if (this._ref.isListDrag) {
|
|
@@ -2395,14 +2486,16 @@ class NgxDraggable {
|
|
|
2395
2486
|
isOnHandle(target) {
|
|
2396
2487
|
if (!this.dragHandle())
|
|
2397
2488
|
return true;
|
|
2489
|
+
// TODO notsafe instanseof: node.nodeType === Node.ELEMENT_NODE
|
|
2398
2490
|
return target instanceof HTMLElement && !!target.closest(this.dragHandle());
|
|
2399
2491
|
}
|
|
2400
2492
|
isInteractive(target) {
|
|
2493
|
+
// TODO notsafe instanseof: node.nodeType === Node.ELEMENT_NODE
|
|
2401
2494
|
return (target instanceof HTMLElement &&
|
|
2402
2495
|
!!target.closest('button,a,input,textarea,select,[data-no-drag]'));
|
|
2403
2496
|
}
|
|
2404
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 });
|
|
2405
|
-
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 });
|
|
2406
2499
|
}
|
|
2407
2500
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: NgxDraggable, decorators: [{
|
|
2408
2501
|
type: Directive,
|
|
@@ -2420,6 +2513,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImpor
|
|
|
2420
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: [{
|
|
2421
2514
|
type: Input,
|
|
2422
2515
|
args: ['data']
|
|
2516
|
+
}], customPreview: [{
|
|
2517
|
+
type: ContentChild,
|
|
2518
|
+
args: [NgxDragPreview]
|
|
2423
2519
|
}], dragStart: [{ type: i0.Output, args: ["dragStart"] }], dragMove: [{ type: i0.Output, args: ["dragMove"] }], dragEnd: [{ type: i0.Output, args: ["dragEnd"] }] } });
|
|
2424
2520
|
|
|
2425
2521
|
const ALL_DIRECTIONS = ['n', 'ne', 'e', 'se', 's', 'sw', 'w', 'nw'];
|
|
@@ -2726,6 +2822,7 @@ class NgxResizable {
|
|
|
2726
2822
|
/**
|
|
2727
2823
|
* Explicit resize handle has priority.
|
|
2728
2824
|
*/
|
|
2825
|
+
// TODO notsafe instanceof:node.nodeType === Node.ELEMENT_NODE
|
|
2729
2826
|
const handle = e.target instanceof HTMLElement
|
|
2730
2827
|
? e.target.closest('[data-ngx-resize-handle]')
|
|
2731
2828
|
: null;
|
|
@@ -2798,6 +2895,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImpor
|
|
|
2798
2895
|
}] } });
|
|
2799
2896
|
|
|
2800
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
|
+
*/
|
|
2801
2909
|
class NgxPlaceholder {
|
|
2802
2910
|
tpl;
|
|
2803
2911
|
_ref = new PlaceHolderRef();
|
|
@@ -2843,11 +2951,6 @@ class NgxDropList {
|
|
|
2843
2951
|
}
|
|
2844
2952
|
ngOnInit() {
|
|
2845
2953
|
this._ref.el = this.el.nativeElement;
|
|
2846
|
-
// Found by walking the real DOM (not Angular's element-injector tree): a list rendered by a
|
|
2847
|
-
// recursively-invoked `ngTemplateOutlet` (a tree/outliner UI, where every level re-uses the
|
|
2848
|
-
// SAME `<ng-template>`) gets a fresh injector context per invocation, so `inject(TOKEN,
|
|
2849
|
-
// {skipSelf})` can never see a provider from another recursion level — the DOM position is
|
|
2850
|
-
// what actually determines nesting/grouping for this library's purposes anyway.
|
|
2851
2954
|
const parentEl = this.el.nativeElement.parentElement;
|
|
2852
2955
|
const group = this.service.findAncestorGroup(parentEl);
|
|
2853
2956
|
const parent = this.service.findAncestorDropList(parentEl);
|
|
@@ -2962,5 +3065,5 @@ function clamp(v, max) {
|
|
|
2962
3065
|
* Generated bundle index. Do not edit.
|
|
2963
3066
|
*/
|
|
2964
3067
|
|
|
2965
|
-
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 };
|
|
2966
3069
|
//# sourceMappingURL=ngx-kit-drag-resize.mjs.map
|