File size: 1,397 Bytes
91677d6
 
 
15d8696
 
 
91677d6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8899818
95e3d2a
91677d6
 
 
 
 
15d8696
91677d6
15d8696
91677d6
15d8696
91677d6
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<script lang="ts">
	import { Button } from '$lib/components/ui/button';
	import { cn } from '$lib/utils';
	import CaretUpIcon from 'phosphor-svelte/lib/CaretUpIcon';
	import CaretDownIcon from 'phosphor-svelte/lib/CaretDownIcon';
	import CaretUpDownIcon from 'phosphor-svelte/lib/CaretUpDownIcon';

	// `column` comes from the TanStack header context. Its `TData/TValue` generics
	// vary across columns, so we type it permissively here and only touch the
	// methods we actually use.
	interface SortableColumn {
		getIsSorted(): false | 'asc' | 'desc';
		toggleSorting(desc?: boolean): void;
	}

	interface Props {
		column: SortableColumn;
		label: string;
		align?: 'start' | 'end';
		class?: string;
	}

	let { column, label, align = 'start', class: className }: Props = $props();
	const sort = $derived(column.getIsSorted());
</script>

<Button
	variant="ghost"
	size="sm"
	onclick={() => column.toggleSorting(sort === 'asc')}
	class={cn(
		'-ml-2 h-7 px-2 text-[0.7rem] font-medium tracking-wide text-muted-foreground uppercase hover:text-foreground',
		align === 'end' && '-mr-2 ml-0 w-full justify-end',
		className
	)}
>
	{label}
	{#if sort === 'asc'}
		<CaretUpIcon size={12} weight="bold" class="ml-1" />
	{:else if sort === 'desc'}
		<CaretDownIcon size={12} weight="bold" class="ml-1" />
	{:else}
		<CaretUpDownIcon size={12} weight="bold" class="ml-1 opacity-60" />
	{/if}
</Button>