obsidian-book-tracker/src/ui/components/BookCover.svelte

106 lines
1.7 KiB
Svelte

<script lang="ts">
import type { BookMetadata } from "@src/types";
import { getAppContext } from "@ui/stores/app";
type NumberUnit =
| "cap"
| "ch"
| "em"
| "ex"
| "ic"
| "lh"
| "rcap"
| "rch"
| "rem"
| "rex"
| "ric"
| "rlh"
| "vh"
| "vw"
| "vmax"
| "vmin"
| "vb"
| "vi"
| "cqw"
| "cqh"
| "cqi"
| "cqb"
| "cqmin"
| "cqmax"
| "px"
| "cm"
| "mm"
| "Q"
| "in"
| "pc"
| "pt"
| "%";
interface Props {
book: BookMetadata;
size?: "fill" | number | `${number}${NumberUnit}`;
}
const { book, size = 500 }: Props = $props();
const app = getAppContext();
const coverPath = $derived(book.localCoverPath);
const coverFile = $derived(app.vault.getFileByPath(coverPath));
const coverSrc = $derived(
coverFile ? app.vault.getResourcePath(coverFile) : "",
);
const coverAlt = $derived(book.title);
const coverWidth = $derived.by(() => {
if (size === "fill") {
return "100%";
} else if (typeof size === "string") {
return size;
} else if (typeof size === "number") {
return `${size}px`;
} else {
return undefined;
}
});
const coverHeight = $derived.by(() => {
if (size === "fill") {
return "100%";
} else {
return undefined;
}
});
</script>
<div
class="book-cover"
style:--book-cover-width={coverWidth}
style:--book-cover-height={coverHeight}
>
<img src={coverSrc} alt={coverAlt} />
</div>
<style lang="scss">
:global(:root) {
--book-cover-aspect-ratio: 2 / 3;
}
.book-cover {
&,
& img {
width: var(--book-cover-width);
height: var(
--book-cover-height,
calc(var(--book-cover-width) / (var(--book-cover-aspect-ratio)))
);
}
img {
border-radius: var(--radius-l);
object-fit: cover;
object-position: center;
}
}
</style>