Skip to content
Snippets Groups Projects
Commit 3cdcaaab authored by Loïc Correnson's avatar Loïc Correnson
Browse files

[dome] more dnd documentation

parent f7b62755
No related branches found
No related tags found
No related merge requests found
...@@ -55,8 +55,7 @@ export interface Dragging { ...@@ -55,8 +55,7 @@ export interface Dragging {
Drop over information: Drop over information:
- `meta` indicates if a modifier key is pressed; - `meta` indicates if a modifier key is pressed;
- `rect` is the original DOM Rectangle of the hovered HTML node; - `rect` is the original DOM Rectangle of the hovered HTML node;
- `dropX,dropY` is the position in `rect` where the drag hovers in; - `dropX,dropY` is the position inside `rect` where the drag hovers in;
*/ */
export interface Dropping { export interface Dropping {
meta: boolean; meta: boolean;
...@@ -66,7 +65,6 @@ export interface Dropping { ...@@ -66,7 +65,6 @@ export interface Dropping {
} }
/** Drag Callbacks. */ /** Drag Callbacks. */
export interface DragHandler { export interface DragHandler {
/** Callback when drag is initiated. */ /** Callback when drag is initiated. */
onStart?: () => void; onStart?: () => void;
...@@ -77,10 +75,12 @@ export interface DragHandler { ...@@ -77,10 +75,12 @@ export interface DragHandler {
} }
/** Drop Callbacks. */ /** Drop Callbacks. */
export interface DropHandler { export interface DropHandler {
/** Callback when the drag source enters the drop target. */
onDropIn?: (d: Dropping) => void; onDropIn?: (d: Dropping) => void;
/** Callback when the drag source leaves the drop target. */
onDropOut?: () => void; onDropOut?: () => void;
/** Callback when the drag source is dropped in the target. */
onDrop?: () => void; onDrop?: () => void;
} }
...@@ -189,6 +189,7 @@ export class DnD { ...@@ -189,6 +189,7 @@ export class DnD {
} }
} }
/** React Hook for creating a local DnD controller. */
export function useDnD(): DnD { export function useDnD(): DnD {
return React.useMemo(() => new DnD(), []); return React.useMemo(() => new DnD(), []);
} }
...@@ -197,6 +198,21 @@ export function useDnD(): DnD { ...@@ -197,6 +198,21 @@ export function useDnD(): DnD {
/* --- Drop Targets --- */ /* --- Drop Targets --- */
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
/** React Hook for connecting a drop target to a DnD controller and drop event
callbacks.
Usage: the hook returns a Rect reference `r` that you shall pass to the HTML
`<div ref={r}/>` element of your drop target. Once this element is mounted
into the DOM, the DnD controller and your handler will start receiving drag
and drop events.
Undefined DnD controller and handlers switch off Drag & Drop events from the
drop target.
Alternatively, you can also use `<DropTarget/>` and `<DragSource/>`
components that already offers such a `<div/>` element connected to a DnD
controller.
*/
export function useDropTarget( export function useDropTarget(
dnd: DnD | undefined, handlers?: DropHandler dnd: DnD | undefined, handlers?: DropHandler
): React.RefObject<HTMLDivElement> { ): React.RefObject<HTMLDivElement> {
...@@ -228,13 +244,12 @@ export interface DropTargetProps extends DropHandler { ...@@ -228,13 +244,12 @@ export interface DropTargetProps extends DropHandler {
children?: React.ReactNode; children?: React.ReactNode;
} }
/** /** A container `<div/>` element that can be dropped in when dragging some
This container can be dropped in when dragging DragSource DragSource connected to the specified DnD controller.
of the specified DnD controller.
Remark: a `<DragSource/>` also behaves as a `<DropTarget/>` See also `<DragSource/>` component that can also behaves as a Drop target.
when it has Drop handler callbacks. If you need a more precise control over the underlying `<div/>` element,
*/ refer to the `useDropTarget()` React Hook. */
export function DropTarget(props: DropTargetProps): JSX.Element { export function DropTarget(props: DropTargetProps): JSX.Element {
const { dnd, disabled = false, className, style, children } = props; const { dnd, disabled = false, className, style, children } = props;
const nodeRef = useDropTarget(dnd, disabled ? undefined : props); const nodeRef = useDropTarget(dnd, disabled ? undefined : props);
...@@ -288,9 +303,9 @@ function RenderOverlay( ...@@ -288,9 +303,9 @@ function RenderOverlay(
return { outerClass: className, outerStyle: style }; return { outerClass: className, outerStyle: style };
} }
/** /** Can be used to dynamically render an element with respect to current
Can be used to conditionally render an element wrt to dragging informations. dragging state. The parameter `d` is `undefined` when there is no current
*/ dragging action. Otherwize, `d` contains the relevant dragging data. */
export type DraggingRenderer = (d: Dragging | undefined) => JSX.Element; export type DraggingRenderer = (d: Dragging | undefined) => JSX.Element;
export interface DragSourceProps extends DragHandler, DropHandler { export interface DragSourceProps extends DragHandler, DropHandler {
...@@ -324,15 +339,15 @@ export interface DragSourceProps extends DragHandler, DropHandler { ...@@ -324,15 +339,15 @@ export interface DragSourceProps extends DragHandler, DropHandler {
children?: React.ReactNode | DraggingRenderer; children?: React.ReactNode | DraggingRenderer;
} }
/** /** This container can be dragged around all over the application window. Its
This container can be dragged around all over the application window. Its
content is rendered inside a double `<div/>`, the outer one being fixed when content is rendered inside a double `<div/>`, the outer one being fixed when
dragged, and the inner one being moved around when dragging. dragged, and the inner one being moved around when dragging.
The content can be rendered conditionnaly by using a function. The content of the inner most `<div/>` can be rendered dynamically by using a
function of type `DraggingRenderer`.
When a Drag Source has Drop Handler callbacks, the element is also When a Drag Source has Drop Handler callbacks, the element is also registered
registered as a Drop Target into the DnD controller. as a Drop Target into the DnD controller.
*/ */
export function DragSource(props: DragSourceProps): JSX.Element { export function DragSource(props: DragSourceProps): JSX.Element {
//--- Props //--- Props
...@@ -431,6 +446,7 @@ interface ListContext { ...@@ -431,6 +446,7 @@ interface ListContext {
onStop?: () => void; onStop?: () => void;
} }
// Propagates the englobing List container callbacks down to ListItem elements
const CurrentList = React.createContext<ListContext>({}); const CurrentList = React.createContext<ListContext>({});
function getItem(ordered: string[] | undefined, id: string): number { function getItem(ordered: string[] | undefined, id: string): number {
...@@ -439,14 +455,17 @@ function getItem(ordered: string[] | undefined, id: string): number { ...@@ -439,14 +455,17 @@ function getItem(ordered: string[] | undefined, id: string): number {
return 0 <= k ? k : ordered.push(id); return 0 <= k ? k : ordered.push(id);
} }
/** List Item properties. */
export interface ItemProps { export interface ItemProps {
id: string; id: string; /** Shall be unique inside the same `<List/>` container. */
className?: string; className?: string; /** Additional class for the List Item contents. */
style?: React.CSSProperties; style?: React.CSSProperties; /** Additional style for the List Item contents. */
children?: React.ReactNode; children?: React.ReactNode; /** List Item contents. */
} }
/** List item component. Shall only be used inside a `<List/>` component. */ /** List item component. Shall only be used inside a `<List/>` component. The
item contents is rendered inside a `<DragSource/>` component automatically
connected to the englobing `<List/>` DnD controller. */
export function Item(props: ItemProps): JSX.Element { export function Item(props: ItemProps): JSX.Element {
//--- Ordering //--- Ordering
const { dnd, items, setSource, setTarget, onStop } = const { dnd, items, setSource, setTarget, onStop } =
...@@ -498,9 +517,9 @@ export interface ListProps { ...@@ -498,9 +517,9 @@ export interface ListProps {
The behavior of the component can be _controlled_ or _uncontrolled_ whether The behavior of the component can be _controlled_ or _uncontrolled_ whether
`items` and `setItems` properties are set or not. In controlled mode, the `items` and `setItems` properties are set or not. In controlled mode, the
`items` property is not mandatory to contains all the list elements, in which `items` property is not required to contains all the list elements, in which
case the missing elements would be added to the end. Notice that `setItems` case the missing elements would be added to the end. Notice that `setItems`
callback is only notified after drag & drop. callback is only notified after a complete drag & drop sequence of events.
*/ */
export function List(props: ListProps): JSX.Element { export function List(props: ListProps): JSX.Element {
const dnd = useDnD(); const dnd = useDnD();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment