mirror of
https://github.com/alam00000/bentopdf.git
synced 2026-11-12 17:44:01 +01:00
feat: drag-and-drop reordering for multi-file to PDF conversions
Tools that combine several files into a single PDF used the upload order as the page order, with no way to change it short of clearing and re-adding files. Each file row now has a drag handle, and the new order is used when the PDF is built. Applies to the JPG, PNG, WebP, BMP, HEIC, SVG, TIFF, Image and TXT to PDF tools. The shared logic lives in utils/sortable-file-list.ts (built on the existing sortablejs dependency) instead of being duplicated per page.
This commit is contained in:
1 parent
4edb1718cc
commit
49ab2ef17f
12 files changed
+281
-11
No files matched your search
@@ -0,0 +1,75 @@
|
||||
import Sortable from 'sortablejs';
|
||||
import { trText } from '../i18n/i18n.js';
|
||||
|
||||
type ReorderHandler = (oldIndex: number, newIndex: number) => void;
|
||||
|
||||
const sortables = new WeakMap<HTMLElement, Sortable>();
|
||||
|
||||
export function moveItem<T>(
|
||||
items: readonly T[],
|
||||
oldIndex: number,
|
||||
newIndex: number
|
||||
): T[] {
|
||||
const result = [...items];
|
||||
if (
|
||||
oldIndex === newIndex ||
|
||||
oldIndex < 0 ||
|
||||
oldIndex >= result.length ||
|
||||
newIndex < 0 ||
|
||||
newIndex >= result.length
|
||||
) {
|
||||
return result;
|
||||
}
|
||||
const [moved] = result.splice(oldIndex, 1);
|
||||
result.splice(newIndex, 0, moved);
|
||||
return result;
|
||||
}
|
||||
|
||||
export function createDragHandle(): HTMLElement {
|
||||
const handle = document.createElement('div');
|
||||
handle.className =
|
||||
'drag-handle cursor-move text-gray-400 hover:text-white p-1 rounded transition-colors flex-shrink-0';
|
||||
const label = trText('Drag to reorder');
|
||||
handle.title = label;
|
||||
handle.setAttribute('aria-label', label);
|
||||
handle.innerHTML = '<i data-lucide="grip-vertical" class="w-4 h-4"></i>';
|
||||
return handle;
|
||||
}
|
||||
|
||||
// Rows must contain an element created by createDragHandle(). The list is
|
||||
// re-rendered by the caller, so one Sortable per container is kept and only
|
||||
// its reorder callback is swapped on subsequent calls.
|
||||
export function enableFileListReorder(
|
||||
container: HTMLElement,
|
||||
onReorder: ReorderHandler
|
||||
): void {
|
||||
const onEnd = (evt: Sortable.SortableEvent) => {
|
||||
const { oldIndex, newIndex } = evt;
|
||||
if (
|
||||
oldIndex === undefined ||
|
||||
newIndex === undefined ||
|
||||
oldIndex === newIndex
|
||||
) {
|
||||
return;
|
||||
}
|
||||
onReorder(oldIndex, newIndex);
|
||||
};
|
||||
|
||||
const existing = sortables.get(container);
|
||||
if (existing) {
|
||||
existing.option('onEnd', onEnd);
|
||||
return;
|
||||
}
|
||||
|
||||
sortables.set(
|
||||
container,
|
||||
Sortable.create(container, {
|
||||
handle: '.drag-handle',
|
||||
animation: 150,
|
||||
ghostClass: 'sortable-ghost',
|
||||
chosenClass: 'sortable-chosen',
|
||||
dragClass: 'sortable-drag',
|
||||
onEnd,
|
||||
})
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user