~ knotless Search/
↑↓ move↵ open⇧↵ all results

johnandersen777.bsky.social/knotless

git that lives in your Atmosphere account

Forked from chadtmiller.com/knotless

0
0
89 lines · 2.4 KB Raw History
<script lang="ts">
	import { repoHref, urlPath } from '#lib/format.ts';
	import Icon from '#lib/atoms/Icon.svelte';
	/** The revision shown, opening to every branch, and, given `tags`, every tag, each linked to the same `view` of `path` on it. */
	let {
		authority,
		name,
		rev,
		view,
		path,
		branches,
		head,
		tags
	}: {
		authority: string;
		name: string;
		rev: string;
		view: string;
		path: string;
		branches: string[];
		head: string;
		tags?: string[];
	} = $props();
	const pinned = $derived(/^([0-9a-f]{40}|[0-9a-f]{64})$/i.test(rev));
	const tagged = $derived(!branches.includes(rev) && !!tags?.includes(rev));
	let open = $state(false);
	let filter = $state('');
	let showTags = $state(false);
	// Opened on a tag, it opens on the tags.
	$effect(() => {
		if (open) showTags = tagged;
	});
	const kind = $derived(showTags ? 'tag' : 'branch');
	const shown = $derived(
		(showTags ? (tags ?? []) : branches).filter((b) =>
			b.toLowerCase().includes(filter.trim().toLowerCase())
		)
	);
	const href = (ref: string) =>
		repoHref(authority, name, `/${view}/${urlPath(ref)}${path ? `/${urlPath(path)}` : ''}`);
</script>

<details class="popover branch-menu" bind:open>
	<summary class="branch" title={rev}
		><Icon name={tagged ? 'tag' : 'branch'} /><span>{pinned ? rev.slice(0, 7) : rev}</span><Icon
			name="caret"
		/></summary
	>
	<div class="menu">
		<div class="menu-head">{tags ? 'Switch branches or tags' : 'Switch branches'}</div>
		<input
			type="search"
			placeholder="Find a {kind}…"
			aria-label="Find a {kind}"
			bind:value={filter}
		/>
		{#if tags}
			<div class="md-tabs ref-tabs" role="tablist" aria-label="Branches or tags">
				<button
					type="button"
					role="tab"
					aria-selected={!showTags}
					onclick={() => (showTags = false)}><Icon name="branch" />Branches</button
				>
				<button type="button" role="tab" aria-selected={showTags} onclick={() => (showTags = true)}
					><Icon name="tag" />Tags</button
				>
			</div>
		{/if}
		{#if shown.length}
			<ul>
				{#each shown as b (b)}
					<li>
						<a
							href={href(b)}
							aria-current={b === rev ? 'true' : undefined}
							onclick={() => (open = false)}
							><Icon name="check" /><span class="name">{b}</span>{#if !showTags && b === head}<span
									class="count">Default</span
								>{/if}</a
						>
					</li>
				{/each}
			</ul>
		{:else}
			<div class="none">{showTags && !tags?.length ? 'No tags yet' : 'Nothing to show'}</div>
		{/if}
	</div>
</details>