import { DndContext, DragOverlay, KeyboardSensor, MouseSensor, TouchSensor, closestCenter, useSensor, useSensors } from '@dnd-kit/core' import { SortableContext, arrayMove, horizontalListSortingStrategy, sortableKeyboardCoordinates } from '@dnd-kit/sortable' import { useRef, useState } from 'react' import { createPortal } from 'react-dom' import { CSS } from '@dnd-kit/utilities' import { useClientMotion } from '@/lib/useClientMotion' import type { ReactNode } from 'react' const SortableColumns = ({ ids, fixed = [], name, onChange, children }: { ids: string[]; fixed?: string[]; name: (id: string) => { text: string; language: string } onChange: (ids: string[]) => void; children: (ids: string[]) => ReactNode }, ) => { const [active, setActive] = useState (null) const drag = useRef<{ id: string; ids: string[] } | null> (null) const motion = useClientMotion () const sensors = useSensors ( useSensor (MouseSensor, { activationConstraint: { distance: 4 } }), useSensor (TouchSensor, { activationConstraint: { delay: 350, tolerance: 8 } }), useSensor (KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates })) const move = (current: string[], from: string, to: string) => { if (fixed.includes (from) || fixed.includes (to)) return current const source = current.indexOf (from) const target = current.indexOf (to) return source < 0 || target < 0 || source === target ? current : arrayMove (current, source, target) } const reset = () => { drag.current = null setActive (null) } return name (String (event.active.id)).text, onDragOver: event => event.over == null ? undefined : name (String (event.over.id)).text, onDragMove: () => undefined, onDragEnd: () => undefined, onDragCancel: () => undefined }, screenReaderInstructions: { draggable: active == null ? '' : name (active).text } }} onDragStart={event => { const id = String (event.active.id) drag.current = { id, ids } setActive (id) }} onDragCancel={reset} onDragEnd={event => { const session = drag.current reset () if (session == null || event.over == null || session.id !== String (event.active.id) || session.ids.length !== ids.length || session.ids.some ((id, index) => id !== ids[index])) return const next = move (ids, session.id, String (event.over.id)) if (next.some ((id, index) => id !== ids[index])) onChange (next) }}> {children (ids)} {typeof document !== 'undefined' && createPortal ( [ { transform: CSS.Translate.toString (transform.initial) }, { transform: CSS.Translate.toString (transform.final) }] }}> {active != null &&
{name (active).text}
}
, document.body)}
} export default SortableColumns