mirror of
https://github.com/pesde-pkg/pesde.git
synced 2025-05-04 10:33:47 +01:00
feat(website): better package layout
This commit is contained in:
parent
b7493438d4
commit
4f02a8db2a
7 changed files with 83 additions and 46 deletions
68
website/src/routes/packages/[scope]/[name]/+layout.svelte
Normal file
68
website/src/routes/packages/[scope]/[name]/+layout.svelte
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import { formatDistanceToNow } from "date-fns"
|
||||||
|
import Tab from "./Tab.svelte"
|
||||||
|
import { page } from "$app/stores"
|
||||||
|
import { onMount, setContext, untrack } from "svelte"
|
||||||
|
|
||||||
|
let { children, data } = $props()
|
||||||
|
|
||||||
|
const [scope, name] = $derived(data.pkg.name.split("/"))
|
||||||
|
|
||||||
|
let currentPkg = $state(data.pkg)
|
||||||
|
|
||||||
|
setContext("currentPkg", {
|
||||||
|
get value() {
|
||||||
|
return currentPkg
|
||||||
|
},
|
||||||
|
set value(v) {
|
||||||
|
currentPkg = v
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const getReadme = () => {
|
||||||
|
console.log($page.params)
|
||||||
|
if ("target" in $page.params) {
|
||||||
|
return `${$page.params.version}/${$page.params.target}`
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
const pkgVersion = $derived(currentPkg.version)
|
||||||
|
const pkgDescription = $derived(currentPkg.description)
|
||||||
|
|
||||||
|
let pkgDate = $state<null | string>(null)
|
||||||
|
let readme = $state(getReadme())
|
||||||
|
|
||||||
|
$effect(() => {
|
||||||
|
pkgDate = formatDistanceToNow(new Date(currentPkg.published_at), { addSuffix: true })
|
||||||
|
readme = untrack(getReadme)
|
||||||
|
})
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
return page.subscribe((page) => {
|
||||||
|
if (pkgDate === null || page.params.target !== undefined) {
|
||||||
|
currentPkg = data.pkg
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="mx-auto max-w-prose px-4 py-16 lg:max-w-screen-lg">
|
||||||
|
<h1 class="text-3xl font-bold">
|
||||||
|
<span class="text-heading">{scope}/</span><span class="text-light">{name}</span>
|
||||||
|
</h1>
|
||||||
|
<div class="mb-2 font-semibold text-primary" class:invisible={pkgDate === null}>
|
||||||
|
v{pkgVersion} ·
|
||||||
|
<time datetime={data.pkg.published_at} title={new Date(data.pkg.published_at).toLocaleString()}>
|
||||||
|
published {pkgDate ?? "..."}
|
||||||
|
</time>
|
||||||
|
</div>
|
||||||
|
<p class="mb-6 max-w-prose">{pkgDescription}</p>
|
||||||
|
|
||||||
|
<nav class="flex w-full border-b-2">
|
||||||
|
<Tab tab={readme}>Readme</Tab>
|
||||||
|
<Tab tab="versions">Versions</Tab>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
{@render children()}
|
||||||
|
</div>
|
|
@ -11,10 +11,6 @@
|
||||||
|
|
||||||
const basePath = $derived.by(() => {
|
const basePath = $derived.by(() => {
|
||||||
const { scope, name } = $page.params
|
const { scope, name } = $page.params
|
||||||
if ("target" in $page.params) {
|
|
||||||
const { version, target } = $page.params
|
|
||||||
return `/packages/${scope}/${name}/${version}/${target}`
|
|
||||||
}
|
|
||||||
return `/packages/${scope}/${name}`
|
return `/packages/${scope}/${name}`
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { formatDistanceToNow } from "date-fns"
|
|
||||||
import { BinaryIcon, Icon, LibraryIcon } from "lucide-svelte"
|
import { BinaryIcon, Icon, LibraryIcon } from "lucide-svelte"
|
||||||
import Tab from "./Tab.svelte"
|
|
||||||
import { page } from "$app/stores"
|
import { page } from "$app/stores"
|
||||||
import type { TargetInfo } from "$lib/registry-api"
|
import type { TargetInfo } from "$lib/registry-api"
|
||||||
import type { ComponentType } from "svelte"
|
import type { ComponentType } from "svelte"
|
||||||
|
@ -11,13 +9,13 @@
|
||||||
|
|
||||||
let { children, data } = $props()
|
let { children, data } = $props()
|
||||||
|
|
||||||
const [scope, name] = $derived(data.pkg.name.split("/"))
|
|
||||||
|
|
||||||
const installCommand = $derived(`pesde add ${data.pkg.name}`)
|
const installCommand = $derived(`pesde add ${data.pkg.name}`)
|
||||||
const xCommand = $derived(`pesde x ${data.pkg.name}`)
|
const xCommand = $derived(`pesde x ${data.pkg.name}`)
|
||||||
|
|
||||||
const defaultTarget = $derived(
|
const defaultTarget = $derived(
|
||||||
"target" in $page.params ? $page.params.target : data.pkg.targets[0].kind,
|
"target" in $page.params && $page.params.target !== "any"
|
||||||
|
? $page.params.target
|
||||||
|
: data.pkg.targets[0].kind,
|
||||||
)
|
)
|
||||||
const currentTarget = $derived(data.pkg.targets.find((target) => target.kind === defaultTarget))
|
const currentTarget = $derived(data.pkg.targets.find((target) => target.kind === defaultTarget))
|
||||||
|
|
||||||
|
@ -42,39 +40,18 @@
|
||||||
lib: LibraryIcon,
|
lib: LibraryIcon,
|
||||||
bin: BinaryIcon,
|
bin: BinaryIcon,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const exportEntries = $derived(
|
||||||
|
Object.entries(exportNames).filter(([key]) => !!currentTarget?.[key as keyof TargetInfo]),
|
||||||
|
)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="mx-auto flex max-w-prose flex-col px-4 py-16 lg:max-w-screen-lg lg:flex-row">
|
<div class="flex flex-col lg:flex-row">
|
||||||
<div class="flex-grow lg:pr-4">
|
<div class="lg:pr-4">
|
||||||
<h1 class="text-3xl font-bold">
|
|
||||||
<span class="text-heading">{scope}/</span><span class="text-light">{name}</span>
|
|
||||||
</h1>
|
|
||||||
<div class="mb-2 font-semibold text-primary">
|
|
||||||
v{data.pkg.version} ·
|
|
||||||
<time
|
|
||||||
datetime={data.pkg.published_at}
|
|
||||||
title={new Date(data.pkg.published_at).toLocaleString()}
|
|
||||||
>
|
|
||||||
published {formatDistanceToNow(new Date(data.pkg.published_at), {
|
|
||||||
addSuffix: true,
|
|
||||||
})}
|
|
||||||
</time>
|
|
||||||
</div>
|
|
||||||
<p class="mb-6 max-w-prose">{data.pkg.description}</p>
|
|
||||||
|
|
||||||
<div class="mb-12 lg:hidden">
|
|
||||||
<TargetSelector id="target-selector-sidebar" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<nav class="flex w-full border-b-2">
|
|
||||||
<Tab tab="">Readme</Tab>
|
|
||||||
<Tab tab="versions">Versions</Tab>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
{@render children()}
|
{@render children()}
|
||||||
</div>
|
</div>
|
||||||
<aside
|
<aside
|
||||||
class="w-full flex-shrink-0 border-t pt-16 lg:ml-auto lg:max-w-[22rem] lg:border-l lg:border-t-0 lg:pl-4 lg:pt-0"
|
class="w-full flex-shrink-0 border-t pt-16 lg:ml-auto lg:max-w-[22rem] lg:border-l lg:border-t-0 lg:pl-4 lg:pt-6"
|
||||||
>
|
>
|
||||||
<h2 class="mb-1 text-lg font-semibold text-heading">Install</h2>
|
<h2 class="mb-1 text-lg font-semibold text-heading">Install</h2>
|
||||||
<Command command={installCommand} class="mb-4" />
|
<Command command={installCommand} class="mb-4" />
|
||||||
|
@ -111,7 +88,7 @@
|
||||||
|
|
||||||
<h2 class="mb-1 text-lg font-semibold text-heading">Exports</h2>
|
<h2 class="mb-1 text-lg font-semibold text-heading">Exports</h2>
|
||||||
<ul class="mb-6 space-y-0.5">
|
<ul class="mb-6 space-y-0.5">
|
||||||
{#each Object.entries(exportNames).filter(([key]) => !!currentTarget?.[key as keyof TargetInfo]) as [exportKey, exportName]}
|
{#each exportEntries as [exportKey, exportName]}
|
||||||
{@const Icon = exportIcons[exportKey as keyof TargetInfo]}
|
{@const Icon = exportIcons[exportKey as keyof TargetInfo]}
|
||||||
<li class="flex items-center">
|
<li class="flex items-center">
|
||||||
<Icon class="mr-2 size-5 text-primary" />
|
<Icon class="mr-2 size-5 text-primary" />
|
||||||
|
|
|
@ -6,7 +6,9 @@
|
||||||
const { id }: { id: string } = $props()
|
const { id }: { id: string } = $props()
|
||||||
|
|
||||||
const defaultTarget = $derived(
|
const defaultTarget = $derived(
|
||||||
"target" in $page.params ? $page.params.target : $page.data.pkg.targets[0].kind,
|
"target" in $page.params && $page.params.target !== "any"
|
||||||
|
? $page.params.target
|
||||||
|
: $page.data.pkg.targets[0].kind,
|
||||||
)
|
)
|
||||||
|
|
||||||
const basePath = $derived.by(() => {
|
const basePath = $derived.by(() => {
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { page } from "$app/stores"
|
|
||||||
import { formatDistanceToNow } from "date-fns"
|
import { formatDistanceToNow } from "date-fns"
|
||||||
|
|
||||||
const { data } = $props()
|
const { data } = $props()
|
||||||
|
@ -8,15 +7,10 @@
|
||||||
<div class="space-y-4 py-4">
|
<div class="space-y-4 py-4">
|
||||||
{#each data.versions as pkg, index}
|
{#each data.versions as pkg, index}
|
||||||
{@const isLatest = index === 0}
|
{@const isLatest = index === 0}
|
||||||
{@const isCurrent = $page.params.version === pkg.version}
|
|
||||||
|
|
||||||
<article
|
<article
|
||||||
class={`relative overflow-hidden rounded bg-card px-5 py-4 transition hover:bg-card-hover ${
|
class={`relative overflow-hidden rounded bg-card px-5 py-4 transition hover:bg-card-hover ${
|
||||||
isLatest
|
isLatest ? "ring-2 ring-inset ring-primary" : ""
|
||||||
? "ring-2 ring-inset ring-primary"
|
|
||||||
: isCurrent
|
|
||||||
? "ring-2 ring-inset ring-body/50"
|
|
||||||
: ""
|
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<h2 class="font-semibold text-heading">
|
<h2 class="font-semibold text-heading">
|
Loading…
Add table
Reference in a new issue