Skip to content

Commit 8ad9cd8

Browse files
devin-ai-integration[bot]thomas@reflex.devLendemor
authored
Add comprehensive API Reference and enhanced examples for drag-and-drop documentation (#1505)
* Add comprehensive API Reference and enhanced examples for drag-and-drop documentation - Added detailed API Reference section for rxe.dnd.draggable and rxe.dnd.drop_target components - Documented all parameters including item, collect, type, accept, on_drop, on_hover, on_end - Added Monitor Classes section covering DragSourceMonitor and DropTargetMonitor methods - Added Default Collected Parameters section showing structure for both components - Enhanced examples demonstrating item parameter usage for data passing - Enhanced examples showing collect parameter usage for state tracking - All examples tested and verified to compile correctly in browser - Documentation follows existing reflex-web patterns and styling Co-Authored-By: [email protected] <[email protected]> * Fix collect parameter example and dynamic list item movement bug - Replace non-functional collect example with real-time monitor state demonstration - Fix move_item method to correctly identify source list and prevent wrong item removal - Address GitHub comments from Lendemor regarding collect usage and dynamic list bugs Co-Authored-By: [email protected] <[email protected]> * Use frontmatter metadata for API Reference instead of manual section Co-Authored-By: [email protected] <[email protected]> * Remove non-functional frontmatter metadata for enterprise components - Enterprise components require manual API Reference sections, not frontmatter metadata - The get_components_from_metadata function only processes docs/library paths - Manual API Reference section now appears correctly on the page - All fixes for collect example and dynamic list bug remain intact Co-Authored-By: [email protected] <[email protected]> * Format API Reference to match library component styling - Use h1_comp and h2_comp components instead of markdown headers - Apply flex flex-col CSS classes to match auto-generated API sections - Maintain comprehensive content while ensuring visual consistency - Addresses user feedback to make API Reference 'close to the other page' Co-Authored-By: [email protected] <[email protected]> * fix syntax error --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: [email protected] <[email protected]> Co-authored-by: Thomas Brandého <[email protected]>
1 parent 1b6a86e commit 8ad9cd8

File tree

1 file changed

+224
-5
lines changed

1 file changed

+224
-5
lines changed

docs/enterprise/drag-and-drop.md

Lines changed: 224 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -226,18 +226,36 @@ class DynamicListState(rx.State):
226226

227227
def move_item(self, item_data: dict, target_list: str):
228228
item_id = item_data.get("id")
229+
source_list = item_data.get("list_id")
229230

230-
# Remove from source list
231-
self.list_a = [item for item in self.list_a if item.id != item_id]
232-
self.list_b = [item for item in self.list_b if item.id != item_id]
231+
if not item_id or not source_list:
232+
return
233+
234+
# Find the item in the source list
235+
source_items = getattr(self, f"list_{source_list.lower()}")
236+
item_to_move = None
237+
for item in source_items:
238+
if item.id == item_id:
239+
item_to_move = item
240+
break
241+
242+
if not item_to_move:
243+
return
244+
245+
# Remove from source list only
246+
if source_list == "A":
247+
self.list_a = [item for item in self.list_a if item.id != item_id]
248+
else:
249+
self.list_b = [item for item in self.list_b if item.id != item_id]
233250

234-
# Add to target list
251+
# Create new item for target list
235252
new_item = ListItem(
236253
id=item_id,
237-
text=item_data.get("text", ""),
254+
text=item_to_move.text,
238255
list_id=target_list
239256
)
240257

258+
# Add to target list
241259
if target_list == "A":
242260
self.list_a.append(new_item)
243261
else:
@@ -317,6 +335,207 @@ Access real-time drag/drop state:
317335
- `is_over`: Boolean indicating if draggable is hovering
318336
- `can_drop`: Boolean indicating if drop is allowed
319337

338+
# API Reference
339+
340+
### rxe.dnd.draggable
341+
342+
Creates a draggable component that can be moved around the interface.
343+
344+
**Parameters:**
345+
346+
- **`type`** (str, required): String identifier that must match the `accept` list of drop targets
347+
- **`item`** (dict | Callable): Data object passed to drop handlers. Can be a static dictionary or a function that receives a `DragSourceMonitor` and returns data
348+
- **`preview_options`** (dict): Configuration for the drag preview appearance
349+
- **`options`** (dict): Additional drag source options like `dropEffect`
350+
- **`on_end`** (EventHandler): Event handler called when drag operation completes
351+
- **`can_drag`** (Callable): Function that determines if the item can be dragged
352+
- **`is_dragging`** (Callable): Function to override the default dragging state detection
353+
- **`collect`** (Callable): Function to collect custom properties from the drag monitor
354+
355+
### rxe.dnd.drop_target
356+
357+
Creates a drop target that can receive draggable items.
358+
359+
**Parameters:**
360+
361+
- **`accept`** (str | list[str], required): Drag type(s) this target accepts
362+
- **`options`** (dict): Additional drop target configuration options
363+
- **`on_drop`** (EventHandler): Event handler called when an item is dropped, receives the `item` data
364+
- **`on_hover`** (EventHandler): Event handler called when an item hovers over the target
365+
- **`can_drop`** (Callable): Function that determines if a specific item can be dropped
366+
- **`collect`** (Callable): Function to collect custom properties from the drop monitor
367+
368+
## Monitor Classes
369+
370+
### DragSourceMonitor
371+
372+
Provides information about the drag operation state:
373+
374+
- **`is_dragging()`**: Returns `True` if this item is currently being dragged
375+
- **`can_drag()`**: Returns `True` if the item can be dragged
376+
- **`get_item()`**: Returns the item data being dragged
377+
- **`get_item_type()`**: Returns the drag type string
378+
- **`get_drop_result()`**: Returns the drop result (available in `on_end`)
379+
- **`did_drop()`**: Returns `True` if the item was successfully dropped
380+
381+
### DropTargetMonitor
382+
383+
Provides information about the drop target state:
384+
385+
- **`is_over()`**: Returns `True` if a draggable item is hovering over this target
386+
- **`can_drop()`**: Returns `True` if the hovering item can be dropped
387+
- **`get_item()`**: Returns the item data of the hovering draggable
388+
- **`get_item_type()`**: Returns the drag type of the hovering item
389+
390+
## Default Collected Parameters
391+
392+
### Draggable.collected_params
393+
394+
```python
395+
{
396+
"is_dragging": bool, # True when this item is being dragged
397+
"can_drag": bool # True when this item can be dragged
398+
}
399+
```
400+
401+
### DropTarget.collected_params
402+
403+
```python
404+
{
405+
"is_over": bool, # True when a draggable is hovering
406+
"can_drop": bool, # True when the hovering item can be dropped
407+
"item": dict | None # Data from the hovering draggable item
408+
}
409+
```
410+
411+
## Advanced Usage Examples
412+
413+
### Data Passing with Item Parameter
414+
415+
The `item` parameter allows you to pass data from draggable components to drop handlers:
416+
417+
```python demo exec toggle
418+
import reflex as rx
419+
import reflex_enterprise as rxe
420+
421+
class SimpleState(rx.State):
422+
message: str = "No items dropped yet"
423+
424+
def simple_draggable():
425+
return rxe.dnd.draggable(
426+
rx.box(
427+
"Drag me!",
428+
p=4,
429+
bg="blue.100",
430+
border="1px solid blue",
431+
cursor="grab"
432+
),
433+
type="simple",
434+
item={"name": "test_item", "value": 42}
435+
)
436+
437+
def simple_drop_target():
438+
return rxe.dnd.drop_target(
439+
rx.box(
440+
rx.text(SimpleState.message),
441+
p=4,
442+
bg="gray.100",
443+
border="2px dashed gray",
444+
min_height="100px"
445+
),
446+
accept=["simple"],
447+
on_drop=lambda item: SimpleState.setvar("message", f"Dropped: {item['name']}")
448+
)
449+
450+
def item_data_example():
451+
return rx.vstack(
452+
simple_draggable(),
453+
simple_drop_target(),
454+
spacing="4"
455+
)
456+
```
457+
458+
### Custom Collect Functions
459+
460+
The `collect` parameter allows you to access drag and drop state information in real-time:
461+
462+
```python demo exec toggle
463+
import reflex as rx
464+
import reflex_enterprise as rxe
465+
466+
class CollectState(rx.State):
467+
drag_info: str = "No drag activity"
468+
drop_info: str = "No drop activity"
469+
470+
def collect_draggable():
471+
params = rxe.dnd.Draggable.collected_params
472+
return rxe.dnd.draggable(
473+
rx.box(
474+
rx.vstack(
475+
rx.text("Drag me!", weight="bold"),
476+
rx.text(f"Dragging: {params.is_dragging}", size="2"),
477+
rx.text(f"Can drag: {params.can_drag}", size="2"),
478+
spacing="1"
479+
),
480+
p=4,
481+
bg=rx.cond(params.is_dragging, "blue.200", "blue.100"),
482+
border="1px solid blue",
483+
cursor=rx.cond(params.is_dragging, "grabbing", "grab"),
484+
opacity=rx.cond(params.is_dragging, 0.7, 1.0)
485+
),
486+
type="collect_item",
487+
item={"id": "collect_test", "name": "Test Item"}
488+
)
489+
490+
def collect_drop_target():
491+
params = rxe.dnd.DropTarget.collected_params
492+
return rxe.dnd.drop_target(
493+
rx.box(
494+
rx.vstack(
495+
rx.text("Drop Zone", weight="bold"),
496+
rx.text(f"Is over: {params.is_over}", size="2"),
497+
rx.text(f"Can drop: {params.can_drop}", size="2"),
498+
rx.cond(
499+
params.item,
500+
rx.text(f"Hovering item: {params.item.get('name', 'Unknown')}", size="2"),
501+
rx.text("No item hovering", size="2")
502+
),
503+
spacing="1"
504+
),
505+
p=4,
506+
bg=rx.cond(
507+
params.is_over & params.can_drop,
508+
"green.200",
509+
rx.cond(params.is_over, "yellow.200", "gray.100")
510+
),
511+
border=rx.cond(
512+
params.is_over & params.can_drop,
513+
"2px solid green",
514+
rx.cond(params.is_over, "2px solid yellow", "2px dashed gray")
515+
),
516+
min_height="120px"
517+
),
518+
accept=["collect_item"],
519+
on_drop=lambda item: [
520+
CollectState.setvar("drop_info", f"Dropped: {item.get('name', 'Unknown')}"),
521+
rx.toast(f"Successfully dropped {item.get('name', 'item')}")
522+
]
523+
)
524+
525+
def custom_collect_example():
526+
return rx.vstack(
527+
rx.text("Real-time Monitor State", weight="bold", size="4"),
528+
rx.hstack(
529+
collect_draggable(),
530+
collect_drop_target(),
531+
spacing="6",
532+
align="start"
533+
),
534+
rx.text(CollectState.drop_info, size="2", color="gray.600"),
535+
spacing="4"
536+
)
537+
```
538+
320539
## Provider
321540

322541
Drag and drop functionality requires the `rxe.dnd.provider` component to wrap your app. The provider is automatically added when using `draggable` or `drop_target` components.

0 commit comments

Comments
 (0)