| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Name | Name | Last commit date | ||
|---|---|---|---|---|
DFlex is a Javascript library for modern Drag and Drop apps. It's built with vanilla Javascript and implemented an enhanced transformation mechanism to manipulate DOM elements. It is by far the only Drag and Drop library on the internet that manipulates the DOM instead of reconstructing it and has its own scheduler and reconciler.
The original input order which appears when inspecting elements stays the
same. While the visual order happens after transformation and it's supported by the
data-index attribute to know the order of elements in the visual list.

To enable handling a large set of elements, the transformation is related
to the viewport. No matter how many elements are affected, DFlex only
transforms elements visible on the screen. Elements outside the viewport are
triggered to a new position when they are visible.

npm install @dflex/dndDFlex DnD depends on three principles to achieve DOM interactivity:
import { store, DnD } from "@dflex/dnd";Each element should be registered in DFlex DnD Store in order to be active for drag and drop later.
store.register(RegisterInputOpts): void;Where RegisterInputOpts is an object with the following properties:
The responsive drag and drop session should be created when onmousedown is fired. So it can initialize the element and its siblings before start dragging.
const dflexDnD = new DnD(id, coordinate, opts);dflexDnD.dragAt(x, y);dflexDnD.endDragging();It's necessary to cleanup the element from store when the element won't be used or will be removed/unmounted from the DOM to prevent any potential memory leaks.
store.unregister(id: string): voidYou can pass options when creating a DnD instance that controls each element individually. So your options can be different from each other.
The threshold object defines when the dragging event should be fired and triggers the response of other sibling elements.
interface ThresholdPercentages {
/** vertical threshold in percentage from 0-100 */
vertical: number;
/** horizontal threshold in percentage from 0-100 */
horizontal: number;
}interface DFlexDnDOpts {
// ... other options.
threshold?: Partial<ThresholdPercentages>;
}{
"threshold": {
"vertical": 60,
"horizontal": 60
}
}DFlex is built to manipulate DOM elements with transformation indefinitely. This means you can always drag and drop elements without reconstruction of the DOM. Still, it comes with a reconciler that tracks elements' changes and only reconciles the elements that have changed their position from their origin.
interface CommitInterface {
enableAfterEndingDrag: boolean;
enableForScrollOnly: boolean;
}interface DFlexDnDOpts {
// ... other options.
commit?: Partial<CommitInterface>;
}{
"commit": {
"enableAfterEndingDrag": true,
"enableForScrollOnly": true
}
}You can define the dragging restrictions for each element relative:
interface Restrictions {
self: {
allowLeavingFromTop: boolean;
allowLeavingFromBottom: boolean;
allowLeavingFromLeft: boolean;
allowLeavingFromRight: boolean;
};
container: {
allowLeavingFromTop: boolean;
allowLeavingFromBottom: boolean;
allowLeavingFromLeft: boolean;
allowLeavingFromRight: boolean;
};
}interface DFlexDnDOpts {
// ... other options.
restrictions?: {
self?: Partial<Restrictions["self"]>;
container?: Partial<Restrictions["container"]>;
};
}{
"restrictions": {
"self": {
"allowLeavingFromTop": true,
"allowLeavingFromBottom": true,
"allowLeavingFromLeft": true,
"allowLeavingFromRight": true
},
"container": {
"allowLeavingFromTop": true,
"allowLeavingFromBottom": true,
"allowLeavingFromLeft": true,
"allowLeavingFromRight": true
}
}
}interface ScrollOptions {
enable?: boolean;
initialSpeed?: number;
threshold?: Partial<ThresholdPercentages>;
}interface DFlexDnDOpts {
// ... other options.
scroll?: Partial<ScrollOptions>;
}{
"scroll": {
"enable": true,
"initialSpeed": 10,
"threshold": {
"vertical": 15,
"horizontal": 15
}
}
}DFlex has three (3) types of custom events.
// DFlex event handler.
const onDFlexEvent = (e: DFlexEvents) => {
// Do something.
console.log(`onDFlexEvent: ${e.type}`, e.detail);
};
// Dragged Events.
const ON_OUT_CONTAINER = "$onDragOutContainer";
const ON_OUT_THRESHOLD = "$onDragOutThreshold";
// Interactivity Events.
const ON_DRAG_OVER = "$onDragOver";
const ON_DRAG_LEAVE = "$onDragLeave";
// Sibling Events.
const ON_LIFT_UP = "$onLiftUpSiblings";
const ON_MOVE_DOWN = "$onMoveDownSiblings";
// Capture DFlex event.
document.addEventListener(
ON_OUT_CONTAINER /** or another event */,
onDFlexEvent
);
// Remove it later when dragging is done.
document.removeEventListener(
ON_OUT_CONTAINER /** or another event */,
onDFlexEvent
);It's an event related to capturing dragged positions. This event is fired when the dragged is out of its threshold position $onDragOutContainer or out of its container $onDragOutThreshold.
interface PayloadDraggedEvent {
/** Returns element id in the registry */
id: string;
/** Returns dragged temp index */
index: number;
}
/** For dragged out of threshold or container event. */
type DFlexDraggedEvent = CustomEvent<PayloadDraggedEvent>;It's an event related to capturing dragged interactions with other elements. This event is fired when the dragged is over another element $onDragOver or when the dragged is leaving the occupied position $onDragLeave.
interface PayloadInteractivityEvent {
/** Returns element id in the registry */
id: string;
/** Returns element current index */
index: number;
/** Returns the element that triggered the event */
target: HTMLElement;
}
/** For dragged over an element or leaving an element. */
type DFlexInteractivityEvent = CustomEvent<PayloadInteractivityEvent>;It's an event related to capturing siblings' positions. This event is fired when the siblings are lifting up $onLiftUpSiblings or moving down $onMoveDownSiblings
interface PayloadSiblingsEvent {
/** Returns the index where the dragged left */
from: number;
/** Returns the last index effected of the dragged leaving/entering */
to: number;
/** Returns an array of sibling ids in order */
siblings: string[];
}
/** When dragged movement triggers the siblings up/down. */
type DFlexSiblingsEvent = CustomEvent<PayloadSiblingsEvent>;DFlex listeners are more generic than the custom events and responsible for monitoring the entire layout and reporting back to you.
DFlex has two (2) types of listeners:
// app/index.js
const unsubscribeLayout = store.listeners.subscribe((e) => {
console.info("new layout state", e);
}, "layoutState");
// call it later for clear listeners from memory.
unsubscribeLayout();
const unsubscribeMutation = store.listeners.subscribe((e) => {
console.info("new mutation state", e);
}, "mutation");
// call it later for clear listeners from memory.
unsubscribeMutation();Responsible for monitoring any change that happens to layout interactivity.
type LayoutState =
| "pending" // when DnD is initiated but not activated yet.
| "ready" // When clicking over the registered element. The element is ready but not being dragged.
| "dragging" // as expected.
| "dragEnd" // as expected.
| "dragCancel"; // When releasing the drag without settling in the new position.
interface DFlexLayoutStateEvent {
type: "layoutState";
status: LayoutState;
}Responsible for monitoring DOM mutation that happens during reconciliation.
type ElmMutationType = "committed";
interface DFlexElmMutationEvent {
type: "mutation";
status: ElmMutationType;
payload: {
target: HTMLElement; // HTML element container.
ids: string[]; // Committed Elements' id in order.
};
}DFlex elements are serialized and exported accordingly.
store.getSerializedElm(elmID: string): DFlexSerializedElement | null
type DFlexSerializedElement = {
type: string;
version: number;
id: string;
translate: PointNum | null;
grid: PointNum;
order: DFlexDOMGenOrder;
initialPosition: AxesPoint;
rect: BoxRectAbstract;
hasTransformedFromOrigin: boolean;
hasPendingTransformation: boolean;
isVisible: boolean;
};DFlex scroll containers are serialized and exported accordingly. You can get any scroll container for any registered element id.
store.getSerializedScrollContainer(elmID: string): DFlexSerializedScroll | null
type DFlexSerializedScroll = {
type: string;
version: number;
key: string;
hasOverFlow: AxesPoint<boolean>;
hasDocumentAsContainer: boolean;
scrollRect: AbstractBox;
scrollContainerRect: AbstractBox;
invisibleDistance: AbstractBox;
visibleScreen: Dimensions;
};Commit changes to the DOM. commit will always do surgical reconciliation. and it's the same function that's used in the options
store.commit(): voidTrue when DFlex is not transforming any elements and not executing any task.
isLayoutAvailable(): booleansafely removing element from store.
store.unregister(id: string): voidTo destroy all DFlex instances. This is what you should do when you are done with DnD completely and your app is about to be closed.
store.destroy(): void;DFlex DOM relations generator algorithm. It Generates relations between DOM elements based on element depth so all the registered DOM can be called inside registry without the need to call browser API. Read once, implement everywhere.
Core instance is the mirror of interactive element that includes all the properties and methods to manipulate the node.
A collection of shared functions. Mostly classes, and types that are used across the project.
DFex Store has main registry for all DOM elements that will be manipulated. It is a singleton object that is accessible from anywhere in the application. The initial release was generic but it only has the Core of the library since ^V3.
Light weight draggable element without extra functionalities that is responsible for interacting with the DOM and moving the affected element(s).
The main package that depends on the other packages. It is responsible for the magical logic of the library to introduce the drag and drop interactive functionality.
For documentation, more information about DFlex and a live demo, be sure to visit the DFlex website https://www.dflex.dev/
PRs are welcome, If you wish to help, you can learn more about how you can contribute to this project in the Contributing guide.
DFlex is a work-in-progress project and currently in development.
DFlex is MIT License.
Jalal Maskoun (@jalal246)
| Back | FazBrowse Home | New Git URL |