|
66 | 66 | let dialogTitle = $state.raw(""); |
67 | 67 | let dialogDescription = $state.raw(""); |
68 | 68 | let dialogConfirmLabel = $state.raw(""); |
69 | | - let dialogOnClose: (() => void) | undefined; |
| 69 | + let dialogTrigger: HTMLElement | null = null; |
70 | 70 | let dialogDidConfirm = false; |
| 71 | + let dialogOnClose: (() => void) | undefined; |
| 72 | +
|
| 73 | + function showDialog({ |
| 74 | + title, |
| 75 | + description, |
| 76 | + confirmLabel, |
| 77 | + onClose, |
| 78 | + }: { |
| 79 | + title: string; |
| 80 | + description: string; |
| 81 | + confirmLabel: string; |
| 82 | + onClose: () => void; |
| 83 | + }) { |
| 84 | + dialogOpen = true; |
| 85 | + dialogTitle = title; |
| 86 | + dialogDescription = description; |
| 87 | + dialogConfirmLabel = confirmLabel; |
| 88 | + dialogTrigger = document.activeElement instanceof HTMLElement ? document.activeElement : null; |
| 89 | + dialogDidConfirm = false; |
| 90 | + dialogOnClose = onClose; |
| 91 | + } |
71 | 92 |
|
72 | 93 | function onDialogOpenChangeComplete(open: boolean) { |
73 | 94 | if (!open) { |
74 | 95 | dialogTitle = ""; |
75 | 96 | dialogDescription = ""; |
76 | 97 | dialogConfirmLabel = ""; |
| 98 | + dialogTrigger?.focus(); |
| 99 | + dialogTrigger = null; |
77 | 100 | dialogOnClose?.(); |
78 | 101 | dialogOnClose = undefined; |
79 | | - dialogDidConfirm = false; |
80 | 102 | } |
81 | 103 | } |
82 | 104 |
|
|
121 | 143 | } |
122 | 144 | } |
123 | 145 |
|
124 | | - dialogOpen = true; |
125 | | - dialogTitle = title; |
126 | | - dialogDescription = `An item named "${name}" already exists in this location. Do you want to skip it or cancel the operation entirely?`; |
127 | | - dialogConfirmLabel = "Skip"; |
128 | | - dialogOnClose = () => { |
129 | | - resolve(dialogDidConfirm ? "skip" : "cancel"); |
130 | | - }; |
| 146 | + showDialog({ |
| 147 | + title, |
| 148 | + description: `An item named "${name}" already exists in this location. Do you want to skip it or cancel the operation entirely?`, |
| 149 | + confirmLabel: "Skip", |
| 150 | + onClose: () => { |
| 151 | + resolve(dialogDidConfirm ? "skip" : "cancel"); |
| 152 | + }, |
| 153 | + }); |
131 | 154 | }); |
132 | 155 | } |
133 | 156 |
|
|
147 | 170 |
|
148 | 171 | function canRemove({ removed }: OnRemoveArgs<FileNode, FolderNode>) { |
149 | 172 | return new Promise<boolean>((resolve) => { |
150 | | - dialogOpen = true; |
151 | | - dialogTitle = `Are you sure you want to delete ${removed.length} item(s)?`; |
152 | | - dialogDescription = "They will be permanently deleted. This action cannot be undone."; |
153 | | - dialogConfirmLabel = "Confirm"; |
154 | | - dialogOnClose = () => { |
155 | | - resolve(dialogDidConfirm); |
156 | | - }; |
| 173 | + showDialog({ |
| 174 | + title: `Are you sure you want to delete ${removed.length} item(s)?`, |
| 175 | + description: "They will be permanently deleted. This action cannot be undone.", |
| 176 | + confirmLabel: "Confirm", |
| 177 | + onClose: () => { |
| 178 | + resolve(dialogDidConfirm); |
| 179 | + }, |
| 180 | + }); |
157 | 181 | }); |
158 | 182 | } |
159 | 183 |
|
|
169 | 193 | } |
170 | 194 | }; |
171 | 195 |
|
172 | | - async function dropItems(dragged: TreeItemState, destination: TreeItemState | undefined) { |
| 196 | + async function dropItems(draggedId: string, destination: TreeItemState | undefined) { |
173 | 197 | if (destination?.node.type === "file") { |
174 | 198 | throw new Error("Cannot drop on a file"); |
175 | 199 | } |
176 | 200 |
|
177 | | - const movedIds = new Set(selectedIds).add(dragged.node.id); |
| 201 | + const movedIds = new Set(selectedIds).add(draggedId); |
178 | 202 | const didMove = await tree!.move(movedIds, destination); |
179 | 203 | if (!didMove) { |
180 | 204 | return; |
181 | 205 | } |
182 | 206 |
|
183 | 207 | let focusTargetOrder; |
184 | 208 | if (destination === undefined || destination.expanded) { |
185 | | - focusTargetOrder = tree! |
186 | | - .getVisibleItems() |
187 | | - .findIndex((item) => item.node.id === dragged.node.id); |
| 209 | + focusTargetOrder = tree!.getVisibleItems().findIndex((item) => item.node.id === draggedId); |
188 | 210 | } else { |
189 | 211 | focusTargetOrder = tree! |
190 | 212 | .getVisibleItems() |
|
299 | 321 | const handleDrop: EventHandler<DragEvent> = (event) => { |
300 | 322 | event.preventDefault(); |
301 | 323 |
|
302 | | - let dragged; |
303 | | - if (draggedId !== undefined) { |
304 | | - dragged = tree!.getItem(draggedId); |
305 | | - } |
306 | | -
|
307 | 324 | let dropDestination; |
308 | 325 | if (dropDestinationId !== undefined) { |
309 | 326 | dropDestination = tree!.getItem(dropDestinationId); |
310 | 327 | } |
311 | 328 |
|
312 | | - if (dragged !== undefined) { |
313 | | - dropItems(dragged, dropDestination); |
| 329 | + if (draggedId !== undefined) { |
| 330 | + dropItems(draggedId, dropDestination); |
314 | 331 | } else if (event.dataTransfer?.types.includes("Files")) { |
315 | 332 | dropFiles(event.dataTransfer.items, dropDestination); |
316 | 333 | } |
|
0 commit comments