npm package: @rivenfx/ngx-drag-drop
Description: 升级到 angular12 的 [ngx-drag-drop](https://github.com/reppners/ngx-drag-drop)
Author: staneee
Latest version: 12.0.1

# @rivenfx/ngx-drag-drop

升级到 angular12 的 [ngx-drag-drop](https://github.com/reppners/ngx-drag-drop)


## 变更部分
* 指令 `dndDropzone` 修改为 `dndDropZone`



----

# 原仓库 README

[![npm](https://img.shields.io/npm/v/ngx-drag-drop.svg)](https://www.npmjs.com/package/ngx-drag-drop)
[![npm (next)](https://img.shields.io/npm/v/ngx-drag-drop/next.svg)](https://www.npmjs.com/package/ngx-drag-drop)
[![NpmLicense](https://img.shields.io/npm/l/ngx-drag-drop.svg)](https://www.npmjs.com/package/ngx-drag-drop)
[![GitHub issues](https://img.shields.io/github/issues/reppners/ngx-drag-drop.svg)](https://github.com/reppners/ngx-drag-drop/issues)
[![Twitter](https://img.shields.io/twitter/url/https/github.com/reppners/ngx-drag-drop.svg?style=social)](https://twitter.com/intent/tweet?text=Angular%20drag%20and%20drop%20with%20ease:&url=https://github.com/reppners/ngx-drag-drop)


# NgxDragDrop

[_Demo_](https://reppners.github.io/ngx-drag-drop/) / [_StackBlitz Issue Template_](https://stackblitz.com/edit/ngx-drag-drop-issue-template)

`npm install ngx-drag-drop --save`

**Angular directives for declarative drag and drop using the HTML5 Drag-And-Drop API**

* sortable lists by using placeholder element (vertical and horizontal)
* nestable
* dropzones optionally support external/native draggables (img, txt, file)
* conditional drag/drop
* typed drag/drop
* utilize [EffectAllowed](https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/effectAllowed)
* custom CSS classes
* touch support by using a [polyfill](#touch-support)
* [AOT](https://angular.io/guide/aot-compiler) compatible

Port of [angular-drag-drop-lists](https://github.com/marceljuenemann/angular-drag-and-drop-lists) but without the lists :wink:

This has `dropzones` though :+1:
The idea is that the directive does not handle lists internally so the `dndDropzone` can be general purpose.


## Usage

`app.component.html`
```HTML
<!--a draggable element-->
<div [dndDraggable]="draggable.data"
     [dndEffectAllowed]="draggable.effectAllowed"
     [dndDisableIf]="draggable.disable"
     (dndStart)="onDragStart($event)"
     (dndCopied)="onDraggableCopied($event)"
     (dndLinked)="onDraggableLinked($event)"
     (dndMoved)="onDraggableMoved($event)"
     (dndCanceled)="onDragCanceled($event)"
     (dndEnd)="onDragEnd($event)">
      
    <!--if [dndHandle] is used inside dndDraggable drag can only start from the handle-->
    <div *ngIf="draggable.handle"
         dndHandle>HANDLE
    </div>
    
    draggable ({{draggable.effectAllowed}}) <span [hidden]="!draggable.disable">DISABLED</span>
    
    <!--optionally select a child element as drag image-->
    <div dndDragImageRef>DRAG_IMAGE</div>
    
</div>

<!--a dropzone-->
<!--to allow dropping content that is not [dndDraggable] set dndAllowExternal to true-->
<section dndDropzone
         (dndDragover)="onDragover($event)"
         (dndDrop)="onDrop($event)">
      
    dropzone 
    
    <!--optional placeholder element for dropzone-->
    <!--will be removed from DOM on init-->
    <div style="border: 1px orangered solid; border-radius: 5px; padding: 15px;"
         dndPlaceholderRef>
        placeholder
    </div>

</section>
```

`app.component`
```JS
import { Component } from '@angular/core';

import { DndDropEvent } from 'ngx-drag-drop';

@Component()
export class AppComponent {
  
  draggable = {
    // note that data is handled with JSON.stringify/JSON.parse
    // only set simple data or POJO's as methods will be lost 
    data: "myDragData",
    effectAllowed: "all",
    disable: false,
    handle: false
  };
  
  onDragStart(event:DragEvent) {

    console.log("drag started", JSON.stringify(event, null, 2));
  }
  
  onDragEnd(event:DragEvent) {
    
    console.log("drag ended", JSON.stringify(event, null, 2));
  }
  
  onDraggableCopied(event:DragEvent) {
    
    console.log("draggable copied", JSON.stringify(event, null, 2));
  }
  
  onDraggableLinked(event:DragEvent) {
      
    console.log("draggable linked", JSON.stringify(event, null, 2));
  }
    
  onDraggableMoved(event:DragEvent) {
    
    console.log("draggable moved", JSON.stringify(event, null, 2));
  }
      
  onDragCanceled(event:DragEvent) {
    
    console.log("drag cancelled", JSON.stringify(event, null, 2));
  }
  
  onDragover(event:DragEvent) {
    
    console.log("dragover", JSON.stringify(event, null, 2));
  }
  
  onDrop(event:DndDropEvent) {
  
    console.log("dropped", JSON.stringify(event, null, 2));
  }
}
```

`app.module`

```JS
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { DndModule } from 'ngx-drag-drop';

import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    DndModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { 
}
```

## API

```TS
// https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/dropEffect
export type DropEffect = "move" | "copy" | "link" | "none";

// https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/effectAllowed
export type EffectAllowed = DropEffect | "copyMove" | "copyLink" | "linkMove" | "all";
```

```TS
export type DndDragImageOffsetFunction = ( event:DragEvent, dragImage:Element ) => { x:number, y:number };

@Directive( {
  selector: "[dndDraggable]"
} )
export declare class DndDraggableDirective {

    // the data attached to the drag
    dndDraggable: any;
    
    // the allowed drop effect
    dndEffectAllowed: EffectAllowed;
    
    // optionally set the type of dragged data to restrict dropping on compatible dropzones
    dndType?: string;
    
    // conditionally disable the draggability
    dndDisableIf: boolean;
    dndDisableDragIf: boolean;
    
    // set a custom class that is applied while dragging
    dndDraggingClass: string = "dndDragging";
    
    // set a custom class that is applied to only the src element while dragging
    dndDraggingSourceClass: string = "dndDraggingSource";
    
    // set the class that is applied when draggable is disabled by [dndDisableIf]
    dndDraggableDisabledClass = "dndDraggableDisabled";
    
    // enables to set a function for calculating custom dragimage offset
    dndDragImageOffsetFunction:DndDragImageOffsetFunction = calculateDragImageOffset;
    
    // emits on drag start
    readonly dndStart: EventEmitter<DragEvent>;
    
    // emits on drag
    readonly dndDrag: EventEmitter<DragEvent>;
    
    // emits on drag end
    readonly dndEnd: EventEmitter<DragEvent>;
    
    // emits when the dragged item has been dropped with effect "move"
    readonly dndMoved: EventEmitter<DragEvent>;
    
    // emits when the dragged item has been dropped with effect "copy"
    readonly dndCopied: EventEmitter<DragEvent>;
    
    // emits when the dragged item has been dropped with effect "link"
    readonly dndLinked: EventEmitter<DragEvent>;
    
    // emits when the drag is canceled
    readonly dndCanceled: EventEmitter<DragEvent>;
}
```

```TS
export interface DndDropEvent {

    // the original drag event
    event: DragEvent;
    
    // the actual drop effect
    dropEffect: DropEffect;
    
    // true if the drag did not origin from a [dndDraggable]
    isExternal:boolean;
    
    // the data set on the [dndDraggable] that started the drag 
    // for external drags use the event property which contains the original drop event as this will be undefined
    data?: any;
    
    // the index where the draggable was dropped in a dropzone
    // set only when using a placeholder
    index?: number;
    
    // if the dndType input on dndDraggable was set
    // it will be transported here
    type?: any;
}

@Directive( {
  selector: "[dndDropzone]"
} )
export declare class DndDropzoneDirective {

    // optionally restrict the allowed types
    dndDropzone?: string[];
    
    // set the allowed drop effect
    dndEffectAllowed: EffectAllowed;
    
    // conditionally disable the dropzone
    dndDisableIf: boolean;
    dndDisableDropIf: boolean;
    
    // if draggables that are not [dndDraggable] are allowed to be dropped
    // set to true if dragged text, images or files should be handled
    dndAllowExternal: boolean;
    
    // if its a horizontal list this influences how the placeholder position
    // is calculated
    dndHorizontal: boolean;
    
    // set the class applied to the dropzone
    // when a draggable is dragged over it
    dndDragoverClass: string = "dndDragover";
    
    // set the class applied to the dropzone
    // when the dropzone is disabled by [dndDisableIf] 
    dndDropzoneDisabledClass = "dndDropzoneDisabled";
    
    // emits when a draggable is dragged over the dropzone
    readonly dndDragover: EventEmitter<DragEvent>;
    
    // emits on successful drop
    readonly dndDrop: EventEmitter<DndDropEvent>;
}
```

## Touch support

Install the `mobile-drag-drop` module available on npm.

Add the following lines to your js code
```JS
import { polyfill } from 'mobile-drag-drop';
// optional import of scroll behaviour
import { scrollBehaviourDragImageTranslateOverride } from "mobile-drag-drop/scroll-behaviour";

polyfill( {
  // use this to make use of the scroll behaviour
  dragImageTranslateOverride: scrollBehaviourDragImageTranslateOverride
} );

// workaround to make scroll prevent work in iOS Safari > 10
try {
  window.addEventListener( "touchmove", function() { }, { passive: false } );
}
catch(e){}
```

For more info on the polyfill check it out on GitHub
https://github.com/timruffles/mobile-drag-drop

## Known issues

### Firefox

* Beware that Firefox does not support dragging on `<button>` elements.
  * `<button [dndDraggable]>` and `<button [dndHandler]>` won't work. 
  * See https://bugzilla.mozilla.org/show_bug.cgi?id=568313 


## Why?

HTML Drag-And-Drop API implementations are not behaving the same way across browsers.

The directives contained in this module enable declarative drag and drop that "just works" across browsers in a consistent way.

Credits go to the author and contributors of [angular-drag-drop-lists](https://github.com/marceljuenemann/angular-drag-and-drop-lists). 

## Maintenance

This project was generated with [Angular CLI](https://github.com/angular/angular-cli).

For the library build it uses [ng-packagr](https://github.com/dherges/ng-packagr).

#### Edit Library

* edit lib code
* run `npm start` (currently needs to be re-run on every lib code change)

#### Release Library

* assure correct version is set in `package.json`
* build library with `npm run build:lib`
* publish library with `npm run publish:stable` (use `npm run publish:next` for pre-releases)

#### Release Docs

* build docs site with `npm run build:docs`
* commit and push changes in `docs` to `master`


---

<p align="center">
Made with :heart: & 
<a href="https://www.jetbrains.com/?from=ngx-drag-drop">
  <img align="center" alt="jetbrains" src="jetbrains.svg" width="120px" />
</a>
& :coffee:
</p>