201 lines
25 KiB
JavaScript
201 lines
25 KiB
JavaScript
|
import { Directive, ElementRef, EventEmitter, forwardRef, HostBinding, HostListener, inject, Input, NgZone, Output, Renderer2, } from '@angular/core';
|
||
|
import { dndState, endDrag, startDrag } from './dnd-state';
|
||
|
import { calculateDragImageOffset, setDragData, setDragImage, } from './dnd-utils';
|
||
|
import * as i0 from "@angular/core";
|
||
|
class DndDragImageRefDirective {
|
||
|
dndDraggableDirective = inject(forwardRef(() => DndDraggableDirective));
|
||
|
elementRef = inject(ElementRef);
|
||
|
ngOnInit() {
|
||
|
this.dndDraggableDirective.registerDragImage(this.elementRef);
|
||
|
}
|
||
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.1", ngImport: i0, type: DndDragImageRefDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
||
|
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.0.1", type: DndDragImageRefDirective, isStandalone: true, selector: "[dndDragImageRef]", ngImport: i0 });
|
||
|
}
|
||
|
export { DndDragImageRefDirective };
|
||
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.1", ngImport: i0, type: DndDragImageRefDirective, decorators: [{
|
||
|
type: Directive,
|
||
|
args: [{ selector: '[dndDragImageRef]', standalone: true }]
|
||
|
}] });
|
||
|
class DndDraggableDirective {
|
||
|
dndDraggable;
|
||
|
dndEffectAllowed = 'copy';
|
||
|
dndType;
|
||
|
dndDraggingClass = 'dndDragging';
|
||
|
dndDraggingSourceClass = 'dndDraggingSource';
|
||
|
dndDraggableDisabledClass = 'dndDraggableDisabled';
|
||
|
dndDragImageOffsetFunction = calculateDragImageOffset;
|
||
|
dndStart = new EventEmitter();
|
||
|
dndDrag = new EventEmitter();
|
||
|
dndEnd = new EventEmitter();
|
||
|
dndMoved = new EventEmitter();
|
||
|
dndCopied = new EventEmitter();
|
||
|
dndLinked = new EventEmitter();
|
||
|
dndCanceled = new EventEmitter();
|
||
|
draggable = true;
|
||
|
dndHandle;
|
||
|
dndDragImageElementRef;
|
||
|
dragImage;
|
||
|
isDragStarted = false;
|
||
|
elementRef = inject(ElementRef);
|
||
|
renderer = inject(Renderer2);
|
||
|
ngZone = inject(NgZone);
|
||
|
set dndDisableIf(value) {
|
||
|
this.draggable = !value;
|
||
|
if (this.draggable) {
|
||
|
this.renderer.removeClass(this.elementRef.nativeElement, this.dndDraggableDisabledClass);
|
||
|
}
|
||
|
else {
|
||
|
this.renderer.addClass(this.elementRef.nativeElement, this.dndDraggableDisabledClass);
|
||
|
}
|
||
|
}
|
||
|
set dndDisableDragIf(value) {
|
||
|
this.dndDisableIf = value;
|
||
|
}
|
||
|
ngAfterViewInit() {
|
||
|
this.ngZone.runOutsideAngular(() => {
|
||
|
this.elementRef.nativeElement.addEventListener('drag', this.dragEventHandler);
|
||
|
});
|
||
|
}
|
||
|
ngOnDestroy() {
|
||
|
this.elementRef.nativeElement.removeEventListener('drag', this.dragEventHandler);
|
||
|
if (this.isDragStarted) {
|
||
|
endDrag();
|
||
|
}
|
||
|
}
|
||
|
onDragStart(event) {
|
||
|
if (!this.draggable) {
|
||
|
return false;
|
||
|
}
|
||
|
// check if there is dnd handle and if the dnd handle was used to start the drag
|
||
|
if (this.dndHandle != null && event._dndUsingHandle == null) {
|
||
|
event.stopPropagation();
|
||
|
return false;
|
||
|
}
|
||
|
// initialize global state
|
||
|
startDrag(event, this.dndEffectAllowed, this.dndType);
|
||
|
this.isDragStarted = true;
|
||
|
setDragData(event, { data: this.dndDraggable, type: this.dndType }, dndState.effectAllowed);
|
||
|
this.dragImage = this.determineDragImage();
|
||
|
// set dragging css class prior to setDragImage so styles are applied before
|
||
|
// TODO breaking change: add class to elementRef rather than drag image which could be another element
|
||
|
this.renderer.addClass(this.dragImage, this.dndDraggingClass);
|
||
|
// set custom dragimage if present
|
||
|
// set dragimage if drag is started from dndHandle
|
||
|
if (this.dndDragImageElementRef != null || event._dndUsingHandle != null) {
|
||
|
setDragImage(event, this.dragImage, this.dndDragImageOffsetFunction);
|
||
|
}
|
||
|
// add dragging source css class on first drag event
|
||
|
const unregister = this.renderer.listen(this.elementRef.nativeElement, 'drag', () => {
|
||
|
this.renderer.addClass(this.elementRef.nativeElement, this.dndDraggingSourceClass);
|
||
|
unregister();
|
||
|
});
|
||
|
this.dndStart.emit(event);
|
||
|
event.stopPropagation();
|
||
|
setTimeout(() => {
|
||
|
this.renderer.setStyle(this.dragImage, 'pointer-events', 'none');
|
||
|
}, 100);
|
||
|
return true;
|
||
|
}
|
||
|
onDrag(event) {
|
||
|
this.dndDrag.emit(event);
|
||
|
}
|
||
|
onDragEnd(event) {
|
||
|
if (!this.draggable || !this.isDragStarted) {
|
||
|
return;
|
||
|
}
|
||
|
// get drop effect from custom stored state as its not reliable across browsers
|
||
|
const dropEffect = dndState.dropEffect;
|
||
|
this.renderer.setStyle(this.dragImage, 'pointer-events', 'unset');
|
||
|
let dropEffectEmitter;
|
||
|
switch (dropEffect) {
|
||
|
case 'copy':
|
||
|
dropEffectEmitter = this.dndCopied;
|
||
|
break;
|
||
|
case 'link':
|
||
|
dropEffectEmitter = this.dndLinked;
|
||
|
break;
|
||
|
case 'move':
|
||
|
dropEffectEmitter = this.dndMoved;
|
||
|
break;
|
||
|
default:
|
||
|
dropEffectEmitter = this.dndCanceled;
|
||
|
break;
|
||
|
}
|
||
|
dropEffectEmitter.emit(event);
|
||
|
this.dndEnd.emit(event);
|
||
|
// reset global state
|
||
|
endDrag();
|
||
|
this.isDragStarted = false;
|
||
|
this.renderer.removeClass(this.dragImage, this.dndDraggingClass);
|
||
|
// IE9 special hammering
|
||
|
window.setTimeout(() => {
|
||
|
this.renderer.removeClass(this.elementRef.nativeElement, this.dndDraggingSourceClass);
|
||
|
}, 0);
|
||
|
event.stopPropagation();
|
||
|
}
|
||
|
registerDragHandle(handle) {
|
||
|
this.dndHandle = handle;
|
||
|
}
|
||
|
registerDragImage(elementRef) {
|
||
|
this.dndDragImageElementRef = elementRef;
|
||
|
}
|
||
|
dragEventHandler = (event) => this.onDrag(event);
|
||
|
determineDragImage() {
|
||
|
// evaluate custom drag image existence
|
||
|
if (typeof this.dndDragImageElementRef !== 'undefined') {
|
||
|
return this.dndDragImageElementRef.nativeElement;
|
||
|
}
|
||
|
else {
|
||
|
return this.elementRef.nativeElement;
|
||
|
}
|
||
|
}
|
||
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.1", ngImport: i0, type: DndDraggableDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
||
|
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.0.1", type: DndDraggableDirective, isStandalone: true, selector: "[dndDraggable]", inputs: { dndDraggable: "dndDraggable", dndEffectAllowed: "dndEffectAllowed", dndType: "dndType", dndDraggingClass: "dndDraggingClass", dndDraggingSourceClass: "dndDraggingSourceClass", dndDraggableDisabledClass: "dndDraggableDisabledClass", dndDragImageOffsetFunction: "dndDragImageOffsetFunction", dndDisableIf: "dndDisableIf", dndDisableDragIf: "dndDisableDragIf" }, outputs: { dndStart: "dndStart", dndDrag: "dndDrag", dndEnd: "dndEnd", dndMoved: "dndMoved", dndCopied: "dndCopied", dndLinked: "dndLinked", dndCanceled: "dndCanceled" }, host: { listeners: { "dragstart": "onDragStart($event)", "dragend": "onDragEnd($event)" }, properties: { "attr.draggable": "this.draggable" } }, ngImport: i0 });
|
||
|
}
|
||
|
export { DndDraggableDirective };
|
||
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.1", ngImport: i0, type: DndDraggableDirective, decorators: [{
|
||
|
type: Directive,
|
||
|
args: [{ selector: '[dndDraggable]', standalone: true }]
|
||
|
}], propDecorators: { dndDraggable: [{
|
||
|
type: Input
|
||
|
}], dndEffectAllowed: [{
|
||
|
type: Input
|
||
|
}], dndType: [{
|
||
|
type: Input
|
||
|
}], dndDraggingClass: [{
|
||
|
type: Input
|
||
|
}], dndDraggingSourceClass: [{
|
||
|
type: Input
|
||
|
}], dndDraggableDisabledClass: [{
|
||
|
type: Input
|
||
|
}], dndDragImageOffsetFunction: [{
|
||
|
type: Input
|
||
|
}], dndStart: [{
|
||
|
type: Output
|
||
|
}], dndDrag: [{
|
||
|
type: Output
|
||
|
}], dndEnd: [{
|
||
|
type: Output
|
||
|
}], dndMoved: [{
|
||
|
type: Output
|
||
|
}], dndCopied: [{
|
||
|
type: Output
|
||
|
}], dndLinked: [{
|
||
|
type: Output
|
||
|
}], dndCanceled: [{
|
||
|
type: Output
|
||
|
}], draggable: [{
|
||
|
type: HostBinding,
|
||
|
args: ['attr.draggable']
|
||
|
}], dndDisableIf: [{
|
||
|
type: Input
|
||
|
}], dndDisableDragIf: [{
|
||
|
type: Input
|
||
|
}], onDragStart: [{
|
||
|
type: HostListener,
|
||
|
args: ['dragstart', ['$event']]
|
||
|
}], onDragEnd: [{
|
||
|
type: HostListener,
|
||
|
args: ['dragend', ['$event']]
|
||
|
}] } });
|
||
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZG5kLWRyYWdnYWJsZS5kaXJlY3RpdmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9kbmQvc3JjL2xpYi9kbmQtZHJhZ2dhYmxlLmRpcmVjdGl2ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBRUwsU0FBUyxFQUNULFVBQVUsRUFDVixZQUFZLEVBQ1osVUFBVSxFQUNWLFdBQVcsRUFDWCxZQUFZLEVBQ1osTUFBTSxFQUNOLEtBQUssRUFDTCxNQUFNLEVBR04sTUFBTSxFQUNOLFNBQVMsR0FDVixNQUFNLGVBQWUsQ0FBQztBQUV2QixPQUFPLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFFM0QsT0FBTyxFQUNMLHdCQUF3QixFQUd4QixXQUFXLEVBQ1gsWUFBWSxHQUNiLE1BQU0sYUFBYSxDQUFDOztBQUVyQixNQUNhLHdCQUF3QjtJQUNuQyxxQkFBcUIsR0FBRyxNQUFNLENBQUMsVUFBVSxDQUFDLEdBQUcsRUFBRSxDQUFDLHFCQUFxQixDQUFDLENBQUMsQ0FBQztJQUN4RSxVQUFVLEdBQTRCLE1BQU0sQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUV6RCxRQUFRO1FBQ04sSUFBSSxDQUFDLHFCQUFxQixDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUNoRSxDQUFDO3VHQU5VLHdCQUF3QjsyRkFBeEIsd0JBQXdCOztTQUF4Qix3QkFBd0I7MkZBQXhCLHdCQUF3QjtrQkFEcEMsU0FBUzttQkFBQyxFQUFFLFFBQVEsRUFBRSxtQkFBbUIsRUFBRSxVQUFVLEVBQUUsSUFBSSxFQUFFOztBQVU5RCxNQUNhLHFCQUFxQjtJQUN2QixZQUFZLENBQU07SUFDbEIsZ0JBQWdCLEdBQWtCLE1BQU0sQ0FBQztJQUN6QyxPQUFPLENBQVU7SUFDakIsZ0JBQWdCLEdBQUcsYUFBYSxDQUFDO0lBQ2pDLHNCQUFzQixHQUFHLG1CQUFt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
|