neodrag

repository·main·Indexed 25 days ago

https://github.com/puruvj/neodrag

A 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.

Tokens
17.5K
Snippets
71
Records
114
Agent score
79%

What's inside neodrag

  1. Overview of Neodrag multi-framework packages

    main
    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.
  2. Implement Controlled vs Uncontrolled dragging

    main

    Uncontrolled (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 position object: { x: number, y: number }.

    Note: When you change position, the element moves, but user interaction does not automatically update your position state 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 disabled option to true.

    // Strictly controlled example
    useDraggable(draggableRef, {
      position: { x: 0, y: 10 },
      disabled: true,
    });
  3. Understand Controlled vs Uncontrolled dragging in @neodrag/solid

    main

    Neodrag follows a philosophy inspired by react-draggable regarding 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 position property (e.g., { x: 10, y: 50 }).

    Important Note on Two-Way Binding: Neodrag is not fully controlled. When you change the position via state, the element moves. However, when a user drags the element, the internal state changes but your position state variable does not automatically update. To keep your state in sync, you must use the onDrag event to update your state variable with the new coordinates.

    Strictly Controlled

    To prevent user interaction and allow only programmatic movement, set the disabled option to true:

    <div use:draggable={{ position: { x: 0, y: 10 }, disabled: true }} />
  4. Understand the Astro project structure

    main

    The project follows a standard Astro directory structure:

    • src/pages/: Contains .astro or .md files. 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.
  5. Understand Controlled vs Uncontrolled dragging

    main

    Neodrag follows a philosophy inspired by react-draggable regarding 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 position variable will not automatically update. To keep your state in sync, you must use the onDrag event 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 disabled option to true.

  6. Controlled vs Uncontrolled dragging

    main

    Neodrag 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 position property (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 internal position property is not automatically updated. To keep your application state in sync with the user's manual dragging, you must use the onDrag event to update your state.

    Strictly Controlled

    To prevent user interaction and allow only programmatic movement, set the disabled option to true.

    new Draggable({ position: { x: 0, y: 10 }, disabled: true });
    new Draggable({ position: { x: 0, y: 10 }, disabled: true });
  7. Understand Uncontrolled vs Controlled dragging

    main

    @neodrag/svelte supports 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:neodrag event.

    Controlled

    You can programmatically set the element's position using the position property (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 position variable will not automatically update. To keep your state in sync, you must use the on:neodrag event to update your state variable.

    Strictly Controlled

    To prevent user interaction and only allow programmatic movement, set disabled: true in the options:

    <div use:draggable={{ position: { x: 0, y: 10 }, disabled: true }} />
  8. Install dependencies for the Solid demo

    main

    To set up the Solid demo project, install the dependencies using your preferred package manager. While the template includes a pnpm-lock.yaml (maintained via pnpm up -Lri), you can use npm, pnpm, or yarn to install.

    $ npm install # or pnpm install or yarn install
  9. Configure draggable options and reactive updates

    main

    You can pass configuration options to the use:draggable directive. 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>;