@neodrag/vanilla

@neodrag/vanilla

A lightweight library to make your elements draggable.

npm i @neodrag/vanilla@next

Usage

Basic usage

import { Draggable } from '@neodrag/vanilla';

const dragInstance = new Draggable(document.querySelector('#drag'));

With plugins

import { Draggable, axis, grid } from '@neodrag/vanilla';

const dragInstance = new Draggable(document.querySelector('#drag'), [
  axis('x'),
  grid([10, 10]),
]);

Defining plugins elsewhere with TypeScript

import {
  Draggable,
  axis,
  bounds,
  BoundsFrom,
  type Plugin,
} from '@neodrag/vanilla';

const plugins: Plugin[] = [axis('y'), bounds(BoundsFrom.parent())];

const dragInstance = new Draggable(
  document.querySelector('#drag'),
  plugins,
);

Reactive Plugins with Compartments

Update plugins dynamically using compartments:

import { Draggable, axis, grid, Compartment } from '@neodrag/vanilla';

const axisCompartment = new Compartment(() => axis('x'));
const dragInstance = new Draggable(
  document.querySelector('#drag'),
  () => [axisCompartment, grid([10, 10])],
);

// Update the axisCompartment. Automatically applies to the drag instance
axisCompartment.current = axis('y');

Multiple reactive compartments

import {
  Draggable,
  axis,
  bounds,
  BoundsFrom,
  grid,
  Compartment,
} from '@neodrag/vanilla';

let currentAxis = 'x';
let gridSize = 20;
let enableBounds = false;

const axisComp = new Compartment(() => axis(currentAxis));
const gridComp = new Compartment(() => grid([gridSize, gridSize]));
const boundsComp = new Compartment(() =>
  enableBounds ? bounds(BoundsFrom.parent()) : null,
);

const dragInstance = new Draggable(
  document.querySelector('#drag'),
  () => [axisComp, gridComp, boundsComp],
);

// Update functions
function updateAxis(newAxis) {
  currentAxis = newAxis;
  axisComp.current = axis(currentAxis);
}

function updateGridSize(newSize) {
  gridSize = newSize;
  gridComp.current = grid([gridSize, gridSize]);
}

function toggleBounds() {
  enableBounds = !enableBounds;
  boundsComp.current = enableBounds
    ? bounds(BoundsFrom.parent())
    : null;
}

Event Handling

import { Draggable, events } from '@neodrag/vanilla';

const dragInstance = new Draggable(document.querySelector('#drag'), [
  events({
    onDragStart: (data) => console.log('Started:', data.offset),
    onDrag: (data) => console.log('Dragging:', data.offset),
    onDragEnd: (data) => console.log('Ended:', data.offset),
  }),
]);

Drag Controls

import { Draggable, controls, ControlFrom } from '@neodrag/vanilla';

const dragInstance = new Draggable(document.querySelector('#drag'), [
  controls({
    allow: ControlFrom.selector('.drag-handle'),
    block: ControlFrom.selector('.no-drag'),
  }),
]);

Cleanup

// Clean up when done
dragInstance.destroy();

Using via CDN

For users who prefer not to install the package and instead use it directly in their projects via a CDN, you can include @neodrag/vanilla directly in your HTML files. This is particularly useful for quick prototyping or projects where you want to avoid a build step.

Using Unpkg

Include the library in your HTML using the following <script> tag. This will load the latest version of @neodrag/vanilla directly from unpkg:

<script src="https://unpkg.com/@neodrag/vanilla@next/dist/umd/index.js"></script>

Using jsDelivr

Alternatively, you can use jsDelivr as a CDN to load @neodrag/vanilla. Include the following line in your HTML:

<script src="https://cdn.jsdelivr.net/npm/@neodrag/vanilla@next/dist/umd/index.js"></script>

Usage with CDN

After including the library via a CDN, @neodrag/vanilla will be available as a global variable NeoDrag. Here’s how you can use it to make an element draggable:

<div id="drag">Drag me!</div>
<script>
  var dragInstance = new NeoDrag.Draggable(
    document.getElementById('drag'),
  );
</script>

CDN with Plugins

<div id="constrained-drag">Constrained dragging</div>
<script>
  var constrainedInstance = new NeoDrag.Draggable(
    document.getElementById('constrained-drag'),
    [
      NeoDrag.axis('x'),
      NeoDrag.bounds(NeoDrag.BoundsFrom.parent()),
      NeoDrag.grid([20, 20]),
    ],
  );
</script>

CDN with Compartments

<div id="reactive-drag">Reactive dragging</div>
<button onclick="switchAxis()">Switch Axis</button>

<script>
  var currentAxis = 'x';
  var axisCompartment = new NeoDrag.Compartment(() =>
    NeoDrag.axis(currentAxis),
  );

  var reactiveInstance = new NeoDrag.Draggable(
    document.getElementById('reactive-drag'),
    () => [axisCompartment],
  );

  function switchAxis() {
    currentAxis = currentAxis === 'x' ? 'y' : 'x';
    axisCompartment.current = NeoDrag.axis(currentAxis);
  }
</script>

This method allows you to use @neodrag/vanilla without any build tools or npm installations, directly in your browser.