Skip to main content

Module model

Module model 

Source
Expand description

§Drop effects API reference

The move/copy/link vocabulary of a drop, its modifier-key resolution, and the model helpers that apply a completed drop to app-owned state.

Concept guide: docs/concepts/drop-effects.md.

The crate never touches your data: drops arrive as DropOutcome values and you decide what they mean. The two helpers here cover the most common meaning, the remove-from-source, append-to-target dance, without imposing bounds on your item type: no Clone (the payload arrives owned), no PartialEq (matching is by the key you extract). DropEffect and effective_effect, DropEffects, and DropQuery are re-exported from the prelude alongside the helpers.

DropZone::<Card> {
    on_drop: move |o: DropOutcome<Card>| {
        try_apply_clone_or_move(
            &mut zones.write(),
            o,
            |c| c.id,                       // identity function
            |mut c| { c.id = fresh_id(); c },  // clone hook, runs only on Copy
        ).expect("target accepts only move or copy");
    },
    "Drop here"
}

§DropEffect

The visual and semantic effect of a drop, mirroring the HTML5 dropEffect/effectAllowed vocabulary.

VariantMeaning
MoveThe item leaves its source and lands in the target. The default, and what most drags mean.
CopyThe target receives a duplicate; the source keeps the original. Forced by Ctrl or Cmd held at release.
LinkA reference-style drop, forced by Alt. Rare, but the vocabulary matches the platform convention.
NoneAdvertises that the drag carries no data effect. Modifier keys never override it; the crate still delivers the outcome, so interpretation stays with your handler.

as_str returns the string the native DataTransfer API expects: "move", "copy", "link", "none". The drag-out sources pass it to effectAllowed when advertising a drag to other applications (drag-out.md).

Where it appears:

  • The Draggable effect prop (default Move) sets the drag’s base effect (drag-and-drop.md).
  • DropOutcome::effect carries the resolved value to on_drop.

§Target effect negotiation

DropEffects is a compact set with MOVE, COPY, LINK, NONE, STANDARD, ALL, and EMPTY constants. Combine flags with | and declare them on a target:

DropZone::<Card> {
    allowed_effects: DropEffects::MOVE | DropEffects::COPY,
    accepts_query: move |query: DropQuery<Card>| {
        query.source != Some(ARCHIVE) && query.pointer_kind != PointerKind::Pen
    },
    on_drop: move |outcome| { /* ... */ },
}

If the proposed effect is supported, it is preserved. Otherwise the target selects the first supported fallback in Move, Copy, Link order. EMPTY rejects the drag. DropEffect::None is a disabled proposal, not a selectable effect: it is rejected before legacy or rich acceptance callbacks, hover, collision, or delivery. The complete DropQuery<T> contains payload, source, proposed_effect, mode, pointer_kind, and drag_id. Highlighting, pointer collision, keyboard navigation, cross-window resolution, and final delivery all evaluate the same query.

§effective_effect

pub fn effective_effect(base: DropEffect, modifiers: dioxus::prelude::Modifiers) -> DropEffect

Resolves the effect a drag should use given the currently held modifier keys, the file-manager convention:

Held at releaseResult
Ctrl or Cmd (Meta)Copy
AltLink
Ctrl and Alt togetherCopy (Ctrl wins)
Neitherbase
Anything, when base is DropEffect::NoneNone (a base of None is never overridden)

The library applies this for you. Pointer drags sample the held modifiers on every pointer event and resolve them against the Draggable’s base effect at release, just before delivery, so the state held at release wins, not the state at pickup. Host-side multi-window deliveries resolve the same function against the drag world’s modifier snapshot, so a release in another window behaves identically. Keyboard drops skip resolution and deliver the base effect unchanged. The function is public for custom drag sources and handlers that need the same answer.

§apply_clone_or_move and try_apply_clone_or_move

pub fn apply_clone_or_move<T, K>(
    zones: &mut HashMap<ZoneId, Vec<T>>,
    outcome: DropOutcome<T>,
    key: impl Fn(&T) -> K,
    clone_item: impl FnMut(T) -> T,
) where
    K: PartialEq,

Applies a drop to a HashMap<ZoneId, Vec<T>> model: one Vec per zone, keyed by the ids your DropZones declare.

ArgumentTypeWhat it does
zones&mut HashMap<ZoneId, Vec<T>>Your model. An unknown to zone is created on the fly rather than dropping the item on the floor.
outcomeDropOutcome<T>The drop as delivered; from, to and effect steer what happens.
keyimpl Fn(&T) -> KThe identity function. Extracts each item’s key (typically an id field) so a move can find and remove the original in the source Vec. Matching is by this key, never PartialEq on the item.
clone_itemimpl FnMut(T) -> TThe clone hook. Runs only on Copy, receiving the owned payload and returning the item to append. Assign the fresh id here so the copy gets its own identity.

Semantics:

  • Move removes the matching item from outcome.from, then appends the payload to outcome.to.
  • Copy leaves the source alone and appends clone_item(payload) to the target.
  • The compatibility helper preserves the 3.x contract: every non-Copy effect follows its historical move path and the function returns ().
  • try_apply_clone_or_move has the same arguments but returns Result<(), ApplyDropError>; Link and None are rejected without mutation. Prefer it when a target has not already constrained allowed_effects to Move/Copy.
  • Removal matches every item in the source whose key equals the payload’s key. Keys are expected to be unique within a zone; if they are not, a single move prunes all of them.
  • A move where from == Some(to) removes and re-appends, so dropping an item back onto its own zone sends it to the end of that list.
  • A move with from: None (payload from outside any zone, e.g. a palette) skips removal and just appends. from is filled by the Draggable’s zone prop; declare it or removal never runs.

§apply_list_clone_or_move and try_apply_list_clone_or_move

pub fn apply_list_clone_or_move<T, K>(
    source: Option<&mut Vec<T>>,
    target: &mut Vec<T>,
    outcome: DropOutcome<T>,
    key: impl Fn(&T) -> K,
    clone_item: impl FnMut(T) -> T,
) where
    K: PartialEq,

The two-list version applies a drop between two plain Vec<T>s with the same move/copy semantics. You choose which lists to pass, so the outcome’s from and to fields are ignored here; only payload and effect are consulted. try_apply_list_clone_or_move is the checked form and returns ApplyDropError for Link or None before mutation.

ArgumentTypeWhat it does
sourceOption<&mut Vec<T>>The list a move removes from. Pass None when the payload came from outside any list; removal is skipped.
target&mut Vec<T>The list the item is appended to.
outcomeDropOutcome<T>Only payload and effect are read.
keyimpl Fn(&T) -> KIdentity function, as above. A move removes every source item whose key matches the payload’s.
clone_itemimpl FnMut(T) -> TClone hook, as above. Runs only on Copy.

§Where the rest lives

The full DropOutcome field reference and the Draggable and DropZone props: drag-and-drop.md. ZoneId and the registry: core.md. Advertising effects to other applications: drag-out.md. Cross-window modifier behavior: multi-window.md.

Structs§

DndScope
An explicit lifetime for Dioxus signals and stores created outside a component scope.

Enums§

ApplyDropError
A model helper refused to guess semantics for an unsupported effect.

Functions§

apply_clone_or_move
Apply a drop to a HashMap<ZoneId, Vec<T>> model.
apply_list_clone_or_move
Apply a drop between two plain Vec<T> lists.
try_apply_clone_or_move
Checked form of apply_clone_or_move.
try_apply_list_clone_or_move
Checked form of apply_list_clone_or_move.
use_dnd_model
Create and provide an app-wide model whose Dioxus state survives every window close order.