import clsx from 'clsx'; import { Ban, ChevronLeft, ChevronRight, CircleDot, GitMerge, GitPullRequest, GitPullRequestClosed, LoaderCircle, UserRound, } from 'lucide-solid'; import { A } from '@solidjs/router'; import { Match, Show, Switch, createEffect, createMemo, createSignal, type Component } from 'solid-js'; import { createQuery } from '@tanstack/solid-query'; import { resolveAvatarUrl } from '../lib/api/identity'; export const ToggleButton: Component<{ active: boolean; label: string; meta?: string; onClick: () => void; }> = (props) => ( ); export const PaginationControls: Component<{ basePath?: string; offset: number; limit: number; totalCount?: number; hasNext?: boolean; query?: Record; hrefForOffset?: (offset: number) => string; }> = (props) => { const safeLimit = createMemo(() => Math.max(1, props.limit)); const hasExactTotal = createMemo(() => typeof props.totalCount === 'number'); const lastOffset = createMemo(() => Math.floor(Math.max((props.totalCount ?? 0) - 1, 0) / safeLimit()) * safeLimit()); const previousOffset = createMemo(() => Math.max(0, props.offset - safeLimit())); const nextOffset = createMemo(() => props.offset + safeLimit()); const hasNextPage = createMemo(() => hasExactTotal() ? nextOffset() < (props.totalCount ?? 0) : Boolean(props.hasNext), ); const pageNumber = (offset: number) => Math.floor(offset / safeLimit()) + 1; const hrefForOffset = (offset: number) => { if (props.hrefForOffset) { return props.hrefForOffset(Math.max(0, offset)); } const params = new URLSearchParams(); for (const [key, value] of Object.entries(props.query ?? {})) { if (value) { params.set(key, value); } } params.set('offset', String(Math.max(0, offset))); params.set('limit', String(safeLimit())); return `${props.basePath ?? ''}?${params.toString()}`; }; const showNextNumber = createMemo(() => hasExactTotal() ? nextOffset() < lastOffset() : hasNextPage()); const showGap = createMemo(() => hasExactTotal() && nextOffset() < (props.totalCount ?? 0) - safeLimit() * 2); const linkClass = 'flex items-center gap-1 no-underline hover:no-underline dark:text-white text-sm'; return ( 0 || hasNextPage()}>
0} fallback={ prev } > prev 0}> 1 0}> {pageNumber(previousOffset())} {pageNumber(props.offset)} {pageNumber(nextOffset())} -- {pageNumber(lastOffset())} next } > next
); }; export const LoadingState: Component<{ label: string }> = (props) => (
{props.label}
); export const SkeletonBlock: Component<{ class?: string }> = (props) => (