useSortable Composable
Reactive array sorting with multiple sort criteria and direction control
Code
import { ref, computed, type Ref } from 'vue';
type SortDirection = 'asc' | 'desc';
type SortKey<T> = keyof T | ((item: T) => any);
interface SortConfig<T> {
key: SortKey<T>;
direction: SortDirection;
}
export function useSortable<T>(items: Ref<T[]>) {
const sortConfig = ref<SortConfig<T> | null>(null);
// Get value from key or function
const getValue = (item: T, key: SortKey<T>) => {
__TOKEN_41__ (typeof key === 'function') {
return key(item);
}
return item[key];
};
// Sorted items computed property
const sortedItems = computed(() => {
__TOKEN_46__ (!sortConfig.value || items.value.length === 0) {
return [...items.value];
}
const { key, direction } = sortConfig.value;
return [...items.value].sort((a, b) => {
const valueA = getValue(a, key);
const valueB = getValue(b, key);
// Handle different types
__TOKEN_52__ (typeof valueA === 'string' && typeof valueB === 'string') {
return direction === 'asc'
? valueA.localeCompare(valueB)
: valueB.localeCompare(valueA);
}
__TOKEN_56__ (typeof valueA === 'number' && typeof valueB === 'number') {
return direction === 'asc' ? valueA - valueB : valueB - valueA;
}
__TOKEN_60__ (valueA instanceof Date && valueB instanceof Date) {
return direction === 'asc' ? valueA.getTime() - valueB.getTime() : valueB.getTime() - valueA.getTime();
}
// Fallback for other types
return 0;
});
});
// Set sort configuration
const setSort = (key: SortKey<T>, direction?: SortDirection) => {
// Toggle direction if same key
__TOKEN_66__ (sortConfig.value?.key === key) {
sortConfig.value.direction = sortConfig.value.direction === 'asc' ? 'desc' : 'asc';
} else {
sortConfig.value = {
key,
direction: direction || 'asc'
};
}
};
// Reset sorting
const resetSort = () => {
sortConfig.value = null;
};
// Toggle sort direction for current key
const toggleSortDirection = () => {
__TOKEN_70__ (sortConfig.value) {
sortConfig.value.direction = sortConfig.value.direction === 'asc' ? 'desc' : 'asc';
}
};
return {
sortedItems,
sortConfig,
setSort,
resetSort,
toggleSortDirection
};
}
// Usage example
// const items = ref([{ name: 'Banana', price: 1.2 }, { name: 'Apple', price: 0.8 }]);
// const { sortedItems, setSort } = useSortable(items);
// setSort('name'); // Sort by name ascending
// setSort('price', 'desc'); // Sort by price descending