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

johnandersen777.bsky.social/knotless

git that lives in your Atmosphere account

Forked from chadtmiller.com/knotless

0
0
59 lines · 1.9 KB Raw History
<script lang="ts">
	import type * as repo from '#lib/lexicons/dev/knotless/repo.ts';
	import type { Snippet } from 'svelte';
	import Icon from '#lib/atoms/Icon.svelte';
	/**
	 * A menu of the `labels` the one looking may put on a pull or an issue,
	 * those it carries (`on`, by name) ticked: choosing one tells `toggle`
	 * to put it on, or take it off, its tick turning while it does. With
	 * `gear`, it opens from a gear beside a heading that names it, as a
	 * sidebar's does, rather than from its name; with `summary`, from what
	 * that draws, as a fact of a pull or issue opens from the labels it
	 * carries.
	 */
	let {
		labels,
		on,
		toggle,
		gear = false,
		summary
	}: {
		labels: repo.Label[];
		on: string[];
		toggle: (name: string, removed: boolean) => Promise<unknown>;
		gear?: boolean;
		summary?: Snippet;
	} = $props();
	let busy = $state('');
	async function pick(name: string, removed: boolean) {
		busy = name;
		await toggle(name, removed);
		busy = '';
	}
	const hex = (color?: string) => (/^#[0-9a-fA-F]{6}$/.test(color ?? '') ? color : undefined);
</script>

<details class="popover filter-menu label-menu" data-held={busy || undefined}>
	{#if summary}<summary title="Choose labels">{@render summary()}</summary>{:else if gear}<summary
			aria-label="Choose labels"
			title="Choose labels"><Icon name="gear" /></summary
		>{:else}<summary>Labels<Icon name="caret" /></summary>{/if}
	<div class="menu">
		<div class="menu-head">Apply labels</div>
		{#each labels as l (l.name)}
			{@const ticked = on.includes(l.name)}
			<button
				class="menu-item"
				type="button"
				aria-pressed={ticked}
				disabled={!!busy}
				onclick={() => pick(l.name, ticked)}
				><span class="tick"
					>{#if busy === l.name}<span class="spinner"></span>{:else if ticked}<Icon
							name="check"
						/>{/if}</span
				><span class="dot" style:--label={hex(l.color)}></span><span>{l.name}</span></button
			>
		{/each}
	</div>
</details>