neodrag
repository·main·Indexed 25 days ago
https://github.com/puruvj/neodragA multi-framework dragging library providing a consistent API across React, Vue, Svelte, Solid, and Vanilla JavaScript. It includes specialized packages (@neodrag/react, @neodrag/vue, @neodrag/svelte, @neodrag/solid, @neodrag/vanilla) that support features such as axis restriction, grid snapping, and bounding constraints via DragOptions.
What's inside neodrag
- Neodrag is a multi-framework library for implementing drag-and-drop functionality. It is designed so that the dragging API behavior remains consistent regardless of the framework you choose. The project is organized as a monorepo with dedicated packages for different environments.
Implement Controlled vs Uncontrolled dragging
mainUncontrolled (Default)
In uncontrolled mode, the user drags the element and it changes position. You can use the drag events to sync the library's internal state with your own application state.
Controlled
You can programmatically move an element by providing a
positionobject:{ x: number, y: number }.Note: When you change
position, the element moves, but user interaction does not automatically update yourpositionstate variable. To keep your state in sync, you must use the drag event handlers to update your state.Strictly Controlled
To prevent user interaction from moving the element and allow only programmatic movement, set the
disabledoption totrue.// Strictly controlled example useDraggable(draggableRef, { position: { x: 0, y: 10 }, disabled: true, });Understand Controlled vs Uncontrolled dragging in @neodrag/solid
mainNeodrag follows a philosophy inspired by
react-draggableregarding controlled and uncontrolled components.Uncontrolled (Default)
Your application does not manage the position. The user drags the element, it moves, and you can react to the movement via events. You do not manually set the position.
Controlled
You programmatically set the position using the
positionproperty (e.g.,{ x: 10, y: 50 }).Important Note on Two-Way Binding: Neodrag is not fully controlled. When you change the
positionvia state, the element moves. However, when a user drags the element, the internal state changes but yourpositionstate variable does not automatically update. To keep your state in sync, you must use theonDragevent to update your state variable with the new coordinates.Strictly Controlled
To prevent user interaction and allow only programmatic movement, set the
disabledoption totrue:<div use:draggable={{ position: { x: 0, y: 10 }, disabled: true }} />Understand the Astro project structure
mainThe project follows a standard Astro directory structure:
src/pages/: Contains.astroor.mdfiles. Each file in this directory is automatically exposed as a route based on its filename.src/components/: A recommended location for storing Astro, React, Vue, Svelte, or Preact components.src/layouts/: Typically used for defining page layouts.public/: Stores static assets like images and favicons that are served directly.package.json: Defines project dependencies and scripts.
Understand Controlled vs Uncontrolled dragging
mainNeodrag follows a philosophy inspired by
react-draggableregarding state control:- Uncontrolled (Default): The user drags the element, and it changes position internally. Your application reacts to these changes via events, but you do not manage the position state yourself.
- Controlled: You manage the element's position using a state variable (e.g.,
position: { x: 10, y: 50 }).
Important Note on Controlled Mode: The library does not support full two-way data binding. When a user drags an element, the internal position changes, but your external
positionvariable will not automatically update. To keep your state in sync, you must use theonDragevent to update your state variable with the new coordinates.To make an element strictly controlled (preventing user interaction and only allowing programmatic movement), set the
disabledoption totrue.Controlled vs Uncontrolled dragging
mainNeodrag supports two modes of interaction:
Uncontrolled (Default)
The user drags the element, and the element changes position. Your application reacts to these changes (e.g., via
onDrag) but does not dictate the position.Controlled
You programmatically set the element's position using the
positionproperty (e.g.,{ x: 10, y: 50 }).Important Note on Two-Way Binding: When you change
position, the element moves. However, when a user drags the element, the internalpositionproperty is not automatically updated. To keep your application state in sync with the user's manual dragging, you must use theonDragevent to update your state.Strictly Controlled
To prevent user interaction and allow only programmatic movement, set the
disabledoption totrue.new Draggable({ position: { x: 0, y: 10 }, disabled: true });new Draggable({ position: { x: 0, y: 10 }, disabled: true });Understand Uncontrolled vs Controlled dragging
main@neodrag/sveltesupports two modes of interaction:Uncontrolled (Default)
The element's position is managed internally by the library. The user drags the element, and you can react to the movement using the
on:neodragevent.Controlled
You can programmatically set the element's position using the
positionproperty (e.g.,{ x: 10, y: 50 }).Important: The library is not fully controlled. When a user drags the element, the internal state changes, but your
positionvariable will not automatically update. To keep your state in sync, you must use theon:neodragevent to update your state variable.Strictly Controlled
To prevent user interaction and only allow programmatic movement, set
disabled: truein the options:<div use:draggable={{ position: { x: 0, y: 10 }, disabled: true }} />Install dependencies for the Solid demo
mainTo set up the Solid demo project, install the dependencies using your preferred package manager. While the template includes a
pnpm-lock.yaml(maintained viapnpm up -Lri), you can usenpm,pnpm, oryarnto install.$ npm install # or pnpm install or yarn installRun the Solid demo in development mode
mainTo start the application in development mode, runnpm devornpm start. The application will be available at http://localhost:3000 and will automatically reload when you make changes to the code.Install @neodrag/react
mainYou can install the
@neodrag/reactpackage using your preferred package manager.# npm npm install @neodrag/react # yarn yarn add @neodrag/react # pnpm pnpm add @neodrag/reactConfigure draggable options and reactive updates
mainYou can pass configuration options to the
use:draggabledirective. These options can be defined inline or as a separate object. Because it is integrated with SolidJS, you can pass a reactive signal to the directive, and Neodrag will automatically update when the signal changes.Inline options:
<div use:draggable={{ axis: 'x', grid: [10, 10] }}>I am draggable</div>;Using TypeScript types:
import { createDraggable, type DragOptions } from '@neodrag/solid'; const options: DragOptions = { axis: 'y', bounds: 'parent', }; const { draggable } = createDraggable(); <div use:draggable={options}>I am draggable</div>;Reactive options with signals:
import { createSignal } from 'solid-js'; import { createDraggable } from '@neodrag/solid'; const [options, setOptions] = createSignal({ axis: 'y', bounds: 'parent', }); <div use:draggable={options()}>I am draggable</div>; // Updating `setOptions` will automatically update the draggable behavior.import { createSignal } from 'solid-js'; import { createDraggable } from '@neodrag/solid'; const [options, setOptions] = createSignal({ axis: 'y', bounds: 'parent', }); <div use:draggable={options()}>I am draggable</div>;Migrating from svelte-drag to @neodrag/svelte
mainIf you are upgrading from the predecessor packagesvelte-drag, follow the official migration guide at https://www.neodrag.dev/docs/migrating/svelte-drag to ensure a smooth transition.