dioxus_dnd/core/components/
mod.rs1#![doc = include_str!("../../../docs/api/drag-and-drop.md")]
2
3use dioxus::prelude::*;
4
5mod delivery;
6mod draggable;
7mod drop_zone;
8mod handle;
9mod overlay;
10mod pointer;
11mod provider;
12
13pub use draggable::Draggable;
14pub(crate) use drop_zone::FlatDropZone;
15pub use drop_zone::{
16 use_parent_zone, BridgeDropZone, BridgeParentZoneBoundary, DropZone, ParentZone,
17};
18pub use handle::{DragHandle, NoDrag};
19pub use overlay::{DragOverlay, SettleSlot};
20pub use provider::DndProvider;
21
22pub(crate) use delivery::{
23 deliver_drop, drop_query, resolve_drag_hover, resolve_drag_target, DropCompletion, SettleRoute,
24 RELEASE_RECOVERY_MOVES,
25};
26pub(crate) use handle::ActivatorContext;
27pub(crate) use overlay::overlay_style;
28pub(crate) use pointer::{primary_press, touch_style, HoldTimer};
29
30fn take_text_styles(attributes: &mut Vec<Attribute>) -> String {
31 let mut styles = Vec::new();
32 attributes.retain(|attribute| {
33 if attribute.name != "style" {
34 return true;
35 }
36 if let dioxus::core::AttributeValue::Text(style) = &attribute.value {
37 styles.push(style.clone());
38 }
39 false
40 });
41 styles.join(" ")
42}
43
44pub(crate) fn merge_style_user_last(attributes: &mut Vec<Attribute>, defaults: &str) -> String {
46 let user = take_text_styles(attributes);
47 format!("{defaults} {user}")
48}
49
50pub(crate) fn merge_style_invariant_last(
57 attributes: &mut Vec<Attribute>,
58 invariant: &str,
59 invariant_properties: &[&str],
60) -> String {
61 attributes.retain(|attribute| {
66 attribute.namespace != Some("style") || !invariant_properties.contains(&attribute.name)
67 });
68 let user = take_text_styles(attributes);
69 format!("{user} {invariant}")
70}
71
72pub(crate) fn protect_attributes(attributes: &mut Vec<Attribute>, protected: &[&str]) {
75 attributes.retain(|attribute| !protected.contains(&attribute.name));
76}
77
78#[cfg(test)]
79mod tests {
80 use super::*;
81
82 #[test]
83 fn protected_listener_and_state_names_are_removed_but_other_attrs_survive() {
84 let mut attributes = vec![
85 Attribute::new("onclick", "caller", None, false),
86 Attribute::new("data-active", "caller", None, false),
87 Attribute::new("class", "card", None, false),
88 ];
89
90 protect_attributes(&mut attributes, &["onclick", "data-active"]);
91
92 assert_eq!(attributes.len(), 1);
93 assert_eq!(attributes[0].name, "class");
94 }
95
96 #[test]
97 fn every_forwarded_style_is_consumed_in_order() {
98 let mut attributes = vec![
99 Attribute::new("style", "color: red;", None, false),
100 Attribute::new("class", "card", None, false),
101 Attribute::new("style", "opacity: .5;", None, false),
102 ];
103
104 let style = merge_style_user_last(&mut attributes, "display: grid;");
105
106 assert_eq!(style, "display: grid; color: red; opacity: .5;");
107 assert_eq!(attributes.len(), 1);
108 assert_eq!(attributes[0].name, "class");
109 }
110
111 #[test]
112 fn invariant_styles_are_emitted_after_user_declarations() {
113 let mut attributes = vec![Attribute::new(
114 "style",
115 "touch-action: auto; transform: scale(2);",
116 None,
117 false,
118 )];
119
120 let style = merge_style_invariant_last(
121 &mut attributes,
122 "touch-action: none; transform: translate(4px);",
123 &["touch-action", "transform"],
124 );
125
126 assert_eq!(
127 style,
128 "touch-action: auto; transform: scale(2); touch-action: none; transform: translate(4px);"
129 );
130 assert!(attributes.is_empty());
131 }
132
133 #[test]
134 fn invariant_style_namespace_properties_are_removed_selectively() {
135 let mut attributes = vec![
136 Attribute::new("touch-action", "auto", Some("style"), false),
137 Attribute::new("transform", "scale(2)", Some("style"), false),
138 Attribute::new("opacity", "0.5", Some("style"), false),
139 ];
140
141 let style = merge_style_invariant_last(
142 &mut attributes,
143 "touch-action: none; transform: none;",
144 &["touch-action", "transform"],
145 );
146
147 assert_eq!(style, " touch-action: none; transform: none;");
148 assert_eq!(attributes.len(), 1);
149 assert_eq!(attributes[0].name, "opacity");
150 assert_eq!(attributes[0].namespace, Some("style"));
151 }
152}