From 34a5ad18672d1ed160b134ecd85d41696559c2e5 Mon Sep 17 00:00:00 2001 From: John White <750350+johnhwhite@users.noreply.github.com> Date: Sun, 26 Feb 2023 13:58:09 -0500 Subject: [PATCH] feat: emit drop event --- .../src/lib/keyboard-sort-event-drop.ts | 6 +++ .../src/lib/keyboard-sort-item.directive.ts | 5 ++ .../lib/keyboard-sort-list.directive.spec.ts | 7 +++ .../src/lib/keyboard-sort-list.directive.ts | 49 ++++++++++++++++--- 4 files changed, 61 insertions(+), 6 deletions(-) create mode 100644 libs/ng-keyboard-sort/src/lib/keyboard-sort-event-drop.ts diff --git a/libs/ng-keyboard-sort/src/lib/keyboard-sort-event-drop.ts b/libs/ng-keyboard-sort/src/lib/keyboard-sort-event-drop.ts new file mode 100644 index 0000000..5b651f2 --- /dev/null +++ b/libs/ng-keyboard-sort/src/lib/keyboard-sort-event-drop.ts @@ -0,0 +1,6 @@ +export interface KeyboardSortEventDrop { + /** Index of the item when it was picked up. */ + previousIndex: number; + /** Current index of the item. */ + currentIndex: number; +} diff --git a/libs/ng-keyboard-sort/src/lib/keyboard-sort-item.directive.ts b/libs/ng-keyboard-sort/src/lib/keyboard-sort-item.directive.ts index dd31176..84f48de 100644 --- a/libs/ng-keyboard-sort/src/lib/keyboard-sort-item.directive.ts +++ b/libs/ng-keyboard-sort/src/lib/keyboard-sort-item.directive.ts @@ -52,6 +52,7 @@ export class KeyboardSortItemDirective implements AfterViewInit, OnDestroy { this.focused = false; } this.#activated = value; + this.#list?.capturePreviousIndex(this); this.kbdSortItemActivated.emit(value); } @@ -117,6 +118,9 @@ export class KeyboardSortItemDirective implements AfterViewInit, OnDestroy { public ngAfterViewInit(): void { this.onNextStable(() => { this.updateEvents(); + if (this.activated) { + this.activated = true; + } this.#subscriptions.add( this.handles?.changes.subscribe(() => { this.updateEvents(); @@ -154,6 +158,7 @@ export class KeyboardSortItemDirective implements AfterViewInit, OnDestroy { public deactivate() { if (this.activated) { + this.#list?.dropItem(this); this.activated = false; this.#renderer.removeClass( this.elementRef.nativeElement, diff --git a/libs/ng-keyboard-sort/src/lib/keyboard-sort-list.directive.spec.ts b/libs/ng-keyboard-sort/src/lib/keyboard-sort-list.directive.spec.ts index b7ea168..6aa3d8f 100644 --- a/libs/ng-keyboard-sort/src/lib/keyboard-sort-list.directive.spec.ts +++ b/libs/ng-keyboard-sort/src/lib/keyboard-sort-list.directive.spec.ts @@ -148,6 +148,8 @@ describe('ListDirective', () => { setupTest({ direction: direction as 'horizontal' | 'vertical', }); + const dropSpy = jasmine.createSpy('dropSpy'); + component.list?.kdbSortDrop.subscribe(dropSpy); expect(component.list).toBeTruthy(); const lastItem = getItem(2); expect(lastItem).toBeTruthy(); @@ -156,6 +158,11 @@ describe('ListDirective', () => { fixture.detectChanges(); tick(); expect(component.data).toEqual(['Item 1', 'Item 3', 'Item 2']); + expect(dropSpy).toHaveBeenCalledTimes(1); + expect(dropSpy).toHaveBeenCalledWith({ + previousIndex: 2, + currentIndex: 1, + }); })); it(`should move item down in ${direction} direction`, fakeAsync(() => { diff --git a/libs/ng-keyboard-sort/src/lib/keyboard-sort-list.directive.ts b/libs/ng-keyboard-sort/src/lib/keyboard-sort-list.directive.ts index 9920fa7..00d94a9 100644 --- a/libs/ng-keyboard-sort/src/lib/keyboard-sort-list.directive.ts +++ b/libs/ng-keyboard-sort/src/lib/keyboard-sort-list.directive.ts @@ -18,6 +18,7 @@ import { filter, Subscription, take } from 'rxjs'; import { DOCUMENT } from '@angular/common'; import { KeyboardSortEvent } from './keyboard-sort-event'; import { KeyboardSortService } from './keyboard-sort.service'; +import { KeyboardSortEventDrop } from './keyboard-sort-event-drop'; @Directive({ selector: '[kbdSortList]', @@ -52,6 +53,9 @@ export class KeyboardSortListDirective implements OnDestroy { @Output() public kbdSortEnabled = new EventEmitter(); + @Output() + public kdbSortDrop = new EventEmitter(); + @Output() public kdbSortEnd = new EventEmitter(); @@ -61,6 +65,8 @@ export class KeyboardSortListDirective implements OnDestroy { #elementRef: ElementRef; #subscriptions = new Subscription(); #kbdSortListDisabled = false; + #previousIndex: number | undefined; + #currentIndex: number | undefined; constructor( readonly changeDetectorRef: ChangeDetectorRef, @@ -86,17 +92,20 @@ export class KeyboardSortListDirective implements OnDestroy { this.#doc.activeElement && !this.#elementRef.nativeElement.contains(this.#doc.activeElement) ) { - this.items?.forEach((item) => { - item.deactivate(); - }); - this.kdbSortEnd.emit({ - list: this, - }); + this.deactivateAll(); } } @HostListener('document:keydown.Escape') public deactivateAll(): void { + if (this.#previousIndex !== undefined && this.#currentIndex !== undefined) { + this.kdbSortDrop.emit({ + previousIndex: this.#previousIndex, + currentIndex: this.#currentIndex, + }); + this.#previousIndex = undefined; + this.#currentIndex = undefined; + } this.items?.forEach((item) => { item.deactivate(); }); @@ -141,6 +150,10 @@ export class KeyboardSortListDirective implements OnDestroy { const currentPosition = items.indexOf(item); if (currentPosition > 0) { const moveToIndex = currentPosition - 1; + if (!this.#previousIndex) { + this.#previousIndex = currentPosition; + } + this.#currentIndex = moveToIndex; if (this.kbdSortListData) { moveItemInArray(this.kbdSortListData, currentPosition, moveToIndex); this.#changeDetectorRef.detectChanges(); @@ -160,6 +173,10 @@ export class KeyboardSortListDirective implements OnDestroy { const currentPosition = items.indexOf(item); if (currentPosition > -1 && currentPosition < items.length - 1) { const moveToIndex = currentPosition + 1; + if (!this.#previousIndex) { + this.#previousIndex = currentPosition; + } + this.#currentIndex = moveToIndex; if (this.kbdSortListData) { moveItemInArray(this.kbdSortListData, currentPosition, moveToIndex); this.#changeDetectorRef.detectChanges(); @@ -185,6 +202,26 @@ export class KeyboardSortListDirective implements OnDestroy { }); } + public dropItem(item: KeyboardSortItemDirective): void { + if ( + item.activated && + this.#previousIndex !== undefined && + this.#currentIndex !== undefined && + this.#previousIndex !== this.#currentIndex + ) { + this.kdbSortDrop.emit({ + previousIndex: this.#previousIndex, + currentIndex: this.#currentIndex, + }); + } + } + + public capturePreviousIndex(item: KeyboardSortItemDirective): void { + if (item.activated) { + this.#previousIndex = this.items?.toArray().indexOf(item); + } + } + private onNextStable(cb: () => void): void { this.#subscriptions.add( this.#appRef.isStable