@vdnd/v3
Version:
A Vue drag-and-drop component library that is easy to use.
564 lines (552 loc) • 24.1 kB
TypeScript
import * as vue from 'vue';
import { HTMLAttributes, MaybeRef, ComputedRef, DefineSetupFnComponent } from 'vue';
type DndHandleProps = HTMLAttributes & {
tag?: string;
};
declare const DndHandle$1: vue.DefineSetupFnComponent<DndHandleProps, {}, {}, HTMLAttributes & {
tag?: string;
} & {}, vue.PublicProps>;
type DndElement = {
label: string;
data: any;
};
type DndDropzoneProps<T extends DndElement> = HTMLAttributes & (T['data'] extends undefined ? {
tag?: string;
label: T['label'];
data?: T['data'];
} : {
tag?: string;
label: T['label'];
/**
* Don't pass `undefined` as `data`.
*
* The union with `undefined` here is to ensure that the type inferring of the `label` is friendly enough.
*/
data: T['data'] | undefined;
});
type DistributeDndDropzoneProps<T extends DndElement = DndElement> = T extends any ? DndDropzoneProps<T> : never;
type DndSourceProps<T extends DndElement> = HTMLAttributes & (T['data'] extends undefined ? {
tag?: string;
label: T['label'];
data?: T['data'];
} : {
tag?: string;
label: T['label'];
/**
* Don't pass `undefined` as `data`.
*
* The union with `undefined` here is to ensure that the type inferring of the `label` is friendly enough.
*/
data: T['data'] | undefined;
});
type DistributeDndSourceProps<T extends DndElement = DndElement> = T extends any ? DndSourceProps<T> : never;
type DragEvent<S extends DndElement = DndElement, Over extends DndElement = DndElement> = {
type: 'drag';
/**
* The current drag source.
*/
source: S;
/**
* The current drop target.
*/
over: Over | undefined;
originalEvent: globalThis.DragEvent;
};
type DragStartEvent<S extends DndElement = DndElement> = {
type: 'dragstart';
/**
* The current drag source.
*/
source: S;
originalEvent: globalThis.DragEvent;
};
type DragPreventEvent<S extends DndElement = DndElement> = {
type: 'dragprevent';
/**
* The disabled drag source.
*/
source: S;
originalEvent: globalThis.DragEvent;
};
type DragEnterEvent<S extends DndElement = DndElement, Enter extends DndElement = DndElement> = {
type: 'dragenter';
/**
* The current drag source.
*/
source: S;
/**
* The current drop target.
*/
enter: Enter;
originalEvent: globalThis.DragEvent;
};
type DragOverEvent<S extends DndElement = DndElement, Over extends DndElement = DndElement> = {
type: 'dragover';
/**
* The current drag source.
*/
source: S;
/**
* The current drop target.
*/
over: Over;
originalEvent: globalThis.DragEvent;
};
type DragLeaveEvent<S extends DndElement = DndElement, Leave extends DndElement = DndElement, Enter extends DndElement = Leave> = {
type: 'dragleave';
/**
* The current drag source.
*/
source: S;
/**
* The previous current drop target.
*/
leave: Leave;
/**
* The current drop target.
*/
enter: Enter | undefined;
originalEvent: globalThis.DragEvent;
};
type DropEvent<S extends DndElement = DndElement, Dropzone extends DndElement = DndElement> = {
type: 'drop';
/**
* The current drag source.
*/
source: S;
/**
* The current drop target.
*/
dropzone: Dropzone;
originalEvent: globalThis.DragEvent;
};
type DragEndEvent<S extends DndElement = DndElement, Over extends DndElement = DndElement> = {
type: 'dragend';
/**
* The current drag source.
*/
source: S;
/**
* The current drop target.
*/
over: Over | undefined;
originalEvent: globalThis.DragEvent;
};
type PickDndElement<T extends DndElement, Label extends string> = Extract<T, {
label: Label;
}>;
type NonNullableProps<O extends object> = {
[K in keyof O]: NonNullable<O[K]>;
};
type OnDrag<S extends DndElement, Over extends DndElement, Event extends DragEvent<S, Over> = DragEvent<S, Over>> = (e: Event) => void;
type OnDragStart<S extends DndElement> = (e: DragStartEvent<S>) => void;
type OnDragPrevent<S extends DndElement> = (e: DragPreventEvent<S>) => void;
type OnDragEnter<S extends DndElement, Enter extends DndElement> = (e: DragEnterEvent<S, Enter>) => void;
type OnDragOver<S extends DndElement, Over extends DndElement> = (e: DragOverEvent<S, Over>) => void;
type OnDragLeave<S extends DndElement, Leave extends DndElement, Enter extends DndElement> = (e: DragLeaveEvent<S, Leave, Enter>) => void;
type OnDrop<S extends DndElement, Dropzone extends DndElement> = (e: DropEvent<S, Dropzone>) => void;
type OnDragEnd<S extends DndElement, Over extends DndElement, Event extends DragEndEvent<S, Over> = DragEndEvent<S, Over>> = (e: Event) => void;
type Draggable<S extends DndElement = DndElement> = MaybeRef<boolean> | ComputedRef<boolean> | ((source: S) => boolean);
type Droppable<S extends DndElement = DndElement, D extends DndElement = DndElement> = MaybeRef<boolean> | ComputedRef<boolean> | ((dropzone: D, source: S) => boolean);
type DropEffect<S extends DndElement = DndElement, D extends DndElement = DndElement> = MaybeRef<Exclude<DataTransfer['dropEffect'], 'none'>> | ComputedRef<Exclude<DataTransfer['dropEffect'], 'none'>> | ((dropzone: D, source: S) => Exclude<DataTransfer['dropEffect'], 'none'>);
type DndInteraction1<S extends DndElement = DndElement, D extends DndElement = DndElement> = {
scope: '*';
draggable?: Draggable<S>;
droppable?: Droppable<S, D>;
onDrag?: OnDrag<S, D>;
onDragStart?: OnDragStart<S>;
onDragPrevent?: OnDragPrevent<S>;
onDragEnter?: OnDragEnter<S, D>;
onDragOver?: OnDragOver<S, D>;
onDragLeave?: OnDragLeave<S, D, D>;
onDrop?: OnDrop<S, D>;
onDragEnd?: OnDragEnd<S, D>;
};
type DndInteraction2<S extends DndElement = DndElement, D extends DndElement = DndElement, SLabel extends S['label'] = S['label']> = {
scope: 's';
source: SLabel;
draggable?: Draggable<PickDndElement<S, SLabel>>;
onDrag?: OnDrag<PickDndElement<S, SLabel>, D>;
onDragStart?: OnDragStart<PickDndElement<S, SLabel>>;
onDragPrevent?: OnDragPrevent<PickDndElement<S, SLabel>>;
onDragEnter?: OnDragEnter<PickDndElement<S, SLabel>, D>;
onDragOver?: OnDragOver<PickDndElement<S, SLabel>, D>;
onDragLeave?: OnDragLeave<PickDndElement<S, SLabel>, D, D>;
onDrop?: OnDrop<PickDndElement<S, SLabel>, D>;
onDragEnd?: OnDragEnd<PickDndElement<S, SLabel>, D>;
};
type DistributiveDndInteraction2<S extends DndElement, D extends DndElement> = S extends any ? DndInteraction2<S, D> : never;
type DndInteraction3<S extends DndElement = DndElement, D extends DndElement = DndElement, E0 extends DndElement = D, DLabel extends D['label'] = D['label']> = {
scope: 'd';
dropzone: DLabel;
droppable?: Droppable<S, PickDndElement<D, DLabel>>;
onDrag?: OnDrag<S, PickDndElement<D, DLabel>, NonNullableProps<DragEvent<S, PickDndElement<D, DLabel>>>>;
onDragEnter?: OnDragEnter<S, PickDndElement<D, DLabel>>;
onDragOver?: OnDragOver<S, PickDndElement<D, DLabel>>;
onDragLeave?: OnDragLeave<S, PickDndElement<D, DLabel>, E0>;
onDrop?: OnDrop<S, PickDndElement<D, DLabel>>;
onDragEnd?: OnDragEnd<S, PickDndElement<D, DLabel>, NonNullableProps<DragEndEvent<S, PickDndElement<D, DLabel>>>>;
};
type DistributiveDndInteraction3<S extends DndElement, D extends DndElement, E0 extends DndElement = D> = D extends any ? DndInteraction3<S, D, E0> : never;
type DndInteraction4<S extends DndElement = DndElement, D extends DndElement = DndElement, E0 extends DndElement = D, SLabel extends S['label'] = S['label'], DLabel extends D['label'] = D['label']> = {
scope: 's+d';
source: SLabel;
dropzone: DLabel;
droppable?: Droppable<PickDndElement<S, SLabel>, PickDndElement<D, DLabel>>;
dropEffect?: DropEffect<PickDndElement<S, SLabel>, PickDndElement<D, DLabel>>;
onDrag?: OnDrag<PickDndElement<S, SLabel>, PickDndElement<D, DLabel>, NonNullableProps<DragEvent<PickDndElement<S, SLabel>, PickDndElement<D, DLabel>>>>;
onDragEnter?: OnDragEnter<PickDndElement<S, SLabel>, PickDndElement<D, DLabel>>;
onDragOver?: OnDragOver<PickDndElement<S, SLabel>, PickDndElement<D, DLabel>>;
onDragLeave?: OnDragLeave<PickDndElement<S, SLabel>, PickDndElement<D, DLabel>, E0>;
onDrop?: OnDrop<PickDndElement<S, SLabel>, PickDndElement<D, DLabel>>;
onDragEnd?: OnDragEnd<PickDndElement<S, SLabel>, PickDndElement<D, DLabel>, NonNullableProps<DragEndEvent<PickDndElement<S, SLabel>, PickDndElement<D, DLabel>>>>;
};
type DistributiveDndInteraction4<S extends DndElement, D extends DndElement, E0 extends DndElement = D> = S extends any ? (D extends any ? DndInteraction4<S, D, E0> : never) : never;
type DndInteraction<S extends DndElement = DndElement, D extends DndElement = DndElement, E0 extends DndElement = D> = DndInteraction1<S, D> | DistributiveDndInteraction2<S, D> | DistributiveDndInteraction3<S, D, E0> | DistributiveDndInteraction4<S, D, E0>;
type DndClasses = {
container?: string;
source?: string;
dropzone?: string;
handle?: string;
'source:dragging'?: string | string[];
'source:draggable'?: string | string[];
'source:disabled'?: string | string[];
'dropzone:over'?: string | string[];
'dropzone:droppable'?: string | string[];
'dropzone:disabled'?: string | string[];
};
type DndModelOptions<Source extends DndElement = DndElement, Dropzone extends DndElement = DndElement> = {
classes?: DndClasses;
interactions?: DndInteraction<Source, Dropzone>[];
};
type DndModel<Source extends DndElement = DndElement, Dropzone extends DndElement = DndElement> = ReturnType<typeof useDndModel$1<Source, Dropzone>>;
type NativeElement<T extends DndElement = DndElement> = {
role: 'container';
htmlEl: HTMLElement;
dndEl: undefined;
} | {
role: 'source';
htmlEl: HTMLElement;
dndEl: T;
} | {
role: 'dropzone';
htmlEl: HTMLElement;
dndEl: T;
} | {
role: 'handle';
htmlEl: HTMLElement;
dndEl: undefined;
};
type NativeElementRole = NativeElement['role'];
declare function useDndModel$1<Source extends DndElement = DndElement, Dropzone extends DndElement = DndElement>(options?: DndModelOptions<Source, Dropzone> | DndInteraction<Source, Dropzone>[]): vue.Raw<{
readonly classes: Readonly<Required<DndClasses>>;
readonly interactions: DndInteraction<Source, Dropzone>[];
readonly initialized: boolean;
readonly currentSource: Source | undefined;
readonly currentTarget: Dropzone | undefined;
isDragging: {
(): boolean;
(label: Source["label"]): boolean;
<Label extends Source["label"]>(label: Label, data: Extract<Source, {
label: Label;
}>["data"]): boolean;
(source: Source): boolean;
(predicate: (source: Source) => boolean): boolean;
};
isDraggable: {
(source: Source): boolean;
<Label extends Source["label"]>(label: Label, data: Extract<Source, {
label: Label;
}>["data"]): boolean;
};
isOver: {
(): boolean;
(label: Dropzone["label"]): boolean;
<Label extends Dropzone["label"]>(label: Label, data: Extract<Dropzone, {
label: Label;
}>["data"]): boolean;
(dropzone: Dropzone): boolean;
(predicate: (dropzone: Dropzone) => boolean): boolean;
};
isDroppable: {
(dropzone: Dropzone): boolean;
<Label extends Dropzone["label"]>(label: Label, data: Extract<Dropzone, {
label: Label;
}>["data"]): boolean;
};
defineInteraction: (interaction: DndInteraction<Source, Dropzone>) => void;
findHTMLElement: {
(role: "container"): HTMLElement | undefined;
<Role extends "source" | "dropzone">(role: Role, dndEl: Role extends "source" ? Source : Dropzone): HTMLElement | undefined;
};
findHTMLElements: {
(role: "handle"): HTMLElement[];
<Role extends "source" | "dropzone">(role: Role, label?: Role extends "source" ? Source["label"] : Dropzone["label"]): HTMLElement[];
};
findHandlesIn: (source: HTMLElement | Source) => HTMLElement[];
/**
* @internal
*/
$findDndElement: {
(role: "source", htmlEl: HTMLElement): Source | undefined;
(role: "dropzone", htmlEl: HTMLElement): Dropzone | undefined;
};
/**
* @internal
*/
$addNativeElement: <Role extends NativeElementRole>(role: Role, htmlEl: HTMLElement, dndEl: Role extends "source" | "dropzone" ? DndElement : undefined) => void;
/**
* @internal
*/
$removeNativeElement: (role: NativeElementRole, htmlEl: HTMLElement) => void;
/**
* @internal
*/
$setInitialized: (flag: boolean) => void;
/**
* @internal
*/
$setCurrentTarget: (value: Dropzone | undefined) => void;
/**
* @internal
*/
$setCurrentSource: (value: Source | undefined) => void;
}>;
declare function injectDndModel$1<Source extends DndElement = DndElement, Dropzone extends DndElement = DndElement>(): vue.Raw<{
readonly classes: Readonly<Required<DndClasses>>;
readonly interactions: DndInteraction<Source, Dropzone>[];
readonly initialized: boolean;
readonly currentSource: Source | undefined;
readonly currentTarget: Dropzone | undefined;
isDragging: {
(): boolean;
(label: Source["label"]): boolean;
<Label extends Source["label"]>(label: Label, data: Extract<Source, {
label: Label;
}>["data"]): boolean;
(source: Source): boolean;
(predicate: (source: Source) => boolean): boolean;
};
isDraggable: {
(source: Source): boolean;
<Label extends Source["label"]>(label: Label, data: Extract<Source, {
label: Label;
}>["data"]): boolean;
};
isOver: {
(): boolean;
(label: Dropzone["label"]): boolean;
<Label extends Dropzone["label"]>(label: Label, data: Extract<Dropzone, {
label: Label;
}>["data"]): boolean;
(dropzone: Dropzone): boolean;
(predicate: (dropzone: Dropzone) => boolean): boolean;
};
isDroppable: {
(dropzone: Dropzone): boolean;
<Label extends Dropzone["label"]>(label: Label, data: Extract<Dropzone, {
label: Label;
}>["data"]): boolean;
};
defineInteraction: (interaction: DndInteraction<Source, Dropzone>) => void;
findHTMLElement: {
(role: "container"): HTMLElement | undefined;
<Role extends "source" | "dropzone">(role: Role, dndEl: Role extends "source" ? Source : Dropzone): HTMLElement | undefined;
};
findHTMLElements: {
(role: "handle"): HTMLElement[];
<Role extends "source" | "dropzone">(role: Role, label?: (Role extends "source" ? Source["label"] : Dropzone["label"]) | undefined): HTMLElement[];
};
findHandlesIn: (source: HTMLElement | Source) => HTMLElement[];
/**
* @internal
*/
$findDndElement: {
(role: "source", htmlEl: HTMLElement): Source | undefined;
(role: "dropzone", htmlEl: HTMLElement): Dropzone | undefined;
};
/**
* @internal
*/
$addNativeElement: <Role extends NativeElementRole>(role: Role, htmlEl: HTMLElement, dndEl: Role extends "source" | "dropzone" ? DndElement : undefined) => void;
/**
* @internal
*/
$removeNativeElement: (role: NativeElementRole, htmlEl: HTMLElement) => void;
/**
* @internal
*/
$setInitialized: (flag: boolean) => void;
/**
* @internal
*/
$setCurrentTarget: (value: Dropzone | undefined) => void;
/**
* @internal
*/
$setCurrentSource: (value: Source | undefined) => void;
}> | undefined;
type DndContainerProps<Source extends DndElement = DndElement, Dropzone extends DndElement = DndElement> = HTMLAttributes & {
tag?: string;
model: DndModel<Source, Dropzone>;
};
type IDndSuite<Source extends DndElement = DndElement, Dropzone extends DndElement = DndElement> = {
useDndModel: typeof useDndModel$1<Source, Dropzone>;
/**
* Inject the dnd-model provided by the `DndContainer`.
*
* The `DndContainer` will provide the model it received for its descendant components.
*/
injectDndModel: typeof injectDndModel$1<Source, Dropzone>;
/**
* `DndContainer` defines the boundaries for drag-and-drop (DND) interactions and performs two key functions:
*
* 1、It detects DND interactions occurring within the container and synchronizes them with the `model`.
* Example: When a user drags a source and selects an element as the current drop target, the `DndContainer` calls the `onDragStart` and `onDragEnter` callbacks in the `model`.
*
* 2、It influences actual user interactions based on the interaction properties of the `model`.
* Example: If the `draggable` property of a source is set to false, the `DndContainer` prevents the user from dragging that source and calls the `onDragPrevent` callbacks in the `model`.
*/
DndContainer: DefineSetupFnComponent<DndContainerProps<Source, Dropzone>>;
/**
* `DndSource` represents an element that is allowed to be dragged, which we refer to as the "source".
*
* The source supports marking its type using the `label` property and binding custom data via the `data` property.
*/
DndSource: DefineSetupFnComponent<DistributeDndSourceProps<Source>>;
/**
* `DndDropzone` represents an area where the current drag source can be dropped, which we refer to as the "drop target".
*
* The drop target supports marking its type using the `label` property and binding custom data via the `data` property.
*/
DndDropzone: DefineSetupFnComponent<DistributeDndDropzoneProps<Dropzone>>;
/**
* `DndHandle` is the drag trigger for the source(`<DndSource />`).
*
* If we want to drag a source that contains drag triggers, we can only drag the source by dragging one of the triggers.
*
* Dragging other elements in the source will not put the source into drag mode, and the entire DND interaction will not begin.
*/
DndHandle: typeof DndHandle$1;
};
declare const DndSuite: IDndSuite;
declare const useDndModel: (options?: DndModelOptions<DndElement, DndElement> | DndInteraction<DndElement, DndElement>[] | undefined) => vue.Raw<{
readonly classes: Readonly<Required<DndClasses>>;
readonly interactions: DndInteraction<DndElement, DndElement>[];
readonly initialized: boolean;
readonly currentSource: DndElement | undefined;
readonly currentTarget: DndElement | undefined;
isDragging: {
(): boolean;
(label: string): boolean;
<Label extends string>(label: Label, data: Extract<DndElement, {
label: Label;
}>["data"]): boolean;
(source: DndElement): boolean;
(predicate: (source: DndElement) => boolean): boolean;
};
isDraggable: {
(source: DndElement): boolean;
<Label extends string>(label: Label, data: Extract<DndElement, {
label: Label;
}>["data"]): boolean;
};
isOver: {
(): boolean;
(label: string): boolean;
<Label extends string>(label: Label, data: Extract<DndElement, {
label: Label;
}>["data"]): boolean;
(dropzone: DndElement): boolean;
(predicate: (dropzone: DndElement) => boolean): boolean;
};
isDroppable: {
(dropzone: DndElement): boolean;
<Label extends string>(label: Label, data: Extract<DndElement, {
label: Label;
}>["data"]): boolean;
};
defineInteraction: (interaction: DndInteraction<DndElement, DndElement>) => void;
findHTMLElement: {
(role: "container"): HTMLElement | undefined;
<Role extends "source" | "dropzone">(role: Role, dndEl: Role extends "source" ? DndElement : DndElement): HTMLElement | undefined;
};
findHTMLElements: {
(role: "handle"): HTMLElement[];
<Role extends "source" | "dropzone">(role: Role, label?: (Role extends "source" ? string : string) | undefined): HTMLElement[];
};
findHandlesIn: (source: DndElement | HTMLElement) => HTMLElement[];
$findDndElement: {
(role: "source", htmlEl: HTMLElement): DndElement | undefined;
(role: "dropzone", htmlEl: HTMLElement): DndElement | undefined;
};
$addNativeElement: <Role extends "container" | "source" | "dropzone" | "handle">(role: Role, htmlEl: HTMLElement, dndEl: Role extends "source" | "dropzone" ? DndElement : undefined) => void;
$removeNativeElement: (role: "container" | "source" | "dropzone" | "handle", htmlEl: HTMLElement) => void;
$setInitialized: (flag: boolean) => void;
$setCurrentTarget: (value: DndElement | undefined) => void;
$setCurrentSource: (value: DndElement | undefined) => void;
}>;
declare const injectDndModel: () => vue.Raw<{
readonly classes: Readonly<Required<DndClasses>>;
readonly interactions: DndInteraction<DndElement, DndElement>[];
readonly initialized: boolean;
readonly currentSource: DndElement | undefined;
readonly currentTarget: DndElement | undefined;
isDragging: {
(): boolean;
(label: string): boolean;
<Label extends string>(label: Label, data: Extract<DndElement, {
label: Label;
}>["data"]): boolean;
(source: DndElement): boolean;
(predicate: (source: DndElement) => boolean): boolean;
};
isDraggable: {
(source: DndElement): boolean;
<Label extends string>(label: Label, data: Extract<DndElement, {
label: Label;
}>["data"]): boolean;
};
isOver: {
(): boolean;
(label: string): boolean;
<Label extends string>(label: Label, data: Extract<DndElement, {
label: Label;
}>["data"]): boolean;
(dropzone: DndElement): boolean;
(predicate: (dropzone: DndElement) => boolean): boolean;
};
isDroppable: {
(dropzone: DndElement): boolean;
<Label extends string>(label: Label, data: Extract<DndElement, {
label: Label;
}>["data"]): boolean;
};
defineInteraction: (interaction: DndInteraction<DndElement, DndElement>) => void;
findHTMLElement: {
(role: "container"): HTMLElement | undefined;
<Role extends "source" | "dropzone">(role: Role, dndEl: Role extends "source" ? DndElement : DndElement): HTMLElement | undefined;
};
findHTMLElements: {
(role: "handle"): HTMLElement[];
<Role extends "source" | "dropzone">(role: Role, label?: (Role extends "source" ? string : string) | undefined): HTMLElement[];
};
findHandlesIn: (source: DndElement | HTMLElement) => HTMLElement[];
$findDndElement: {
(role: "source", htmlEl: HTMLElement): DndElement | undefined;
(role: "dropzone", htmlEl: HTMLElement): DndElement | undefined;
};
$addNativeElement: <Role extends "container" | "source" | "dropzone" | "handle">(role: Role, htmlEl: HTMLElement, dndEl: Role extends "source" | "dropzone" ? DndElement : undefined) => void;
$removeNativeElement: (role: "container" | "source" | "dropzone" | "handle", htmlEl: HTMLElement) => void;
$setInitialized: (flag: boolean) => void;
$setCurrentTarget: (value: DndElement | undefined) => void;
$setCurrentSource: (value: DndElement | undefined) => void;
}> | undefined;
declare const DndContainer: vue.DefineSetupFnComponent<DndContainerProps<DndElement, DndElement>>;
declare const DndSource: vue.DefineSetupFnComponent<DndSourceProps<DndElement>>;
declare const DndDropzone: vue.DefineSetupFnComponent<DndDropzoneProps<DndElement>>;
declare const DndHandle: vue.DefineSetupFnComponent<DndHandleProps, {}, {}, vue.HTMLAttributes & {
tag?: string;
} & {}, vue.PublicProps>;
export { DndContainer, DndDropzone, DndHandle, DndSource, DndSuite, injectDndModel, useDndModel };
export type { DndClasses, DndElement, DndInteraction, DndModel, DndModelOptions, IDndSuite };