콘텐츠로 이동
Sortable사용 가이드

고급 정렬

comins-sortable@0.1.6

아래 Playground 경로는 해당 모듈 저장소에서 개발 서버를 실행한 뒤 사용하는 로컬 경로입니다. 현재 문서 사이트의 실행 링크는 아닙니다.

comins-sortable@0.1.2부터 제공되는 기능입니다. 저장소 Playground에서 확인할 수 있습니다.

다중 드래그, threshold, grid 충돌, swap은 Vanilla, React, Vue, Svelte가 공유하는 Area option입니다.

import { useState } from 'react';
import { SortableArea, SortableRoot } from 'comins-sortable/react';
import 'comins-sortable/styles.css';
type Item = { id: string; label: string };
type Mode = 'multi' | 'thresholds' | 'swap' | 'grid' | 'swap-grid';
export function AdvancedSortingExample() {
const [mode, setMode] = useState<Mode>('multi');
const [items, setItems] = useState<Item[]>(
Array.from({ length: 12 }, (_, index) => ({
id: `item-${index + 1}`,
label: `Item ${index + 1}`,
})),
);
return (
<>
<select value={mode} onChange={(event) => setMode(event.target.value as Mode)}>
<option value="multi">Multi-drag</option>
<option value="thresholds">Thresholds</option>
<option value="swap">Swap</option>
<option value="grid">Grid</option>
<option value="swap-grid">Swap grid</option>
</select>
<SortableRoot<Item>>
<SortableArea
areaId="items"
items={items}
itemKey="id"
handle=".drag-handle"
direction={mode === 'grid' || mode === 'swap-grid' ? 'grid' : 'vertical'}
areaProps={{ style: {
display: 'grid',
gridTemplateColumns: mode === 'grid' || mode === 'swap-grid' ? 'repeat(3, 1fr)' : '1fr',
gap: 8,
} }}
multiDrag={mode === 'multi'}
selectedClass="is-selected"
swapThreshold={mode === 'thresholds' ? 0.5 : undefined}
invertSwap={mode === 'thresholds'}
swap={mode === 'swap' || mode === 'swap-grid'}
onItemsChange={(next) => setItems([...next])}
>
{(item) => (
<div>
<button
type="button"
className="drag-handle"
aria-label={`Drag ${item.label}`}
style={{ touchAction: 'none', userSelect: 'none', WebkitUserSelect: 'none' }}
>
⠿
</button>
<span>{item.label}</span>
</div>
)}
</SortableArea>
</SortableRoot>
</>
);
}

multiDrag에서는 macOS의 Command (⌘), Windows/Linux의 Ctrl로 개별 항목을 토글하고 Shift로 최근 기준점부터 연속 범위를 선택합니다. 선택된 항목을 드래그하면 원래 표시 순서로 함께 이동하며 change의 itemIds에서 전체 항목을 확인할 수 있습니다. 보조 마우스 버튼은 선택을 바꾸지 않습니다. 활성화된 다중 선택 항목의 Ctrl 컨텍스트 메뉴만 억제하며, 일반 우클릭·무시 대상 컨트롤·Host 슬롯의 기본 메뉴는 유지합니다.

handle을 설정하면 항목 선택과 Ctrl 메뉴 억제에도 같은 입력 범위를 적용합니다. Playground에서는 핸들을 보조키와 함께 클릭하여 선택하고, 본문은 텍스트 선택과 복사에 사용합니다. 본문을 선택해도 기존 다중 선택 상태는 유지됩니다.

0.1.3부터 selectedClass를 변경할 때 이전 선택 클래스를 제거합니다. 영역 등록 해제나 scope 파괴 시 라이브러리의 선택 표시와 범위 기준점을 정리하며, 같은 영역을 다시 등록하면 빈 선택 상태로 시작합니다. 관련 없는 CSS 클래스와 브라우저 텍스트 선택은 유지합니다.

Playground의 초기화 버튼은 네 어댑터 모두에서 예제를 복원하고 선택 ID·표시와 Shift 범위 기준점을 지웁니다. 초기화 후 Shift+Review를 클릭하면 Review만 선택됩니다. 일반적인 제어 상태 갱신은 선택을 초기화하지 않으므로 배열 교체만으로는 선택 상태까지 초기화되지 않습니다. Playground는 관련 sortable 등록을 명시적으로 다시 생성합니다. 공개 reset() API를 추가한 것은 아닙니다.

transitions Playground에서 Build 선택 → 초기화 → Shift+Review 선택 → Review만 맨 앞으로 이동하는 흐름을 확인합니다. 현재 GIF에는 이 초기화 장면이 없습니다.

swapThreshold(0–1)는 포인터가 대상 카드의 어디까지 들어와야 정렬 순서가 바뀌는지 결정합니다. 드래그 시작에 필요한 이동 거리인 activationDistance와는 별개입니다. Playground에서 Design을 위쪽 Research로 이동하면 색칠된 상단 영역이 Research 앞으로 삽입되는 범위를 표시합니다. 반전을 끈 경우 0.2는 상단 60%, 0.8은 90%이며, invertSwap을 켜면 각각 40%, 10%가 됩니다. 아래로 이동할 때는 반대 방향을 적용합니다. 컨트롤을 바꾸면 설명과 영역 표시가 함께 갱신됩니다.

direction="grid"는 두 축을 사용하며 드래그한 카드의 중심이 현재 Placeholder 위에 있는 동안 목적지를 유지합니다. 일반 그리드 정렬은 항목을 삽입하면서 사이의 셀을 밀어냅니다. swap은 같은 Area의 드래그 항목과 강조된 대상 항목만 교환하며 나머지 위치는 유지하고 swapItemId를 내보냅니다. 스왑 그리드는 direction="grid"와 swap을 조합한 예제입니다.

Playground는 /examples/transitions/react 아래의 transitions, thresholds, swap, grid, swap-grid 경로에서 확인합니다.

예를 들어 [A, B, C, D]에서 A를 C 위치로 이동하면 일반 Grid는 [B, C, A, D], Swap Grid는 [C, B, A, D]가 됩니다.

그리드 삽입은 핸들을 잡은 위치와 관계없이 드래그한 카드의 화면상 중심을 기준으로 판정합니다. 카드 한 칸만큼 이동하면 해당 슬롯으로 이동하며, 다른 행의 같은 열도 동일하게 처리합니다. 영역 수락과 swap 대상은 실제 포인터가 가리키는 요소로 계속 판정합니다.


실행 가능한 대표 예제 · 배포 기준 원본 가이드