@libs-ui/components-drag-drop 0.2.10-6.2

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.
@@ -0,0 +1,1176 @@
1
+ import * as i0 from '@angular/core';
2
+ import { signal, Injectable, input, inject, ElementRef, Directive, model, output, effect, untracked } from '@angular/core';
3
+ import { get, checkMouseOverInContainer, cloneIBoundingClientRect, uuid, set, cloneDeep, getViewport, checkViewInScreen } from '@libs-ui/utils';
4
+ import { Subject, takeUntil, debounceTime, filter, fromEvent, tap, throttleTime, mergeMap, startWith } from 'rxjs';
5
+
6
+ const styleContainer = (config, viewEncapsulation, groupID) => {
7
+ const defaultConfig = [{
8
+ className: 'libs-ui-drag-drop-container',
9
+ styles: `display:block;`
10
+ },
11
+ {
12
+ className: 'libs-ui-drag-drop-item',
13
+ styles: `
14
+ cursor:move;`
15
+ },
16
+ {
17
+ className: 'libs-ui-drag-drop-item-placeholder',
18
+ styles: `visibility: hidden;`
19
+ },
20
+ {
21
+ className: 'libs-ui-drag-drop-item-origin-placeholder',
22
+ styles: `visibility: hidden;`
23
+ },
24
+ {
25
+ className: 'libs-ui-drag-drop-item-drop-placeholder',
26
+ styles: `visibility: hidden;`
27
+ },
28
+ {
29
+ className: 'libs-ui-drag-drop-item-dragging',
30
+ styles: `cursor:move; user-select: none; `
31
+ },
32
+ {
33
+ className: 'libs-ui-drag-drop-item-disable',
34
+ styles: ` cursor:not-allowed;`
35
+ },
36
+ {
37
+ className: 'libs-ui-drag-drop-item-translate-bottom',
38
+ styles: `position:relative;animation: translateBottom 0.35s 1 ease;`
39
+ },
40
+ {
41
+ className: 'libs-ui-drag-drop-item-translate-top',
42
+ styles: `position:relative;animation: translateTop 0.35s 1 ease;`
43
+ },
44
+ {
45
+ className: 'libs-ui-drag-drop-item-translate-left',
46
+ styles: `position:relative;animation: translateLeft 0.35s 1 ease;`
47
+ },
48
+ {
49
+ className: 'libs-ui-drag-drop-item-translate-right',
50
+ styles: `position:relative;animation: translateRight 0.35s 1 ease;`
51
+ }];
52
+ config.forEach(item => {
53
+ const itemExits = defaultConfig.find(defaultItem => defaultItem.className === item.className);
54
+ if (itemExits) {
55
+ itemExits.styles = item.styles;
56
+ return;
57
+ }
58
+ defaultConfig.push(item);
59
+ });
60
+ const groupAttr = viewEncapsulation ? `[groupID~="${groupID}"]` : '';
61
+ let styles = '';
62
+ defaultConfig.forEach((item) => {
63
+ const style = `${groupAttr}.${item.className}{${item.styles}}`;
64
+ styles = `${styles}${style}\n`;
65
+ });
66
+ styles = ` @keyframes translateTop {
67
+ 0% {
68
+ transform: translateY(30px);
69
+ }
70
+
71
+ 100% {
72
+ transform: translateX(0);
73
+ }
74
+ }
75
+
76
+ @keyframes translateBottom {
77
+ 0% {
78
+ transform: translateY(-30px);
79
+ }
80
+
81
+ 100% {
82
+ transform: translateX(0px);
83
+ }
84
+ }
85
+ @keyframes translateLeft {
86
+ 0% {
87
+ transform: translateX(30px);
88
+ }
89
+
90
+ 100% {
91
+ transform: translateX(0);
92
+ }
93
+ }
94
+
95
+ @keyframes translateRight {
96
+ 0% {
97
+ transform: translateX(-30px);
98
+ }
99
+
100
+ 100% {
101
+ transform: translateX(0px);
102
+ }
103
+ }
104
+ ${styles}`.replace(/\n+/g, '');
105
+ return styles;
106
+ };
107
+
108
+ class MoLibsSharedDragDropService {
109
+ itemsClick = new Array();
110
+ onDragItemInContainerVirtualScroll = new Subject();
111
+ itemDragInfo;
112
+ container = signal(new Map());
113
+ targetItemDragFlag = 'item-drag-target';
114
+ classContainerDefine = 'libs-ui-drag-drop-container';
115
+ classItemDefine = 'libs-ui-drag-drop-item';
116
+ onDragging = new Subject();
117
+ onDragStart = new Subject();
118
+ onDragEnd = new Subject();
119
+ onDragOver = new Subject();
120
+ onDragLeave = new Subject();
121
+ onDrop = new Subject();
122
+ onDropContainer = new Subject();
123
+ onItemInit = new Subject();
124
+ get OnDragItemInContainerVirtualScroll() {
125
+ return this.onDragItemInContainerVirtualScroll;
126
+ }
127
+ set ItemDragInfo(data) {
128
+ this.itemDragInfo = data;
129
+ }
130
+ get ItemDragInfo() {
131
+ return this.itemDragInfo;
132
+ }
133
+ get Container() {
134
+ return this.container;
135
+ }
136
+ get TargetItemDragFlag() {
137
+ return this.targetItemDragFlag;
138
+ }
139
+ get ClassContainerDefine() {
140
+ return this.classContainerDefine;
141
+ }
142
+ get ClassItemDefine() {
143
+ return this.classItemDefine;
144
+ }
145
+ get OnDragging() {
146
+ return this.onDragging;
147
+ }
148
+ get OnDragOver() {
149
+ return this.onDragOver;
150
+ }
151
+ get OnDragLeave() {
152
+ return this.onDragLeave;
153
+ }
154
+ get OnDragStart() {
155
+ return this.onDragStart;
156
+ }
157
+ get OnDragEnd() {
158
+ return this.onDragEnd;
159
+ }
160
+ get OnDropContainer() {
161
+ return this.onDropContainer;
162
+ }
163
+ get OnDrop() {
164
+ return this.onDrop;
165
+ }
166
+ get OnItemInit() {
167
+ return this.onItemInit;
168
+ }
169
+ get ItemClick() {
170
+ return [...this.itemsClick];
171
+ }
172
+ set ItemClick(item) {
173
+ this.itemsClick.push(item);
174
+ }
175
+ resetItemClick() {
176
+ this.itemsClick.length = 0;
177
+ }
178
+ checkElementOverAcceptElementDrag(groupNameOfContainer, groupNameOfElementDrag, groupNameOfDropTo) {
179
+ if (groupNameOfContainer !== groupNameOfElementDrag && !groupNameOfDropTo) {
180
+ return false;
181
+ }
182
+ if (groupNameOfDropTo !== null && !groupNameOfDropTo.toString().split(';').includes(groupNameOfContainer || 'undefinedName')) {
183
+ return false;
184
+ }
185
+ return true;
186
+ }
187
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: MoLibsSharedDragDropService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
188
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: MoLibsSharedDragDropService, providedIn: 'any' });
189
+ }
190
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: MoLibsSharedDragDropService, decorators: [{
191
+ type: Injectable,
192
+ args: [{
193
+ providedIn: 'any'
194
+ }]
195
+ }] });
196
+
197
+ class LibsUiComponentsDragScrollDirective {
198
+ /* PROPERTY */
199
+ stopScroll = signal(false);
200
+ virtualScrollPageInfo = signal(undefined);
201
+ intervalScrollToElement = signal(undefined);
202
+ onDestroy = new Subject();
203
+ /* INPUT */
204
+ ignoreAutoScroll = input();
205
+ widthZoneDetect = input(16, { transform: value => value ?? 16 });
206
+ movementLength = input(6, { transform: value => value ?? 6 });
207
+ rootElementScroll = input();
208
+ virtualScrollerComponent = input();
209
+ /* INJECT */
210
+ elementRef = inject(ElementRef);
211
+ dragDropService = inject(MoLibsSharedDragDropService);
212
+ ngAfterViewInit() {
213
+ this.dragDropService.OnDragging.pipe(takeUntil(this.onDestroy)).subscribe((eventDragging) => this.checkAndScrollElementToPosition(eventDragging, this.ignoreAutoScroll()));
214
+ this.dragDropService.OnDragEnd.pipe(takeUntil(this.onDestroy)).subscribe(() => {
215
+ clearInterval(this.intervalScrollToElement());
216
+ if (this.virtualScrollPageInfo()) {
217
+ const firstElement = get(this.virtualScrollerComponent(), 'element')?.nativeElement.firstElementChild;
218
+ const isHorizontal = get(this.virtualScrollerComponent(), '_horizontal');
219
+ if (isHorizontal) {
220
+ firstElement.style.transform = `scaleX(${this.virtualScrollPageInfo()?.scrollEndPosition})`;
221
+ }
222
+ if (!isHorizontal) {
223
+ firstElement.style.transform = `scaleY(${this.virtualScrollPageInfo()?.scrollEndPosition})`;
224
+ }
225
+ this.virtualScrollPageInfo.set(undefined);
226
+ }
227
+ this.stopScroll.set(false);
228
+ });
229
+ this.dragDropService.OnDragStart.pipe(takeUntil(this.onDestroy)).subscribe(() => {
230
+ if (this.virtualScrollerComponent) {
231
+ this.virtualScrollerComponent()?.scrollToIndex(0);
232
+ }
233
+ });
234
+ if (!this.virtualScrollerComponent) {
235
+ return;
236
+ }
237
+ this.virtualScrollerComponent()?.vsChange.pipe(takeUntil(this.onDestroy)).subscribe(pageInfo => {
238
+ const items = get(this.virtualScrollerComponent, '_items');
239
+ if (items && items.length === pageInfo.endIndex) {
240
+ this.virtualScrollPageInfo.set(pageInfo);
241
+ const elementSetScroll = this.rootElementScroll() || this.elementRef.nativeElement;
242
+ const isHorizontal = get(this.virtualScrollerComponent, '_horizontal');
243
+ if (isHorizontal && pageInfo.scrollEndPosition < elementSetScroll.offsetWidth + elementSetScroll.scrollLeft + 3) {
244
+ this.stopScroll.set(true);
245
+ clearInterval(this.intervalScrollToElement());
246
+ return;
247
+ }
248
+ if (!isHorizontal && pageInfo.scrollEndPosition < elementSetScroll.offsetHeight + elementSetScroll.scrollTop + 3) {
249
+ this.stopScroll.set(true);
250
+ clearInterval(this.intervalScrollToElement());
251
+ return;
252
+ }
253
+ }
254
+ this.stopScroll.set(false);
255
+ });
256
+ }
257
+ /* FUNCTIONS */
258
+ checkAndScrollElementToPosition(eventDragging, ignoreAutoScroll) {
259
+ let elementSetScroll = this.rootElementScroll() || this.elementRef.nativeElement;
260
+ if (ignoreAutoScroll || !checkMouseOverInContainer(eventDragging.mousePosition, elementSetScroll)) {
261
+ return;
262
+ }
263
+ const rectElement = cloneIBoundingClientRect(this.elementRef.nativeElement.getBoundingClientRect());
264
+ if (this.rootElementScroll()) {
265
+ const rectElementScroll = this.rootElementScroll()?.getBoundingClientRect();
266
+ rectElement.left = rectElementScroll.left;
267
+ rectElement.top = rectElementScroll.top;
268
+ }
269
+ const { width, height, top, left } = rectElement;
270
+ const { clientX, clientY } = eventDragging.mousePosition;
271
+ const limitLeft = left + elementSetScroll.offsetWidth;
272
+ const limitTop = top + elementSetScroll.offsetHeight;
273
+ clearInterval(this.intervalScrollToElement());
274
+ if ((clientX < left || clientX > left + width) && (clientY < top || clientY > top + height)) {
275
+ return;
276
+ }
277
+ this.intervalScrollToElement.set(setInterval(() => {
278
+ elementSetScroll = (this.rootElementScroll() || this.elementRef.nativeElement);
279
+ let directionTop = 0;
280
+ let directionLeft = 0;
281
+ if (top <= clientY && clientY <= top + this.widthZoneDetect()) {
282
+ elementSetScroll.scrollTop -= this.movementLength();
283
+ directionTop = -1;
284
+ }
285
+ if (limitTop - this.widthZoneDetect() <= clientY && clientY <= limitTop) {
286
+ if (this.stopScroll()) {
287
+ return;
288
+ }
289
+ elementSetScroll.scrollTop += this.movementLength();
290
+ directionTop = 1;
291
+ }
292
+ if ((limitLeft - this.widthZoneDetect() <= clientX) && (clientX <= limitLeft)) {
293
+ if (this.stopScroll()) {
294
+ return;
295
+ }
296
+ elementSetScroll.scrollLeft += this.movementLength();
297
+ directionLeft = +1;
298
+ }
299
+ if (left <= clientX && clientX <= left + this.widthZoneDetect()) {
300
+ elementSetScroll.scrollLeft -= this.movementLength();
301
+ directionLeft = -1;
302
+ }
303
+ if (elementSetScroll.scrollLeft && (elementSetScroll.scrollLeft + elementSetScroll.offsetWidth >= elementSetScroll.scrollWidth)) {
304
+ elementSetScroll.scrollLeft -= elementSetScroll.scrollLeft + elementSetScroll.offsetWidth - elementSetScroll.scrollWidth;
305
+ }
306
+ if (elementSetScroll.scrollTop && (elementSetScroll.scrollTop + elementSetScroll.offsetHeight >= elementSetScroll.scrollHeight)) {
307
+ elementSetScroll.scrollTop -= elementSetScroll.scrollTop + elementSetScroll.offsetHeight - elementSetScroll.scrollHeight;
308
+ }
309
+ if ((directionTop < 0 && !elementSetScroll.scrollTop) || (!elementSetScroll.scrollLeft && directionLeft < 0) || (directionTop && elementSetScroll.scrollHeight <= elementSetScroll.scrollTop + elementSetScroll.offsetHeight + 3) || (directionLeft && elementSetScroll.scrollWidth <= elementSetScroll.scrollLeft + elementSetScroll.offsetWidth + 3)) {
310
+ return clearInterval(this.intervalScrollToElement());
311
+ }
312
+ }, 10));
313
+ }
314
+ ngOnDestroy() {
315
+ this.onDestroy.next();
316
+ this.onDestroy.complete();
317
+ }
318
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LibsUiComponentsDragScrollDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
319
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "18.2.13", type: LibsUiComponentsDragScrollDirective, isStandalone: true, selector: "[LibsUiComponentsDragScrollDirective]", inputs: { ignoreAutoScroll: { classPropertyName: "ignoreAutoScroll", publicName: "ignoreAutoScroll", isSignal: true, isRequired: false, transformFunction: null }, widthZoneDetect: { classPropertyName: "widthZoneDetect", publicName: "widthZoneDetect", isSignal: true, isRequired: false, transformFunction: null }, movementLength: { classPropertyName: "movementLength", publicName: "movementLength", isSignal: true, isRequired: false, transformFunction: null }, rootElementScroll: { classPropertyName: "rootElementScroll", publicName: "rootElementScroll", isSignal: true, isRequired: false, transformFunction: null }, virtualScrollerComponent: { classPropertyName: "virtualScrollerComponent", publicName: "virtualScrollerComponent", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 });
320
+ }
321
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LibsUiComponentsDragScrollDirective, decorators: [{
322
+ type: Directive,
323
+ args: [{
324
+ // eslint-disable-next-line @angular-eslint/directive-selector
325
+ selector: "[LibsUiComponentsDragScrollDirective]",
326
+ standalone: true
327
+ }]
328
+ }] });
329
+
330
+ class LibsUiComponentsDragContainerDirective extends LibsUiComponentsDragScrollDirective {
331
+ /* PROPERTY */
332
+ groupID = signal(uuid());
333
+ isDragOver = signal(false);
334
+ /* INPUT */
335
+ disableDragContainer = input();
336
+ mode = input('move', { transform: value => value ?? 'move' });
337
+ directionDrag = input();
338
+ viewEncapsulation = input('emulated', { transform: value => value ?? 'emulated' });
339
+ acceptDragSameGroup = input(false, { transform: value => value ?? false });
340
+ placeholder = input(true, { transform: value => value ?? true });
341
+ groupName = input('groupDragAndDropDefault', { transform: value => value ?? 'groupDragAndDropDefault' }); // nếu các group có tên trùng nhau sẽ được drop
342
+ dropToGroupName = input(null); // nếu item trong các group A được drop vào group B nhưng group B không được drop vào group A
343
+ items = model.required();
344
+ stylesOverride = input();
345
+ /* OUTPUT */
346
+ outDragStartContainer = output();
347
+ outDragOverContainer = output();
348
+ outDragLeaveContainer = output();
349
+ outDragEndContainer = output();
350
+ outDroppedContainer = output();
351
+ outDroppedContainerEmpty = output();
352
+ outFunctionControl = output();
353
+ constructor() {
354
+ super();
355
+ const element = this.elementRef.nativeElement;
356
+ const container = { element };
357
+ this.dragDropService.Container.update(data => {
358
+ data.set(this.groupID(), container);
359
+ return data;
360
+ });
361
+ effect(() => {
362
+ if (!this.rootElementScroll()) {
363
+ return;
364
+ }
365
+ untracked(() => {
366
+ set(container, 'elementScroll', this.rootElementScroll());
367
+ this.dragDropService.Container.update(containerMap => new Map(containerMap));
368
+ });
369
+ });
370
+ effect(() => {
371
+ if (this.directionDrag() && this.elementRef.nativeElement) {
372
+ this.setAttributeElementAndItemDrag(this.elementRef.nativeElement);
373
+ }
374
+ });
375
+ effect(() => {
376
+ if (this.disableDragContainer() && this.elementRef.nativeElement) {
377
+ this.setAttributeElementAndItemDrag(this.elementRef.nativeElement);
378
+ }
379
+ });
380
+ }
381
+ ngAfterViewInit() {
382
+ this.outFunctionControl.emit({ setAttributeElementAndItemDrag: () => this.setAttributeElementAndItemDrag(this.elementRef.nativeElement) });
383
+ this.outDroppedContainer.subscribe(eventDropped => {
384
+ this.dragDropService.OnDropContainer.next(eventDropped);
385
+ });
386
+ this.onDestroy.subscribe(() => {
387
+ if (indexSpliceListTo > -1) {
388
+ this.items.update(items => {
389
+ items.splice(indexSpliceListTo, 1);
390
+ return [...items];
391
+ });
392
+ }
393
+ this.dragDropService.Container().delete(this.groupID());
394
+ });
395
+ const elementContainer = this.elementRef.nativeElement;
396
+ this.initStyleAndAttribute(elementContainer, true);
397
+ this.dragDropService.OnItemInit.pipe(debounceTime(250), filter(groupName => groupName === this.groupName()), takeUntil(this.onDestroy)).subscribe(() => this.initStyleAndAttribute(elementContainer));
398
+ const styleTag = document.createElement("style");
399
+ styleTag.textContent = styleContainer((this.stylesOverride() || []), this.viewEncapsulation(), this.groupID());
400
+ elementContainer.appendChild(styleTag);
401
+ elementContainer.classList.add(this.dragDropService.ClassContainerDefine);
402
+ const handlerDragStart = (eventDragStart) => {
403
+ this.setAttributeElementAndItemDrag(elementContainer, true);
404
+ if (this.groupID() === eventDragStart.elementDrag.getAttribute('groupID')) {
405
+ this.outDragStartContainer.emit({ ...eventDragStart, itemDragInfo: this.dragDropService.ItemDragInfo });
406
+ }
407
+ };
408
+ const storeIndex = { indexDrag: -1, indexDragOver: -1 };
409
+ let indexSpliceListTo = -1;
410
+ const handlerDragOver = (eventDragOver) => {
411
+ const { elementDrag, elementDragOver } = eventDragOver;
412
+ if (this.disableDragContainer() || !this.dragDropService.checkElementOverAcceptElementDrag(this.groupName(), elementDrag.getAttribute('groupName'), elementDrag.getAttribute('dropToGroupName'))) {
413
+ return;
414
+ }
415
+ const indexDrag = Number(elementDrag.getAttribute('index')).valueOf();
416
+ const indexDragOver = Number(elementDragOver.getAttribute('index')).valueOf();
417
+ const idGroupElementDrag = elementDrag.getAttribute('groupID');
418
+ const idGroupElementDragOver = elementDragOver.getAttribute('groupID');
419
+ if ((this.groupID() !== idGroupElementDrag) || (idGroupElementDrag !== idGroupElementDragOver)) { // xử lý cho item drag over qua 1 item khác container
420
+ if (idGroupElementDragOver === this.groupID() && this.placeholder()) {
421
+ const item = this.mode() === 'deepCopy' ? cloneDeep(this.dragDropService.ItemDragInfo?.item) : this.dragDropService.ItemDragInfo?.item;
422
+ if (indexSpliceListTo >= 0) {
423
+ this.items.update(items => {
424
+ items.splice(indexSpliceListTo, 1);
425
+ return [...items];
426
+ });
427
+ }
428
+ this.items.update(items => {
429
+ items.splice(indexDragOver, 0, item);
430
+ return [...items];
431
+ });
432
+ indexSpliceListTo = indexDragOver;
433
+ this.setAttributeElementAndItemDrag(elementContainer, false, indexSpliceListTo);
434
+ }
435
+ return;
436
+ }
437
+ if (!this.acceptDragSameGroup() || indexDrag < 0 || indexDragOver < 0 || !this.items().length || indexDrag > this.items().length || indexDragOver > this.items().length || (storeIndex.indexDrag === indexDrag && storeIndex.indexDragOver === indexDragOver)) {
438
+ return;
439
+ }
440
+ // xử lý cho item drag over qua 1 item cùng container
441
+ const itemDrag = this.items()[indexDrag];
442
+ this.setAnimationElementDragOver(indexDrag, indexDragOver, elementDragOver);
443
+ storeIndex.indexDrag = indexDrag;
444
+ storeIndex.indexDragOver = indexDragOver;
445
+ this.items.update(items => {
446
+ items.splice(indexDrag, 1);
447
+ return [...items];
448
+ });
449
+ this.items.update(items => {
450
+ items.splice(indexDragOver, 0, itemDrag);
451
+ return [...items];
452
+ });
453
+ elementDrag.setAttribute('index', indexDragOver.toString());
454
+ this.setAttributeElementAndItemDrag(elementContainer);
455
+ };
456
+ const removePlaceholderDrag = (eventDrag, isDragging) => {
457
+ clearInterval(this.intervalScrollToElement());
458
+ storeIndex.indexDrag = -1;
459
+ storeIndex.indexDragOver = -1;
460
+ const childrenElement = elementContainer.getElementsByClassName(this.dragDropService.ClassItemDefine);
461
+ if (!checkMouseOverInContainer(eventDrag.mousePosition, (this.rootElementScroll() || elementContainer))) {
462
+ const childElementIndex = Array.from(childrenElement).findIndex((child) => child.classList.contains('libs-ui-drag-drop-item-drop-placeholder'));
463
+ if (childElementIndex >= 0 && this.groupID() !== eventDrag.elementDrag.getAttribute('groupID')) {
464
+ this.items.update(items => {
465
+ items.splice(childElementIndex, 1);
466
+ return [...items];
467
+ });
468
+ }
469
+ indexSpliceListTo = -1;
470
+ this.removeAttributes(elementContainer, isDragging);
471
+ this.setIndexElement(elementContainer);
472
+ return;
473
+ }
474
+ if (indexSpliceListTo >= 0) {
475
+ this.items.update(items => {
476
+ items.splice(indexSpliceListTo, 1);
477
+ return [...items];
478
+ });
479
+ }
480
+ indexSpliceListTo = -1;
481
+ };
482
+ const handlerDragging = (eventDragging) => {
483
+ this.setAttributeElementAndItemDrag(elementContainer);
484
+ const { elementDrag } = eventDragging;
485
+ const fieldIdItem = elementDrag.getAttribute('field_id');
486
+ const idItemDrag = elementDrag.getAttribute('item_id');
487
+ if (fieldIdItem && idItemDrag && this.items().find(item => get(item, fieldIdItem) === idItemDrag)) {
488
+ const childrenElement = elementContainer.getElementsByClassName(this.dragDropService.ClassItemDefine);
489
+ const childElement = Array.from(childrenElement).find((child) => child.getAttribute('item_id') === idItemDrag);
490
+ if (this.items() === eventDragging.itemDragInfo?.itemsDrag() && childElement && !childElement.classList.contains('libs-ui-drag-drop-item-drop-placeholder') && !childElement.getAttribute(this.dragDropService.TargetItemDragFlag)) {
491
+ childElement.setAttribute(this.dragDropService.TargetItemDragFlag, 'true');
492
+ this.groupID.set(elementDrag.getAttribute('groupID') || '');
493
+ styleTag.remove();
494
+ styleTag.textContent = styleContainer((this.stylesOverride() || []), this.viewEncapsulation(), this.groupID());
495
+ elementContainer.appendChild(styleTag);
496
+ this.setAttributeElementAndItemDrag(elementContainer, true);
497
+ }
498
+ }
499
+ if (this.disableDragContainer()) {
500
+ return;
501
+ }
502
+ if (this.groupID() === elementDrag.getAttribute('groupID') && !this.acceptDragSameGroup()) {
503
+ this.checkAndScrollElementToPosition(eventDragging, this.ignoreAutoScroll() || !this.acceptDragSameGroup());
504
+ return;
505
+ }
506
+ if (!checkMouseOverInContainer(eventDragging.mousePosition, (this.rootElementScroll() || elementContainer))) {
507
+ if (this.isDragOver()) {
508
+ this.isDragOver.set(false);
509
+ this.outDragLeaveContainer.emit({ ...eventDragging, elementDragLeave: elementContainer });
510
+ }
511
+ return removePlaceholderDrag(eventDragging, true);
512
+ }
513
+ this.checkAndScrollElementToPosition(eventDragging, this.ignoreAutoScroll());
514
+ // Đoạn code xử lý cho việc kéo một element vào 1 container nhưng container không có item hoặc item drag không over qua item trong container
515
+ if (!this.isDragOver()) {
516
+ elementContainer.classList.add('libs-ui-drag-drop-container-dragover');
517
+ this.isDragOver.set(true);
518
+ this.outDragOverContainer.emit({ ...eventDragging, elementDragOver: elementContainer });
519
+ }
520
+ const eventDragOver = { ...eventDragging, elementDragOver: elementContainer };
521
+ if (!this.items().length) {
522
+ eventDragOver.elementDragOver = {
523
+ getAttribute: (name) => {
524
+ if (name === 'groupID') {
525
+ return this.groupID();
526
+ }
527
+ if (name !== 'index') {
528
+ return null;
529
+ }
530
+ return 0;
531
+ }
532
+ };
533
+ this.dragDropService.OnDragOver.next(eventDragOver);
534
+ return;
535
+ }
536
+ const childrenElement = elementContainer.getElementsByClassName(this.dragDropService.ClassItemDefine);
537
+ let childElement = Array.from(childrenElement).find((child) => checkMouseOverInContainer(eventDragging.mousePosition, child));
538
+ if (childElement) { // nếu tìm thấy thì sẽ nhận qua sự kiện của drag-item.directive emit
539
+ return;
540
+ }
541
+ childElement = Array.from(childrenElement).pop();
542
+ if (childElement) {
543
+ eventDragOver.elementDragOver = childElement;
544
+ this.dragDropService.OnDragOver.next(eventDragOver);
545
+ }
546
+ };
547
+ const handlerDragEnd = (eventDragEnd) => {
548
+ if (this.disableDragContainer()) {
549
+ return;
550
+ }
551
+ let rect = undefined;
552
+ if (this.rootElementScroll() || elementContainer) {
553
+ rect = (this.rootElementScroll() || elementContainer)?.getBoundingClientRect();
554
+ }
555
+ removePlaceholderDrag(eventDragEnd);
556
+ const { elementDrag, mousePosition, itemDragInfo } = eventDragEnd;
557
+ if (this.groupID() === elementDrag.getAttribute('groupID')) {
558
+ this.outDragEndContainer.emit({ ...eventDragEnd });
559
+ }
560
+ if (!checkMouseOverInContainer(mousePosition, this.rootElementScroll() || elementContainer, rect)) {
561
+ return;
562
+ }
563
+ const eventDrop = { elementDrag: elementDrag, elementDrop: elementContainer, itemDragInfo: itemDragInfo };
564
+ if (this.disableDragContainer() || !this.dragDropService.checkElementOverAcceptElementDrag(this.groupName(), elementDrag.getAttribute('groupName'), elementDrag.getAttribute('dropToGroupName'))) {
565
+ return;
566
+ }
567
+ const childrenElement = elementContainer.getElementsByClassName(this.dragDropService.ClassItemDefine);
568
+ const childElement = Array.from(childrenElement).find((child) => checkMouseOverInContainer(mousePosition, child));
569
+ if (childElement) {
570
+ eventDrop.elementDrop = childElement;
571
+ this.dragDropService.OnDrop.next(eventDrop);
572
+ return;
573
+ }
574
+ eventDrop.elementDrop = {
575
+ getAttribute: (name) => {
576
+ if (name === 'dropContainer') {
577
+ return true;
578
+ }
579
+ if (name === 'groupID') {
580
+ return this.groupID();
581
+ }
582
+ if (name !== 'index') {
583
+ return null;
584
+ }
585
+ return childrenElement.length;
586
+ }
587
+ };
588
+ this.dragDropService.OnDrop.next(eventDrop);
589
+ };
590
+ const handlerDrop = (eventDrop) => {
591
+ if (this.disableDragContainer()) {
592
+ return;
593
+ }
594
+ const { elementDrag, elementDrop, itemDragInfo } = eventDrop;
595
+ if (this.groupID() === elementDrag.getAttribute('groupID') && this.groupID() === elementDrop.getAttribute('groupID')) {
596
+ if (itemDragInfo) {
597
+ itemDragInfo.indexDrop = Number(elementDrop.getAttribute('index')).valueOf();
598
+ itemDragInfo.itemsDrop = this.items;
599
+ itemDragInfo.containerDrop = elementContainer;
600
+ }
601
+ if (this.acceptDragSameGroup()) {
602
+ this.outDroppedContainer.emit(eventDrop);
603
+ }
604
+ this.removeAttributes(elementContainer);
605
+ this.setIndexElement(elementContainer);
606
+ return;
607
+ }
608
+ if (this.groupID() !== elementDrop.getAttribute('groupID') || elementDrag.getAttribute('groupID') === elementDrop.getAttribute('groupID')) {
609
+ return;
610
+ }
611
+ const indexDragOver = Number(elementDrop.getAttribute('index')).valueOf() - (elementDrop.getAttribute('dropContainer') ? 0 : 1);
612
+ const item = this.mode() === 'deepCopy' ? cloneDeep(itemDragInfo?.item) : itemDragInfo?.item;
613
+ if (itemDragInfo) {
614
+ itemDragInfo.indexDrop = indexDragOver;
615
+ itemDragInfo.itemsDrop = this.items;
616
+ itemDragInfo.containerDrop = elementContainer;
617
+ }
618
+ if (!this.items().length) {
619
+ this.outDroppedContainerEmpty.emit(eventDrop);
620
+ }
621
+ this.items.update(items => {
622
+ items.splice(indexDragOver, 0, item);
623
+ return [...items];
624
+ });
625
+ if (itemDragInfo && itemDragInfo.itemsMove && itemDragInfo.itemsMove()) {
626
+ itemDragInfo.itemsDrag.set([...itemDragInfo.itemsMove()]);
627
+ this.setAttributeElementAndItemDrag(elementContainer);
628
+ }
629
+ this.outDroppedContainer.emit(eventDrop);
630
+ this.removeAttributes(elementContainer);
631
+ this.setIndexElement(elementContainer);
632
+ };
633
+ [{
634
+ name: 'OnDragStart',
635
+ event: this.dragDropService.OnDragStart,
636
+ functionCall: handlerDragStart
637
+ }, {
638
+ name: 'OnDragOver',
639
+ event: this.dragDropService.OnDragOver,
640
+ functionCall: handlerDragOver
641
+ }, {
642
+ name: 'OnDragging',
643
+ event: this.dragDropService.OnDragging,
644
+ functionCall: handlerDragging
645
+ }, {
646
+ name: 'OnDragEnd',
647
+ event: this.dragDropService.OnDragEnd,
648
+ functionCall: handlerDragEnd
649
+ }, {
650
+ name: 'OnDrop',
651
+ event: this.dragDropService.OnDrop,
652
+ functionCall: handlerDrop
653
+ }].forEach((item) => (item.event.pipe(takeUntil(this.onDestroy)).subscribe(item.functionCall)));
654
+ }
655
+ /* */
656
+ async setAttributeElementAndItemDrag(elementContainer, setItemDrag, indexInsert) {
657
+ const childrenElement = elementContainer.getElementsByClassName(this.dragDropService.ClassItemDefine);
658
+ let index = -1;
659
+ elementContainer.setAttribute('groupID', this.groupID());
660
+ elementContainer.removeAttribute('disableDragContainer');
661
+ if (this.disableDragContainer()) {
662
+ elementContainer.setAttribute('disableDragContainer', `${this.disableDragContainer()}`);
663
+ }
664
+ if (this.groupName()) {
665
+ elementContainer.setAttribute('groupName', this.groupName() || '');
666
+ }
667
+ Array.from(childrenElement).forEach((childElement) => {
668
+ if (!childElement.hasAttribute('groupName') || childElement.getAttribute('groupName') === this.groupName()) {
669
+ childElement.setAttribute('groupID', this.groupID());
670
+ }
671
+ if (childElement.getAttribute('groupID') !== this.groupID()) {
672
+ return;
673
+ }
674
+ index += 1;
675
+ childElement.setAttribute('index', `${index}`);
676
+ childElement.removeAttribute('disableDragContainer');
677
+ if (this.disableDragContainer()) {
678
+ childElement.setAttribute('disableDragContainer', `${this.disableDragContainer()}`);
679
+ }
680
+ if (this.groupName() && !childElement.hasAttribute('groupName')) {
681
+ childElement.setAttribute('groupName', this.groupName() || '');
682
+ }
683
+ if (this.placeholder()) {
684
+ childElement.setAttribute('placeholder', `${this.placeholder()}`);
685
+ }
686
+ if (this.dropToGroupName()) {
687
+ childElement.setAttribute('dropToGroupName', `${this.dropToGroupName()?.join(';')}`);
688
+ }
689
+ if (indexInsert === index && this.placeholder()) {
690
+ if (!childElement.classList.contains('libs-ui-drag-drop-item-placeholder')) {
691
+ childElement.classList.add('libs-ui-drag-drop-item-placeholder');
692
+ }
693
+ if (!childElement.classList.contains('libs-ui-drag-drop-item-drop-placeholder')) {
694
+ childElement.classList.add('libs-ui-drag-drop-item-drop-placeholder');
695
+ }
696
+ }
697
+ if (setItemDrag && childElement.getAttribute(this.dragDropService.TargetItemDragFlag) && this.items().length >= index) {
698
+ if (this.placeholder()) {
699
+ if (!childElement.classList.contains('libs-ui-drag-drop-item-placeholder')) {
700
+ childElement.classList.add('libs-ui-drag-drop-item-placeholder');
701
+ }
702
+ if (!childElement.classList.contains('libs-ui-drag-drop-item-origin-placeholder')) {
703
+ childElement.classList.add('libs-ui-drag-drop-item-origin-placeholder');
704
+ }
705
+ }
706
+ this.dragDropService.ItemDragInfo = { item: this.items()[index], indexDrag: index, itemsDrag: this.items, containerDrag: elementContainer, itemsMove: signal([...this.items()]) };
707
+ if (this.mode() === 'move') {
708
+ this.dragDropService.ItemDragInfo.itemsMove?.update(items => {
709
+ items.splice(index, 1);
710
+ return [...items];
711
+ });
712
+ }
713
+ }
714
+ });
715
+ }
716
+ initStyleAndAttribute(elementContainer, hasRemoveAttribute = false) {
717
+ this.setAttributeElementAndItemDrag(elementContainer);
718
+ if (hasRemoveAttribute) {
719
+ this.removeAttributes(elementContainer);
720
+ }
721
+ this.setIndexElement(elementContainer);
722
+ }
723
+ ;
724
+ setAnimationElementDragOver(indexDrag, indexDragOver, elementDragOver) {
725
+ if (!this.directionDrag() || !elementDragOver) {
726
+ return;
727
+ }
728
+ if (this.directionDrag() === 'vertical') {
729
+ elementDragOver.classList.remove('libs-ui-drag-drop-item-translate-bottom');
730
+ elementDragOver.classList.remove('libs-ui-drag-drop-item-translate-top');
731
+ if (indexDrag > indexDragOver) {
732
+ elementDragOver.classList.add('libs-ui-drag-drop-item-translate-bottom');
733
+ }
734
+ if (indexDrag < indexDragOver) {
735
+ elementDragOver.classList.add('libs-ui-drag-drop-item-translate-top');
736
+ }
737
+ return;
738
+ }
739
+ elementDragOver.classList.remove('libs-ui-drag-drop-item-translate-left');
740
+ elementDragOver.classList.remove('libs-ui-drag-drop-item-translate-right');
741
+ if (indexDrag > indexDragOver) {
742
+ elementDragOver.classList.add('libs-ui-drag-drop-item-translate-right');
743
+ }
744
+ if (indexDrag < indexDragOver) {
745
+ elementDragOver.classList.add('libs-ui-drag-drop-item-translate-left');
746
+ }
747
+ }
748
+ setIndexElement(elementContainer) {
749
+ const childrenElement = elementContainer.getElementsByClassName(this.dragDropService.ClassItemDefine);
750
+ let index = -1;
751
+ Array.from(childrenElement).forEach((childElement) => {
752
+ if (childElement.getAttribute('groupID') !== this.groupID()) {
753
+ return;
754
+ }
755
+ index += 1;
756
+ childElement.setAttribute('index', `${index}`);
757
+ });
758
+ }
759
+ removeAttributes(elementContainer, ignoreRemoveClassItemOriginPlaceholder) {
760
+ const childrenElement = elementContainer.getElementsByClassName(this.dragDropService.ClassItemDefine);
761
+ elementContainer.classList.remove('libs-ui-drag-drop-container-dragover');
762
+ Array.from(childrenElement).forEach((childElement) => {
763
+ if (childElement.getAttribute('groupID') !== this.groupID()) {
764
+ return;
765
+ }
766
+ childElement.removeAttribute('index');
767
+ if (!this.dropToGroupName() || !this.dropToGroupName()?.length) {
768
+ childElement.removeAttribute('dropToGroupName');
769
+ }
770
+ if (!this.placeholder()) {
771
+ childElement.removeAttribute('placeholder');
772
+ }
773
+ if (this.placeholder()) {
774
+ childElement.classList.remove('libs-ui-drag-drop-item-placeholder');
775
+ if (!ignoreRemoveClassItemOriginPlaceholder) {
776
+ childElement.classList.remove('libs-ui-drag-drop-item-origin-placeholder');
777
+ }
778
+ childElement.classList.remove('libs-ui-drag-drop-item-drop-placeholder');
779
+ }
780
+ });
781
+ }
782
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LibsUiComponentsDragContainerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
783
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "18.2.13", type: LibsUiComponentsDragContainerDirective, isStandalone: true, selector: "[LibsUiComponentsDragContainerDirective]", inputs: { disableDragContainer: { classPropertyName: "disableDragContainer", publicName: "disableDragContainer", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, directionDrag: { classPropertyName: "directionDrag", publicName: "directionDrag", isSignal: true, isRequired: false, transformFunction: null }, viewEncapsulation: { classPropertyName: "viewEncapsulation", publicName: "viewEncapsulation", isSignal: true, isRequired: false, transformFunction: null }, acceptDragSameGroup: { classPropertyName: "acceptDragSameGroup", publicName: "acceptDragSameGroup", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, groupName: { classPropertyName: "groupName", publicName: "groupName", isSignal: true, isRequired: false, transformFunction: null }, dropToGroupName: { classPropertyName: "dropToGroupName", publicName: "dropToGroupName", isSignal: true, isRequired: false, transformFunction: null }, items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: true, transformFunction: null }, stylesOverride: { classPropertyName: "stylesOverride", publicName: "stylesOverride", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { items: "itemsChange", outDragStartContainer: "outDragStartContainer", outDragOverContainer: "outDragOverContainer", outDragLeaveContainer: "outDragLeaveContainer", outDragEndContainer: "outDragEndContainer", outDroppedContainer: "outDroppedContainer", outDroppedContainerEmpty: "outDroppedContainerEmpty", outFunctionControl: "outFunctionControl" }, usesInheritance: true, ngImport: i0 });
784
+ }
785
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LibsUiComponentsDragContainerDirective, decorators: [{
786
+ type: Directive,
787
+ args: [{
788
+ // eslint-disable-next-line @angular-eslint/directive-selector
789
+ selector: "[LibsUiComponentsDragContainerDirective]",
790
+ standalone: true,
791
+ }]
792
+ }], ctorParameters: () => [] });
793
+
794
+ class LibsUiDragItemInContainerVirtualScrollDirective {
795
+ /* PROPERTY */
796
+ onDestroy = new Subject();
797
+ /* OUTPUT */
798
+ outDragEndContainer = output();
799
+ /* INJECT */
800
+ dragDropService = inject(MoLibsSharedDragDropService);
801
+ ngAfterViewInit() {
802
+ this.dragDropService.OnDragEnd.pipe(takeUntil(this.onDestroy)).subscribe(e => {
803
+ this.outDragEndContainer.emit(e);
804
+ });
805
+ this.dragDropService.OnDragItemInContainerVirtualScroll.pipe(takeUntil(this.onDestroy)).subscribe(dragItemInContainerVirtualScrollEvent => {
806
+ const stopEventMouse = (mouseEvent) => {
807
+ if (!dragItemInContainerVirtualScrollEvent.ignoreStopEvent) {
808
+ mouseEvent.preventDefault();
809
+ mouseEvent.stopPropagation();
810
+ }
811
+ };
812
+ const documentMouseUp = fromEvent(document, 'mouseup')
813
+ .pipe(tap((eventMouseUp) => {
814
+ this.updateMouseEventsWhenMoveOverIframe('auto');
815
+ stopEventMouse(eventMouseUp);
816
+ const mousePosition = { clientX: eventMouseUp.clientX, clientY: eventMouseUp.clientY };
817
+ if (dragItemInContainerVirtualScrollEvent.dragBoundary && dragItemInContainerVirtualScrollEvent.dragBoundaryAcceptMouseLeaveContainer) {
818
+ const result = this.getClientPosition(dragItemInContainerVirtualScrollEvent.elementDrag, mousePosition, dragItemInContainerVirtualScrollEvent.distanceStartElementAndMouseLeft, dragItemInContainerVirtualScrollEvent.distanceStartElementAndMouseTop, dragItemInContainerVirtualScrollEvent.dragBoundary, dragItemInContainerVirtualScrollEvent.elementContainer);
819
+ mousePosition.clientX = result.clientX;
820
+ mousePosition.clientY = result.clientY;
821
+ }
822
+ const dragEndEvent = { mousePosition, elementDrag: dragItemInContainerVirtualScrollEvent.elementDrag, itemDragInfo: this.dragDropService.ItemDragInfo };
823
+ this.dragDropService.ItemDragInfo = undefined;
824
+ this.dragDropService.OnDragEnd.next(dragEndEvent);
825
+ document.body.classList.remove('select-none');
826
+ dragItemInContainerVirtualScrollEvent.elementDrag.remove();
827
+ }), takeUntil(this.onDestroy));
828
+ fromEvent(document, 'mousemove').pipe(tap((eventMousemove) => {
829
+ stopEventMouse(eventMousemove);
830
+ const { clientX, clientY } = eventMousemove;
831
+ const mousePosition = { clientX, clientY };
832
+ const result = this.getClientPosition(dragItemInContainerVirtualScrollEvent.elementDrag, mousePosition, dragItemInContainerVirtualScrollEvent.distanceStartElementAndMouseLeft, dragItemInContainerVirtualScrollEvent.distanceStartElementAndMouseTop, dragItemInContainerVirtualScrollEvent.dragBoundary, dragItemInContainerVirtualScrollEvent.elementContainer);
833
+ const elementKeepContainer = result.elementKeepContainer;
834
+ const left = result.clientX - dragItemInContainerVirtualScrollEvent.distanceStartElementAndMouseLeft;
835
+ const top = result.clientY - dragItemInContainerVirtualScrollEvent.distanceStartElementAndMouseTop;
836
+ if (dragItemInContainerVirtualScrollEvent.dragBoundary && dragItemInContainerVirtualScrollEvent.dragBoundaryAcceptMouseLeaveContainer) {
837
+ if (clientX < result.viewport.left) {
838
+ mousePosition.clientX = result.viewport.left;
839
+ }
840
+ if (clientX > result.viewport.width) {
841
+ mousePosition.clientX = result.viewport.width;
842
+ }
843
+ if (clientY < result.viewport.top) {
844
+ mousePosition.clientY = result.viewport.top;
845
+ }
846
+ if (clientY > result.viewport.height) {
847
+ mousePosition.clientY = result.viewport.height;
848
+ }
849
+ }
850
+ dragItemInContainerVirtualScrollEvent.elementDrag.style.left = `${left}px`;
851
+ dragItemInContainerVirtualScrollEvent.elementDrag.style.top = `${top}px`;
852
+ this.dragDropService.OnDragging.next({ mousePosition, elementDrag: dragItemInContainerVirtualScrollEvent.elementDrag, elementKeepContainer, itemDragInfo: this.dragDropService.ItemDragInfo });
853
+ }), takeUntil((documentMouseUp)), takeUntil(this.onDestroy)).subscribe();
854
+ });
855
+ }
856
+ /* FUNCTIONS */
857
+ getClientPosition(element, mousePosition, distanceStartElementAndMouseLeft, distanceStartElementAndMouseTop, dragBoundary, elementContainer) {
858
+ let viewport = getViewport();
859
+ const rectElement = element.getBoundingClientRect();
860
+ const containerById = this.dragDropService.Container().get(element.getAttribute('groupID') || '');
861
+ const containerItem = elementContainer || containerById?.elementScroll || containerById?.element || document.body;
862
+ let { clientX, clientY } = mousePosition;
863
+ viewport.left = 0;
864
+ viewport.top = 0;
865
+ if (dragBoundary) {
866
+ viewport = cloneIBoundingClientRect(containerItem.getBoundingClientRect());
867
+ viewport.height = viewport.top + viewport.height;
868
+ viewport.width = viewport.left + viewport.width;
869
+ }
870
+ let elementKeepContainer = false;
871
+ if (clientX > viewport.width && clientY > viewport.height || clientX < viewport.left && clientY < viewport.top) {
872
+ elementKeepContainer = true;
873
+ }
874
+ if ((clientX + (rectElement.width - distanceStartElementAndMouseLeft)) > viewport.width) {
875
+ clientX -= (clientX + (rectElement.width - distanceStartElementAndMouseLeft) - viewport.width);
876
+ }
877
+ if ((clientY + (rectElement.height - distanceStartElementAndMouseTop)) > viewport.height) {
878
+ clientY -= (clientY + (rectElement.height - distanceStartElementAndMouseTop) - viewport.height);
879
+ }
880
+ if ((clientX - distanceStartElementAndMouseLeft) < (dragBoundary && containerItem ? viewport.left : 0)) {
881
+ clientX = (dragBoundary && containerItem ? viewport.left : 0) + distanceStartElementAndMouseLeft;
882
+ }
883
+ if ((clientY - distanceStartElementAndMouseTop) < (dragBoundary && containerItem ? viewport.top : 0)) {
884
+ clientY = (dragBoundary && containerItem ? viewport.top : 0) + distanceStartElementAndMouseTop;
885
+ }
886
+ return { clientX, clientY, elementKeepContainer, viewport };
887
+ }
888
+ updateMouseEventsWhenMoveOverIframe(pointerEvents) {
889
+ const frames = document.getElementsByTagName("iframe");
890
+ if (!frames?.length) {
891
+ return;
892
+ }
893
+ for (let i = 0; i < frames.length; ++i) {
894
+ frames[i].style.pointerEvents = pointerEvents;
895
+ }
896
+ }
897
+ ngOnDestroy() {
898
+ this.onDestroy.next();
899
+ this.onDestroy.complete();
900
+ }
901
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LibsUiDragItemInContainerVirtualScrollDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
902
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.13", type: LibsUiDragItemInContainerVirtualScrollDirective, isStandalone: true, selector: "[LibsUiDragItemInContainerVirtualScrollDirective]", outputs: { outDragEndContainer: "outDragEndContainer" }, ngImport: i0 });
903
+ }
904
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LibsUiDragItemInContainerVirtualScrollDirective, decorators: [{
905
+ type: Directive,
906
+ args: [{
907
+ // eslint-disable-next-line @angular-eslint/directive-selector
908
+ selector: "[LibsUiDragItemInContainerVirtualScrollDirective]",
909
+ standalone: true,
910
+ }]
911
+ }] });
912
+
913
+ /* eslint-disable @typescript-eslint/no-explicit-any */
914
+ class LibsUiDragItemDirective extends LibsUiDragItemInContainerVirtualScrollDirective {
915
+ /* PROPERTY */
916
+ isDragOver = signal(false);
917
+ isDragging = signal(false);
918
+ /* INPUT */
919
+ //setup 3 field phía dưới nếu đang sử dụng item trong virtual-scroll
920
+ fieldId = input('');
921
+ item = input(undefined);
922
+ itemInContainerVirtualScroll = input();
923
+ //----------------------------------
924
+ throttleTimeHandlerDraggingEvent = input(0, { transform: value => value || 0 });
925
+ ignoreStopEvent = input();
926
+ onlyMouseDownStopEvent = input();
927
+ dragRootElement = input();
928
+ groupName = input('groupDragAndDropDefault', { transform: value => value ?? 'groupDragAndDropDefault' });
929
+ dragBoundary = input();
930
+ dragBoundaryAcceptMouseLeaveContainer = input();
931
+ elementContainer = input();
932
+ zIndex = input(1300, { transform: value => value ?? 1300 });
933
+ disable = input();
934
+ /* OUTPUT */
935
+ outDragStart = output();
936
+ outDragOver = output();
937
+ outDragLeave = output();
938
+ outDragEnd = output();
939
+ outDropped = output();
940
+ /* INJECT */
941
+ elementRef = inject(ElementRef);
942
+ constructor() {
943
+ super();
944
+ effect(() => {
945
+ if (!this.elementRef?.nativeElement) {
946
+ return;
947
+ }
948
+ const element = this.elementRef.nativeElement;
949
+ element.classList.remove(`${this.dragDropService.ClassItemDefine}-disable`);
950
+ if (this.disable() && !element.classList.contains(`${this.dragDropService.ClassItemDefine}-disable`)) {
951
+ element.classList.add(`${this.dragDropService.ClassItemDefine}-disable`);
952
+ }
953
+ });
954
+ }
955
+ ngAfterViewInit() {
956
+ const element = this.elementRef.nativeElement;
957
+ if (this.fieldId()) {
958
+ element.setAttribute('field_id', this.fieldId());
959
+ if (this.item()) {
960
+ element.setAttribute('item_id', get(this.item(), this.fieldId()));
961
+ }
962
+ }
963
+ element.setAttribute('groupName', this.groupName());
964
+ element.classList.add(this.dragDropService.ClassItemDefine);
965
+ this.dragDropService.OnDragging.pipe(throttleTime(this.throttleTimeHandlerDraggingEvent()), takeUntil(this.onDestroy)).subscribe((eventDragging) => {
966
+ if (this.disable() || element.getAttribute('disableDragContainer') || (this.fieldId() && this.item() && eventDragging.elementDrag.getAttribute('item_id') === get(this.item(), this.fieldId()))) {
967
+ return;
968
+ }
969
+ const containerById = this.dragDropService.Container().get(element.getAttribute('groupID') || '');
970
+ if (containerById) {
971
+ if (eventDragging.elementKeepContainer || !this.dragDropService.checkElementOverAcceptElementDrag(containerById.element.getAttribute('groupName'), eventDragging.elementDrag.getAttribute('groupName'), eventDragging.elementDrag.getAttribute('dropToGroupName'))) {
972
+ return;
973
+ }
974
+ }
975
+ if (checkMouseOverInContainer(eventDragging.mousePosition, element) && element !== eventDragging.elementDrag && containerById && checkViewInScreen(containerById.element, element, containerById.elementScroll)) {
976
+ if (this.isDragOver()) {
977
+ return;
978
+ }
979
+ const eventDragOver = { ...eventDragging, elementDragOver: element };
980
+ this.dragDropService.OnDragOver.next(eventDragOver);
981
+ this.outDragOver.emit(eventDragOver);
982
+ this.isDragOver.set(true);
983
+ return;
984
+ }
985
+ if (this.isDragOver()) {
986
+ const eventDragLeave = { ...eventDragging, elementDragLeave: element };
987
+ this.isDragOver.set(false);
988
+ this.dragDropService.OnDragLeave.next(eventDragLeave);
989
+ this.outDragLeave.emit(eventDragLeave);
990
+ }
991
+ });
992
+ this.dragDropService.OnDropContainer.pipe(takeUntil(this.onDestroy)).subscribe((eventDrop) => {
993
+ if (eventDrop.elementDrop !== element) {
994
+ return;
995
+ }
996
+ const dropEvent = { elementDrag: eventDrop.elementDrag, elementDrop: element, itemDragInfo: eventDrop.itemDragInfo };
997
+ this.outDropped.emit(dropEvent);
998
+ });
999
+ const styleTag = document.createElement("style");
1000
+ styleTag.textContent = `.libs-ui-drag-drop-item-dragging{cursor:move}`;
1001
+ let nodeClone = element;
1002
+ let distanceStartElementAndMouseLeft = -1;
1003
+ let distanceStartElementAndMouseTop = -1;
1004
+ let contextMenu = false;
1005
+ const stopEventMouse = (mouseEvent) => {
1006
+ if (!this.ignoreStopEvent()) {
1007
+ mouseEvent.preventDefault();
1008
+ mouseEvent.stopPropagation();
1009
+ }
1010
+ };
1011
+ const updatePositionElementRootAndRemoveNodeClone = () => {
1012
+ if (this.dragRootElement()) {
1013
+ const containerById = this.dragDropService.Container().get(element.getAttribute('groupID') || '');
1014
+ const containerItem = this.elementContainer() || containerById?.elementScroll || containerById?.element || document.body;
1015
+ const rectContainer = containerItem.getBoundingClientRect();
1016
+ const rectNodeClone = nodeClone.getBoundingClientRect();
1017
+ const numberSub = Number((getComputedStyle(containerItem).border.match(/\d+px/gi) || ['0'])[0].replace(/\D+/ig, '')).valueOf();
1018
+ element.style.left = (rectNodeClone.left - rectContainer.left - numberSub) + 'px';
1019
+ element.style.top = (rectNodeClone.top - rectContainer.top - numberSub) + 'px';
1020
+ element.classList.remove('opacity-0');
1021
+ }
1022
+ distanceStartElementAndMouseLeft = -1;
1023
+ distanceStartElementAndMouseTop = -1;
1024
+ nodeClone.remove();
1025
+ };
1026
+ fromEvent(document, 'contextmenu').pipe(tap(() => {
1027
+ if (this.isDragging()) {
1028
+ updatePositionElementRootAndRemoveNodeClone();
1029
+ }
1030
+ contextMenu = true;
1031
+ }), takeUntil(this.onDestroy)).subscribe();
1032
+ const documentMouseUp = fromEvent(document, 'mouseup')
1033
+ .pipe(tap((eventMouseup) => {
1034
+ this.updateMouseEventsWhenMoveOverIframe('auto');
1035
+ this.dragDropService.resetItemClick();
1036
+ stopEventMouse(eventMouseup);
1037
+ if (this.disable() || element.getAttribute('disableDragContainer') || contextMenu || !this.isDragging()) {
1038
+ contextMenu = false;
1039
+ return;
1040
+ }
1041
+ contextMenu = false;
1042
+ this.isDragging.set(false);
1043
+ element.removeAttribute(this.dragDropService.TargetItemDragFlag);
1044
+ if (this.itemInContainerVirtualScroll()) {
1045
+ return;
1046
+ }
1047
+ const mousePosition = { clientX: eventMouseup.clientX, clientY: eventMouseup.clientY };
1048
+ if (this.dragBoundary() && this.dragBoundaryAcceptMouseLeaveContainer()) {
1049
+ const result = this.getClientPosition(element, mousePosition, distanceStartElementAndMouseLeft, distanceStartElementAndMouseTop, this.dragBoundary(), this.elementContainer());
1050
+ mousePosition.clientX = result.clientX;
1051
+ mousePosition.clientY = result.clientY;
1052
+ }
1053
+ const dragEndEvent = { mousePosition, elementDrag: element, itemDragInfo: this.dragDropService.ItemDragInfo };
1054
+ this.dragDropService.ItemDragInfo = undefined;
1055
+ this.dragDropService.OnDragEnd.next(dragEndEvent);
1056
+ this.outDragEnd.emit(dragEndEvent);
1057
+ document.body.classList.remove('!select-none');
1058
+ nodeClone.classList.remove('libs-ui-drag-drop-item-dragging');
1059
+ styleTag.remove();
1060
+ updatePositionElementRootAndRemoveNodeClone();
1061
+ }), takeUntil(this.onDestroy));
1062
+ const elementMouseDown = fromEvent(element, 'mousedown').pipe(tap(eventMousedown => {
1063
+ this.dragDropService.ItemClick = element;
1064
+ contextMenu = false;
1065
+ this.updateMouseEventsWhenMoveOverIframe('none');
1066
+ if ((this.disable() || element.getAttribute('disableDragContainer') || !this.isDragging() || this.itemInContainerVirtualScroll()) && !this.onlyMouseDownStopEvent()) {
1067
+ return;
1068
+ }
1069
+ stopEventMouse(eventMousedown);
1070
+ }), takeUntil(this.onDestroy));
1071
+ const documentMouseMove = fromEvent(document, 'mousemove').pipe(tap((eventMousemove) => stopEventMouse(eventMousemove)), takeUntil((documentMouseUp)), takeUntil(this.onDestroy));
1072
+ const drag = elementMouseDown.pipe(mergeMap((mouseEvent) => documentMouseMove.pipe(startWith((mouseEvent)))));
1073
+ let ignoreMousedown = false;
1074
+ drag.pipe(tap((dragMouseEvent) => {
1075
+ const rectElement = element.getBoundingClientRect();
1076
+ const viewport = getViewport();
1077
+ if (this.disable() || element.getAttribute('disableDragContainer') || !dragMouseEvent.clientX || (!ignoreMousedown && dragMouseEvent.type === 'mousedown' && rectElement.height + rectElement.top >= viewport.height)) {
1078
+ return;
1079
+ }
1080
+ const { clientX, clientY } = dragMouseEvent;
1081
+ if (distanceStartElementAndMouseLeft === -1) {
1082
+ distanceStartElementAndMouseLeft = clientX - rectElement.left;
1083
+ }
1084
+ if (distanceStartElementAndMouseTop === -1) {
1085
+ distanceStartElementAndMouseTop = clientY - rectElement.top;
1086
+ }
1087
+ }), takeUntil(this.onDestroy)).subscribe(dragMouseEvent => {
1088
+ if (this.dragDropService.ItemClick.filter(item => item !== element).some(item => element.contains(item))) {
1089
+ return;
1090
+ }
1091
+ if (this.disable() || element.getAttribute('disableDragContainer') || !dragMouseEvent.clientX || dragMouseEvent.type === 'mousedown' || contextMenu || (this.itemInContainerVirtualScroll() && this.isDragging())) {
1092
+ return;
1093
+ }
1094
+ ignoreMousedown = true;
1095
+ const { clientX, clientY } = dragMouseEvent;
1096
+ const mousePosition = { clientX, clientY };
1097
+ const rectElement = element.getBoundingClientRect();
1098
+ if (!this.isDragging()) {
1099
+ this.isDragging.set(true);
1100
+ const eventDragStart = { mousePosition, elementDrag: element, itemDragInfo: this.dragDropService.ItemDragInfo };
1101
+ element.setAttribute(this.dragDropService.TargetItemDragFlag, 'true');
1102
+ this.dragDropService.OnDragStart.next(eventDragStart);
1103
+ eventDragStart.itemDragInfo = this.dragDropService.ItemDragInfo;
1104
+ this.outDragStart.emit(eventDragStart);
1105
+ nodeClone = element.cloneNode(true);
1106
+ nodeClone.style.zIndex = `${this.zIndex()}`;
1107
+ nodeClone.classList.add('!fixed');
1108
+ nodeClone.classList.remove('libs-ui-drag-drop-item-origin-placeholder');
1109
+ nodeClone.classList.remove('libs-ui-drag-drop-item-placeholder');
1110
+ nodeClone.appendChild(styleTag);
1111
+ nodeClone.classList.add('libs-ui-drag-drop-item-dragging');
1112
+ nodeClone.style.width = `${rectElement.width}px`;
1113
+ nodeClone.style.height = `${rectElement.height}px`;
1114
+ nodeClone.style.left = `${-999}px`;
1115
+ nodeClone.style.top = `${-999}px`;
1116
+ document.body.classList.add('!select-none');
1117
+ document.body.append(nodeClone);
1118
+ if (this.dragRootElement()) {
1119
+ element.classList.add('opacity-0');
1120
+ }
1121
+ if (this.itemInContainerVirtualScroll()) {
1122
+ this.dragDropService.OnDragItemInContainerVirtualScroll.next({
1123
+ itemDragInfo: this.dragDropService.ItemDragInfo,
1124
+ elementDrag: nodeClone,
1125
+ distanceStartElementAndMouseTop,
1126
+ distanceStartElementAndMouseLeft,
1127
+ elementContainer: this.elementContainer(),
1128
+ dragBoundary: this.dragBoundary(),
1129
+ dragBoundaryAcceptMouseLeaveContainer: this.dragBoundaryAcceptMouseLeaveContainer(),
1130
+ ignoreStopEvent: this.ignoreStopEvent()
1131
+ });
1132
+ return;
1133
+ }
1134
+ }
1135
+ const result = this.getClientPosition(nodeClone, mousePosition, distanceStartElementAndMouseLeft, distanceStartElementAndMouseTop, this.dragBoundary(), this.elementContainer());
1136
+ const elementKeepContainer = result.elementKeepContainer;
1137
+ const left = result.clientX - distanceStartElementAndMouseLeft;
1138
+ const top = result.clientY - distanceStartElementAndMouseTop;
1139
+ if (this.dragBoundary() && this.dragBoundaryAcceptMouseLeaveContainer()) {
1140
+ if (clientX < result.viewport.left) {
1141
+ mousePosition.clientX = result.viewport.left;
1142
+ }
1143
+ if (clientX > result.viewport.width) {
1144
+ mousePosition.clientX = result.viewport.width;
1145
+ }
1146
+ if (clientY < result.viewport.top) {
1147
+ mousePosition.clientY = result.viewport.top;
1148
+ }
1149
+ if (clientY > result.viewport.height) {
1150
+ mousePosition.clientY = result.viewport.height;
1151
+ }
1152
+ }
1153
+ nodeClone.style.left = `${left}px`;
1154
+ nodeClone.style.top = `${top}px`;
1155
+ const eventDragging = { mousePosition, elementDrag: nodeClone, elementKeepContainer, itemDragInfo: this.dragDropService.ItemDragInfo };
1156
+ this.dragDropService.OnDragging.next(eventDragging);
1157
+ });
1158
+ }
1159
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LibsUiDragItemDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1160
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "18.2.13", type: LibsUiDragItemDirective, isStandalone: true, selector: "[LibsUiDragItemDirective]", inputs: { fieldId: { classPropertyName: "fieldId", publicName: "fieldId", isSignal: true, isRequired: false, transformFunction: null }, item: { classPropertyName: "item", publicName: "item", isSignal: true, isRequired: false, transformFunction: null }, itemInContainerVirtualScroll: { classPropertyName: "itemInContainerVirtualScroll", publicName: "itemInContainerVirtualScroll", isSignal: true, isRequired: false, transformFunction: null }, throttleTimeHandlerDraggingEvent: { classPropertyName: "throttleTimeHandlerDraggingEvent", publicName: "throttleTimeHandlerDraggingEvent", isSignal: true, isRequired: false, transformFunction: null }, ignoreStopEvent: { classPropertyName: "ignoreStopEvent", publicName: "ignoreStopEvent", isSignal: true, isRequired: false, transformFunction: null }, onlyMouseDownStopEvent: { classPropertyName: "onlyMouseDownStopEvent", publicName: "onlyMouseDownStopEvent", isSignal: true, isRequired: false, transformFunction: null }, dragRootElement: { classPropertyName: "dragRootElement", publicName: "dragRootElement", isSignal: true, isRequired: false, transformFunction: null }, groupName: { classPropertyName: "groupName", publicName: "groupName", isSignal: true, isRequired: false, transformFunction: null }, dragBoundary: { classPropertyName: "dragBoundary", publicName: "dragBoundary", isSignal: true, isRequired: false, transformFunction: null }, dragBoundaryAcceptMouseLeaveContainer: { classPropertyName: "dragBoundaryAcceptMouseLeaveContainer", publicName: "dragBoundaryAcceptMouseLeaveContainer", isSignal: true, isRequired: false, transformFunction: null }, elementContainer: { classPropertyName: "elementContainer", publicName: "elementContainer", isSignal: true, isRequired: false, transformFunction: null }, zIndex: { classPropertyName: "zIndex", publicName: "zIndex", isSignal: true, isRequired: false, transformFunction: null }, disable: { classPropertyName: "disable", publicName: "disable", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { outDragStart: "outDragStart", outDragOver: "outDragOver", outDragLeave: "outDragLeave", outDragEnd: "outDragEnd", outDropped: "outDropped" }, usesInheritance: true, ngImport: i0 });
1161
+ }
1162
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LibsUiDragItemDirective, decorators: [{
1163
+ type: Directive,
1164
+ args: [{
1165
+ // eslint-disable-next-line @angular-eslint/directive-selector
1166
+ selector: "[LibsUiDragItemDirective]",
1167
+ standalone: true
1168
+ }]
1169
+ }], ctorParameters: () => [] });
1170
+
1171
+ /**
1172
+ * Generated bundle index. Do not edit.
1173
+ */
1174
+
1175
+ export { LibsUiComponentsDragContainerDirective, LibsUiComponentsDragScrollDirective, LibsUiDragItemDirective, LibsUiDragItemInContainerVirtualScrollDirective };
1176
+ //# sourceMappingURL=libs-ui-components-drag-drop.mjs.map