yew_hooks/hooks/
use_drop.rs1use std::rc::Rc;
2
3use web_sys::{DataTransfer, File};
4use yew::prelude::*;
5
6use super::{use_event, use_mut_latest};
7use crate::web_sys_ext::ClipboardEvent;
8
9#[derive(Default)]
11pub struct UseDropOptions {
12 #[allow(clippy::type_complexity)]
14 pub onfiles: Option<Box<dyn FnMut(Vec<File>, DataTransfer)>>,
15 pub ontext: Option<Box<dyn FnMut(String, DataTransfer)>>,
17 pub onuri: Option<Box<dyn FnMut(String, DataTransfer)>>,
19
20 pub ondragover: Option<Box<dyn FnMut(DragEvent)>>,
22 pub ondragenter: Option<Box<dyn FnMut(DragEvent)>>,
24 pub ondragleave: Option<Box<dyn FnMut(DragEvent)>>,
26 pub ondragexit: Option<Box<dyn FnMut(DragEvent)>>,
28 pub ondrop: Option<Box<dyn FnMut(DragEvent)>>,
30 pub onpaste: Option<Box<dyn FnMut(ClipboardEvent)>>,
32}
33
34pub struct UseDropHandle {
36 pub over: UseStateHandle<bool>,
38 pub files: UseStateHandle<Option<Vec<File>>>,
40 pub text: UseStateHandle<Option<String>>,
42 pub uri: UseStateHandle<Option<String>>,
44}
45
46#[hook]
90pub fn use_drop(node: NodeRef) -> UseDropHandle {
91 use_drop_with_options(node, UseDropOptions::default())
92}
93
94#[hook]
124pub fn use_drop_with_options(node: NodeRef, options: UseDropOptions) -> UseDropHandle {
125 let over = use_state(|| false);
126 let files = use_state(|| None);
127 let text = use_state(|| None);
128 let uri = use_state(|| None);
129
130 let onfiles_ref = use_mut_latest(options.onfiles);
131 let ontext_ref = use_mut_latest(options.ontext);
132 let onuri_ref = use_mut_latest(options.onuri);
133
134 let ondragover_ref = use_mut_latest(options.ondragover);
135 let ondragenter_ref = use_mut_latest(options.ondragenter);
136 let ondragleave_ref = use_mut_latest(options.ondragleave);
137 let ondragexit_ref = use_mut_latest(options.ondragexit);
138 let ondrop_ref = use_mut_latest(options.ondrop);
139 let onpaste_ref = use_mut_latest(options.onpaste);
140
141 {
142 let over = over.clone();
143 use_event(node.clone(), "dragover", move |e: DragEvent| {
144 e.prevent_default();
145 over.set(true);
146
147 let ondragover_ref = ondragover_ref.current();
148 let ondragover = &mut *ondragover_ref.borrow_mut();
149 if let Some(ondragover) = ondragover {
150 ondragover(e);
151 }
152 });
153 }
154
155 {
156 let over = over.clone();
157 use_event(node.clone(), "dragenter", move |e: DragEvent| {
158 e.prevent_default();
159 over.set(true);
160
161 let ondragenter_ref = ondragenter_ref.current();
162 let ondragenter = &mut *ondragenter_ref.borrow_mut();
163 if let Some(ondragenter) = ondragenter {
164 ondragenter(e);
165 }
166 });
167 }
168
169 {
170 let over = over.clone();
171 use_event(node.clone(), "dragleave", move |e: DragEvent| {
172 over.set(false);
173
174 let ondragleave_ref = ondragleave_ref.current();
175 let ondragleave = &mut *ondragleave_ref.borrow_mut();
176 if let Some(ondragleave) = ondragleave {
177 ondragleave(e);
178 }
179 });
180 }
181
182 {
183 let over = over.clone();
184 use_event(node.clone(), "dragexit", move |e: DragEvent| {
185 over.set(false);
186
187 let ondragexit_ref = ondragexit_ref.current();
188 let ondragexit = &mut *ondragexit_ref.borrow_mut();
189 if let Some(ondragexit) = ondragexit {
190 ondragexit(e);
191 }
192 });
193 }
194
195 let on_data_transfer = {
196 let uri = uri.clone();
197 let files = files.clone();
198 let text = text.clone();
199 let ontext_ref = ontext_ref.clone();
200 let onfiles_ref = onfiles_ref.clone();
201
202 Rc::new(move |data_transfer: DataTransfer| {
203 if let Ok(uri_data) = data_transfer.get_data("text/uri-list") {
204 if !uri_data.is_empty() {
205 let onuri_ref = onuri_ref.current();
206 let onuri = &mut *onuri_ref.borrow_mut();
207 if let Some(onuri) = onuri {
208 let uri_data = uri_data.clone();
209 onuri(uri_data, data_transfer);
210 }
211 uri.set(Some(uri_data));
212 return;
213 }
214 }
215
216 if let Some(files_list) = data_transfer.files() {
217 if files_list.length() > 0 {
218 log::debug!("files_list");
219 let mut files_vec = vec![];
220 for index in 0..files_list.length() {
221 if let Some(file) = files_list.item(index) {
222 files_vec.push(file);
223 }
224 }
225
226 let onfiles_ref = onfiles_ref.current();
227 let onfiles = &mut *onfiles_ref.borrow_mut();
228 if let Some(onfiles) = onfiles {
229 let files_vec = files_vec.clone();
230 onfiles(files_vec, data_transfer);
231 }
232 files.set(Some(files_vec));
233 return;
234 }
235 }
236
237 if let Ok(text_data) = data_transfer.get_data("text") {
238 let ontext_ref = ontext_ref.current();
239 let ontext = &mut *ontext_ref.borrow_mut();
240 if let Some(ontext) = ontext {
241 let text_data = text_data.clone();
242 ontext(text_data, data_transfer);
243 }
244 text.set(Some(text_data));
245 }
246 })
247 };
248
249 {
250 let over = over.clone();
251 let on_data_transfer = on_data_transfer.clone();
252 use_event(node.clone(), "drop", move |e: DragEvent| {
253 e.prevent_default();
254 over.set(false);
255
256 if let Some(data_transfer) = e.data_transfer() {
257 on_data_transfer(data_transfer);
258 }
259
260 let ondrop_ref = ondrop_ref.current();
261 let ondrop = &mut *ondrop_ref.borrow_mut();
262 if let Some(ondrop) = ondrop {
263 ondrop(e);
264 }
265 });
266 }
267
268 {
269 let on_data_transfer = on_data_transfer.clone();
270 use_event(node, "paste", move |e: ClipboardEvent| {
271 if let Some(data_transfer) = e.clipboard_data() {
272 on_data_transfer(data_transfer);
273 }
274
275 let onpaste_ref = onpaste_ref.current();
276 let onpaste = &mut *onpaste_ref.borrow_mut();
277 if let Some(onpaste) = onpaste {
278 onpaste(e);
279 }
280 });
281 }
282
283 UseDropHandle {
284 over,
285 files,
286 text,
287 uri,
288 }
289}