Skip to main content

reflex-pragmatic-drag-and-drop

Reflex bindings for Atlassian's Pragmatic drag and drop. Build sortable lists and Kanban boards in pure Python, without writing JavaScript.

Wraps the full suite: @atlaskit/pragmatic-drag-and-drop (core), -hitbox (closest edge), -auto-scroll, and -react-drop-indicator.

Status

Functional core (Phases 1–3 of the plan) with a test suite. See specs/ for the complete design (PRD, API, Tech Design, Data Model, Plan).

Requirements

  • Python ≥ 3.12 · Reflex ≥ 0.9 · uv package manager

Pinned versions: core ^4.0.0, hitbox ^3.0.0, auto-scroll ^3.2.1, react-drop-indicator ^4.2.4.

Installation

Add the published package to your Reflex project:

uv add reflex-pragmatic-drag-and-drop      # or: pip install reflex-pragmatic-drag-and-drop

The pinned @atlaskit/* npm packages and the bundled React glue are installed by Reflex into .web on the next reflex run — no manual JavaScript setup.

Running the Kanban demo (from a clone)

uv sync                 # installs Python dependencies
uv run reflex run       # installs @atlaskit packages in .web and starts on :3000

Open http://localhost:3000 and drag the cards by their grip handle within and between columns. The demo toggles the Atlaskit drop indicator line and switches the auto-scroll speed of the column lists (standard / fast).

After upgrading the @atlaskit/* pins, delete the local .web/ directory so Reflex reinstalls the frontend from reflex.lock/ (a stale .web/package.json makes the frozen-lockfile install fail with "lockfile is out of sync").

Usage

import reflex as rx
import reflex_pragmatic_dnd as dnd


class State(rx.State):
    msg: str = ""

    @rx.event
    def on_drop(self, payload: dict):
        self.msg = f"{payload['source']} -> {payload.get('target')}"


def index():
    return rx.box(
        # Global listener: a single handler for the whole page.
        dnd.monitor(on_drop=State.on_drop),

        # A draggable element that carries data.
        dnd.draggable(
            rx.text("Drag me"),
            drag_id="card-1",
            item_data={"cardId": "card-1"},
        ),

        # A drop target with edge detection (for reordering).
        dnd.drop_target(
            rx.text("Drop it here"),
            drop_id="zone-1",
            target_data={"kind": "zone"},
            with_closest_edge=True,
            allowed_edges=["top", "bottom"],
        ),

        rx.text(State.msg),
    )

Components

Factory Wraps Events
dnd.draggable(...) draggable (element adapter) on_drag_start, on_drop
dnd.drop_target(...) dropTargetForElements (+ hitbox) on_drag_enter, on_drag_leave, on_drop
dnd.monitor(...) monitorForElements on_drag_start, on_drop
dnd.scroll_container(...) autoScrollForElements —

Built-in drop indicator and auto-scroll configuration:

dnd.drop_target(
    card,
    drop_id="c1",
    with_closest_edge=True,
    show_drop_indicator=True,   # Atlaskit <DropIndicator> on the closest edge
    drop_indicator_gap="8px",   # spacing between siblings; line sits halfway
)

dnd.scroll_container(
    cards,
    max_scroll_speed="fast",    # "standard" (default) | "fast"
    allowed_axis="vertical",    # "all" (default) | "vertical" | "horizontal"
    max_height="300px",
    overflow_y="auto",
)

Full details on props and payloads: specs/api/component-api-v1.md.

State reducers (optional)

The library includes two pure functions that transform the payload of monitor(on_drop=...) into the new state, implementing the rules of specs/data-model/event-payloads.md §4. They do not mutate their inputs and return the original object unchanged on a no-op (dropping outside, onto itself, or onto an unknown column):

@rx.event
def handle_drop(self, payload: dict):
    self.cards = dnd.move_card(self.cards, payload, columns=["todo", "doing", "done"])

@rx.event
def reorder(self, payload: dict):
    self.items = dnd.reorder_list(self.items, payload)

Visual states (CSS)

drop_target exposes attributes on the DOM for styling during the drag, and draggable marks the element in progress:

Attribute Value Component
data-dragging true/false draggable
data-over true/false drop_target
data-closest-edge top/bottom/left/right/"" drop_target (with with_closest_edge)
data-drop-id the drop_id drop_target
dnd.drop_target(
    rx.text("Drop it here"),
    drop_id="zone-1",
    with_closest_edge=True,
    # Highlight the target and draw a line on the closest edge.
    style={
        "&[data-over='true']": {"background": "var(--accent-3)"},
        "&[data-closest-edge='top']": {"box_shadow": "inset 0 2px 0 var(--accent-9)"},
        "&[data-closest-edge='bottom']": {"box_shadow": "inset 0 -2px 0 var(--accent-9)"},
    },
)

Examples

Structure

reflex_pragmatic_dnd/            # the library (wrappers + JSX glue)
reflex_pragmatic_drag_and_drop/  # Kanban demo app
examples/                        # additional examples
specs/                           # SDD documentation

How it works

A local React glue (pragmatic_dnd.jsx, bundled with rx.asset) attaches Pragmatic to the DOM elements via useEffect/useRef and emits JSON-serializable payloads. NoSSRComponent wrappers expose them as Reflex components with typed events. Only discrete events (start/drop) cross the WebSocket; the continuous computation happens on the client. See specs/technical/architecture.md.

Tests

uv run pytest

Covers the pure reducers (transformation rules from Data Model §4 and edge cases from API Spec §4), the states of the demo/example app, and the wrapper contract (tags, snake↔camel props, events, NoSSRComponent, pinned @atlaskit dependencies).

Publishing

This package is a Reflex custom component. Build it with uv run reflex component build and publish with uv publish. Full steps, prerequisites, and the command reference are in PUBLISHING.md.

License

MIT.

Metadata

Release files for reflex-pragmatic-drag-and-drop 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for reflex-pragmatic-drag-and-drop 0.2.0
File Size Uploaded Provenance
reflex_pragmatic_drag_and_drop-0.2.0.tar.gz 19.8 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for reflex-pragmatic-drag-and-drop 0.2.0
File Interpreter ABI Platform
reflex_pragmatic_drag_and_drop-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 31.4 kB

Release files / reflex_pragmatic_drag_and_drop-0.2.0.tar.gz

Download URL reflex_pragmatic_drag_and_drop-0.2.0.tar.gz
Size 19.8 kB
Tags Source
SHA-256 checksum
How to use checksums
dc24492de19b071249f1a782bb61def3f350e6aed925fdf88e28cf1ac8a37477
BLAKE2b-256 checksum
How to use checksums
2fb07ff223fcd132c17c4fc50b3b0342b7507d542fbf074d5f464d00b546e94e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.9

Release files / reflex_pragmatic_drag_and_drop-0.2.0-py3-none-any.whl

Download URL reflex_pragmatic_drag_and_drop-0.2.0-py3-none-any.whl
Size 11.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9fee98895c4c93b4c068f1231636fece59a1262947aca36d56cde226e718679e
BLAKE2b-256 checksum
How to use checksums
54f7e26735c2433b1524b95529d0189b37d44ad88fe2d37060559b4499c44eae
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.9

Security for reflex-pragmatic-drag-and-drop 0.2.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page