diff --git a/dist/index.html b/dist/index.html
index 4a8c710..326effd 100644
--- a/dist/index.html
+++ b/dist/index.html
@@ -5756,12 +5756,13 @@ var SearchStore = class {
var search = new SearchStore();
//#endregion
//#region src/components/Sidebar.svelte
-var root_1$7 = /* @__PURE__ */ from_html(`
Loading entries...
`);
@@ -5979,7 +6044,7 @@ var root_2$4 = /* @__PURE__ */ from_html(`+ New Entry`);
var root_3$4 = /* @__PURE__ */ from_html(`
`);
var root_6$4 = /* @__PURE__ */ from_html(`matching "
"`, 1);
-var root_7$2 = /* @__PURE__ */ from_html(`
| | | |
`);
+var root_7$2 = /* @__PURE__ */ from_html(`
| ⠿ | | |
`);
var root_5$3 = /* @__PURE__ */ from_html(`
`, 1);
var root$5 = /* @__PURE__ */ from_html(`
`);
function EntryList($$anchor, $$props) {
@@ -5988,6 +6053,13 @@ function EntryList($$anchor, $$props) {
let loading = /* @__PURE__ */ state(true);
let error = /* @__PURE__ */ state("");
let resultCount = /* @__PURE__ */ state(0);
+ let draggedEntryId = /* @__PURE__ */ state(null);
+ function handleDragStart(entryId) {
+ set(draggedEntryId, entryId, true);
+ }
+ function handleDragEnd() {
+ set(draggedEntryId, null);
+ }
async function loadEntries() {
set(loading, true);
set(error, "");
@@ -6076,7 +6148,7 @@ function EntryList($$anchor, $$props) {
each(tbody, 21, () => get(entries), (entry) => entry.id, ($$anchor, entry) => {
var tr = root_7$2();
var td = child(tr);
- var span_1 = child(td);
+ var span_1 = sibling(child(td), 2);
var text_6 = child(span_1, true);
reset(span_1);
reset(td);
@@ -6092,11 +6164,18 @@ function EntryList($$anchor, $$props) {
reset(td_2);
reset(tr);
template_effect(() => {
+ set_class(tr, 1, `entry-row ${get(draggedEntryId) === get(entry).id ? "dragging" : ""}`, "svelte-13s7gu4");
set_text(text_6, get(entry).title);
set_text(text_7, get(entry).username);
set_text(text_8, get(entry).url || "—");
});
delegated("click", tr, () => $$props.onSelect(get(entry).id));
+ event("DragStart", tr, (e) => {
+ e.dataTransfer.setData("text/plain", get(entry).id);
+ e.dataTransfer.effectAllowed = "move";
+ handleDragStart(get(entry).id);
+ });
+ event("DragEnd", tr, handleDragEnd);
append($$anchor, tr);
});
reset(tbody);
@@ -7261,6 +7340,25 @@ label {
color: var(--color-primary);
}
+ .group-wrapper.drop-target.svelte-181dlmc .group-item:where(.svelte-181dlmc),
+ .group-row.drop-target.svelte-181dlmc .group-item:where(.svelte-181dlmc) {
+ background: rgba(108, 99, 255, 0.3);
+ color: var(--color-primary);
+ }
+
+ .group-wrapper.drop-target.svelte-181dlmc,
+ .group-row.drop-target.svelte-181dlmc {
+ background: rgba(108, 99, 255, 0.12);
+ border: 2px dashed var(--color-primary);
+ border-radius: var(--radius-md);
+ box-shadow: 0 0 12px rgba(108, 99, 255, 0.3);
+ }
+
+ .group-wrapper.svelte-181dlmc {
+ border-radius: var(--radius-md);
+ transition: background-color 150ms;
+ }
+
.group-icon.svelte-181dlmc {
font-size: 1rem;
}
@@ -7310,6 +7408,27 @@ label {
border-top: 1px solid var(--color-border);
}
+ .drop-indicator.svelte-181dlmc {
+ position: fixed;
+ bottom: 20px;
+ left: 50%;
+ transform: translateX(-50%);
+ padding: 8px 16px;
+ background: var(--color-primary);
+ color: #fff;
+ border-radius: var(--radius-md);
+ font-size: 0.8rem;
+ font-weight: 500;
+ z-index: 100;
+ pointer-events: none;
+ animation: svelte-181dlmc-fadeIn 150ms ease;
+ }
+
+ @keyframes svelte-181dlmc-fadeIn {
+ from { opacity: 0; transform: translateX(-50%) translateY(10px); }
+ to { opacity: 1; transform: translateX(-50%) translateY(0); }
+ }
+
/* Modal */
.modal-overlay.svelte-181dlmc {
position: fixed;
@@ -7435,7 +7554,7 @@ label {
}
.entry-row.svelte-13s7gu4 {
- cursor: pointer;
+ cursor: grab;
transition: background-color 150ms;
}
@@ -7443,12 +7562,32 @@ label {
background: var(--color-surface-hover);
}
+ .entry-row.dragging.svelte-13s7gu4 {
+ opacity: 0.4;
+ }
+
+ .entry-row.svelte-13s7gu4:active {
+ cursor: grabbing;
+ }
+
.entry-row.svelte-13s7gu4 td:where(.svelte-13s7gu4) {
padding: 10px 12px;
font-size: 0.875rem;
border-bottom: 1px solid var(--color-border);
}
+ .drag-handle.svelte-13s7gu4 {
+ color: var(--color-text-muted);
+ margin-right: 6px;
+ user-select: none;
+ opacity: 0.5;
+ transition: opacity 150ms;
+ }
+
+ .entry-row.svelte-13s7gu4:hover .drag-handle:where(.svelte-13s7gu4) {
+ opacity: 1;
+ }
+
.entry-title.svelte-13s7gu4 {
font-weight: 500;
}
diff --git a/src/components/EntryList.svelte b/src/components/EntryList.svelte
index 97dc646..55cc3b2 100644
--- a/src/components/EntryList.svelte
+++ b/src/components/EntryList.svelte
@@ -9,6 +9,16 @@
let { onSelect, onAdd } = $props()
+ let draggedEntryId = $state(null)
+
+ function handleDragStart(entryId) {
+ draggedEntryId = entryId
+ }
+
+ function handleDragEnd() {
+ draggedEntryId = null
+ }
+
async function loadEntries() {
loading = true
error = ''
@@ -82,8 +92,19 @@
{#each entries as entry (entry.id)}
- onSelect(entry.id)} class="entry-row">
+
onSelect(entry.id)}
+ class="entry-row {draggedEntryId === entry.id ? 'dragging' : ''}"
+ draggable="true"
+ onDragStart={(e) => {
+ e.dataTransfer.setData('text/plain', entry.id)
+ e.dataTransfer.effectAllowed = 'move'
+ handleDragStart(entry.id)
+ }}
+ onDragEnd={handleDragEnd}
+ >
|
+ ⠿
{entry.title}
|
@@ -153,7 +174,7 @@
}
.entry-row {
- cursor: pointer;
+ cursor: grab;
transition: background-color 150ms;
}
@@ -161,12 +182,32 @@
background: var(--color-surface-hover);
}
+ .entry-row.dragging {
+ opacity: 0.4;
+ }
+
+ .entry-row:active {
+ cursor: grabbing;
+ }
+
.entry-row td {
padding: 10px 12px;
font-size: 0.875rem;
border-bottom: 1px solid var(--color-border);
}
+ .drag-handle {
+ color: var(--color-text-muted);
+ margin-right: 6px;
+ user-select: none;
+ opacity: 0.5;
+ transition: opacity 150ms;
+ }
+
+ .entry-row:hover .drag-handle {
+ opacity: 1;
+ }
+
.entry-title {
font-weight: 500;
}
diff --git a/src/components/Sidebar.svelte b/src/components/Sidebar.svelte
index afcfbaa..4eeda74 100644
--- a/src/components/Sidebar.svelte
+++ b/src/components/Sidebar.svelte
@@ -1,5 +1,5 @@
|