This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

core / web / src / lib / components / repo / DiffFileCard.svelte
2.9 kB 100 lines
1<script lang="ts"> 2 import ArrowRight from "$icon/arrow-right"; 3 import ChevronDown from "$icon/chevron-down"; 4 import ChevronRight from "$icon/chevron-right"; 5 import Eye from "$icon/eye"; 6 import type { DiffFile, DiffStat } from "$lib/api/diff"; 7 import type { FileDiffMetadata } from "@pierre/diffs"; 8 import Button from "$lib/components/ui/Button.svelte"; 9 import type { Snippet } from "svelte"; 10 import DiffStatPill from "./DiffStatPill.svelte"; 11 import PierreDiff from "./PierreDiff.svelte"; 12 import type { DiffStyle } from "./pierre"; 13 14 interface Props { 15 file: DiffFile; 16 // resolved display path (new name, falling back to old) 17 name: string; 18 stat: DiffStat; 19 // pierre's structured diff, absent for binaries 20 fileDiff?: FileDiffMetadata; 21 // server-prerendered shadow dom for fileDiff 22 prerenderedHTML?: string; 23 // side-by-side or stacked 24 diffStyle?: DiffStyle; 25 // blob route for the "view file" link, hidden when absent 26 blobUrl?: string; 27 open?: boolean; 28 // review-button slot on the file header (pull pages) 29 headerActions?: Snippet<[DiffFile]>; 30 } 31 32 let { 33 file, 34 name, 35 stat, 36 fileDiff, 37 prerenderedHTML, 38 diffStyle = "unified", 39 blobUrl, 40 open = $bindable(true), 41 headerActions 42 }: Props = $props(); 43</script> 44 45<!-- the summary sticks below the topbar and needs a solid bg 46 or the diff shows through. z-[5] keeps it under the z-10 topbar it 47 shares its sticky band with --> 48<details 49 bind:open 50 id="file-{name}" 51 class="group mx-auto w-full rounded border border-border-default bg-background-default" 52> 53 <summary 54 class="sticky top-[calc(3rem+env(safe-area-inset-top))] z-5 cursor-pointer list-none rounded bg-background-default group-open:rounded-b-none group-open:border-b group-open:border-border-default" 55 > 56 <div class="flex cursor-pointer justify-between"> 57 <div class="flex items-center gap-2 overflow-x-auto p-2"> 58 {#if open} 59 <ChevronDown class="size-4" /> 60 {:else} 61 <ChevronRight class="size-4" /> 62 {/if} 63 <DiffStatPill {stat} /> 64 65 <div class="flex items-center gap-2 overflow-x-auto"> 66 {#if file.name.old && file.name.new && file.name.old !== file.name.new} 67 {file.name.old} 68 <ArrowRight class="size-4" /> 69 {file.name.new} 70 {:else} 71 {name} 72 {/if} 73 </div> 74 </div> 75 <div class="flex items-center pr-1"> 76 {#if blobUrl} 77 <Button 78 href={blobUrl as "/"} 79 variant="ghost" 80 size="sm" 81 icon={Eye} 82 class="hidden md:inline-flex" 83 onclick={(event) => event.stopPropagation()} 84 > 85 View file 86 </Button> 87 {/if} 88 {@render headerActions?.(file)} 89 </div> 90 </div> 91 </summary> 92 93 {#if file.is_binary} 94 <p class="p-4 text-center text-foreground-placeholder"> 95 This is a binary file and will not be displayed. 96 </p> 97 {:else} 98 <PierreDiff files={fileDiff ? [fileDiff] : []} {diffStyle} prerenderedHTML={[prerenderedHTML]} /> 99 {/if} 100</details>