|
|
@@ -0,0 +1,77 @@
|
|
|
+import { computed, ref, watch, type Ref } from 'vue'
|
|
|
+
|
|
|
+export type SortOrder = 'asc' | 'desc'
|
|
|
+
|
|
|
+export function nextSortState(
|
|
|
+ currentField: string | null,
|
|
|
+ currentOrder: SortOrder | null,
|
|
|
+ prop: string,
|
|
|
+ order: SortOrder
|
|
|
+): { sortField: string | null; sortOrder: SortOrder | null } {
|
|
|
+ if (currentField === prop && currentOrder === order) {
|
|
|
+ return { sortField: null, sortOrder: null }
|
|
|
+ }
|
|
|
+ return { sortField: prop, sortOrder: order }
|
|
|
+}
|
|
|
+
|
|
|
+export function useColumnSort(options?: { onChange?: () => void }) {
|
|
|
+ const sortField = ref<string | null>(null)
|
|
|
+ const sortOrder = ref<SortOrder | null>(null)
|
|
|
+
|
|
|
+ const hasActiveSort = computed(() => Boolean(sortField.value && sortOrder.value))
|
|
|
+
|
|
|
+ function setSort(prop: string, order: SortOrder) {
|
|
|
+ const next = nextSortState(sortField.value, sortOrder.value, prop, order)
|
|
|
+ sortField.value = next.sortField
|
|
|
+ sortOrder.value = next.sortOrder
|
|
|
+ options?.onChange?.()
|
|
|
+ }
|
|
|
+
|
|
|
+ function clearSort() {
|
|
|
+ if (!sortField.value && !sortOrder.value) return
|
|
|
+ sortField.value = null
|
|
|
+ sortOrder.value = null
|
|
|
+ options?.onChange?.()
|
|
|
+ }
|
|
|
+
|
|
|
+ function isSortActive(prop: string, order?: SortOrder) {
|
|
|
+ if (!sortField.value || sortField.value !== prop) return false
|
|
|
+ if (order == null) return true
|
|
|
+ return sortOrder.value === order
|
|
|
+ }
|
|
|
+
|
|
|
+ function toQueryParams(): Record<string, string> {
|
|
|
+ if (!sortField.value || !sortOrder.value) return {}
|
|
|
+ return { sortField: sortField.value, sortOrder: sortOrder.value }
|
|
|
+ }
|
|
|
+
|
|
|
+ function onColumnHidden(prop: string) {
|
|
|
+ if (sortField.value === prop) clearSort()
|
|
|
+ }
|
|
|
+
|
|
|
+ function watchVisibleColumns(visibleProps: Ref<string[]>) {
|
|
|
+ watch(
|
|
|
+ visibleProps,
|
|
|
+ (next, prev) => {
|
|
|
+ if (!prev) return
|
|
|
+ const nextSet = new Set(next || [])
|
|
|
+ for (const p of prev) {
|
|
|
+ if (!nextSet.has(p)) onColumnHidden(p)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ { deep: true }
|
|
|
+ )
|
|
|
+ }
|
|
|
+
|
|
|
+ return {
|
|
|
+ sortField,
|
|
|
+ sortOrder,
|
|
|
+ hasActiveSort,
|
|
|
+ setSort,
|
|
|
+ clearSort,
|
|
|
+ isSortActive,
|
|
|
+ toQueryParams,
|
|
|
+ onColumnHidden,
|
|
|
+ watchVisibleColumns
|
|
|
+ }
|
|
|
+}
|