<script lang="ts">
import ExternalLink from "$icon/external-link";
import FoldVertical from "$icon/fold-vertical";
import UnfoldVertical from "$icon/unfold-vertical";
import { MediaQuery } from "svelte/reactivity";
import Button from "#lib/components/ui/Button.svelte";
import CopyButton from "#lib/components/ui/CopyButton.svelte";
import { plural } from "#lib/format.ts";
interface Props {
block: HTMLElement;
code: string;
lines: number;
}
let { block, code, lines }: Props = $props();
const narrow = new MediaQuery("width < 40rem");
let expanded = $state(false);
let raw: string | undefined;
$effect(() => () => {
if (raw) URL.revokeObjectURL(raw);
});
const toggle = () => {
expanded = !expanded;
block.toggleAttribute("data-expanded", expanded);
if (!expanded && block.getBoundingClientRect().top < 0) block.scrollIntoView();
};
const openRaw = () => {
raw ??= URL.createObjectURL(new Blob([code], { type: "text/plain;charset=utf-8" }));
window.open(raw, "_blank");
};
const toggleLabel = $derived(expanded ? "Collapse code" : "Expand code");
</script>
{#snippet toggleText()}{toggleLabel}{/snippet}
<div class="flex flex-wrap items-center justify-between gap-xs">
<div class="flex items-center gap-sm">
<Button
icon={expanded ? FoldVertical : UnfoldVertical}
aria-label={toggleLabel}
onclick={toggle}
children={narrow.current ? undefined : toggleText}
variant="ghost"
/>
<span class="typography-monospace-small text-foreground-muted">
{lines}
{plural(lines, "line", "lines")}
</span>
</div>
<div class="flex flex-row items-center gap-xs *:hit-area-x-1.5 *:overflow-visible">
<CopyButton
value={code}
variant="ghost"
label="Copy to clipboard"
showLabel={false}
size="regular"
/>
<Button
icon={ExternalLink}
iconSide="right"
aria-label="Open raw in new tab"
onclick={openRaw}
variant="ghost"
/>
</div>
</div>