DnD

Drag & Drop

@w1c/dnd contains the pointer math used by draggable and resizable W1C windows. It has no framework dependencies and does not store geometry for you.

import {
	createDragSession,
	createResizeSession,
	moveDrag,
	moveResize,
	startPointerSession,
	endPointerSession
} from '@w1c/dnd';

Geometry

Use the pure helpers when you already have pointer coordinates. They do not touch the DOM.

const drag = createDragSession(1, { x: 20, y: 30 }, { x: 100, y: 120 });

moveDrag(drag, { x: 40, y: 15 });
// { x: 120, y: 105 }

Resize helpers apply optional minimum and maximum constraints.

const resize = createResizeSession(1, { x: 0, y: 0 }, { width: 320, height: 220 });

moveResize(resize, { x: -80, y: 120 }, { minWidth: 300, minHeight: 180, maxHeight: 260 });
// { width: 300, height: 260 }

Pointer Sessions

The DOM helpers cover the repeated pointer-event work:

  • start only from the primary button and primary pointer
  • capture the active pointer on the handle element
  • match move and end events by pointerId
  • release capture on pointer up or pointer cancel
let session = null;

function onPointerDown(event: PointerEvent) {
	const result = startPointerSession(event);
	if (!result) return;

	session = result.session;
}

function onPointerUp(event: PointerEvent) {
	if (endPointerSession(session, event)) {
		session = null;
	}
}

Window Integration

w1c-window uses @w1c/dnd internally when you opt into movement or resizing.

<w1c-window title="Mailbox" movable resizable x="24" y="16" width="380" height="260" min-width="300" min-height="220">
	<p>Drag the titlebar. Resize from the bottom-right handle.</p>
</w1c-window>

w1c-window reflects moving and resizing while a session is active, so themes and app code can set cursors, user-select: none, or visual state classes. It emits move and resize events with { x, y, width, height } in detail.

Persistence, z-index, focus, and maximized state stay in application code. The DnD package only handles pointer sessions and geometry.

Example

This was adapted from the Ibex codebase.

You can see it in action right here.