Skip to content

Commit c170393

Browse files
feat(side-panel): wire back show prereleases checkbox
1 parent 9181652 commit c170393

File tree

3 files changed

+59
-4
lines changed

3 files changed

+59
-4
lines changed

src/lib/persisted.svelte.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
type Primitive = string | null | symbol | boolean | number | undefined | bigint;
2+
3+
function isPrimitive(val: unknown): val is Primitive {
4+
return val !== Object(val) || val === null;
5+
}
6+
7+
/**
8+
* A `localStorage` wrapper, runes edition.
9+
*
10+
* @param key the `localStorage` key to use
11+
* @param initial the initial value if it doesn't already exist in `localStorage`
12+
* @returns the (one-way) rune, updating `localStorage` on change
13+
*
14+
* @see {@link https://x.com/puruvjdev/status/1787037268143689894/photo/1|Original idea}
15+
*/
16+
export function persisted<T>(key: string, initial: T) {
17+
const existing = localStorage.getItem(key);
18+
19+
const primitive = isPrimitive(initial);
20+
const parsedValue = existing ? (JSON.parse(existing) as T) : initial;
21+
22+
const state = $state<T extends Primitive ? { value: T } : T>(
23+
// @ts-expect-error type conflict between object version and raw version
24+
primitive ? { value: parsedValue } : parsedValue
25+
);
26+
27+
$effect.root(() => {
28+
$effect(() => {
29+
localStorage.setItem(key, JSON.stringify(primitive ? (state as { value: T }).value : state));
30+
});
31+
});
32+
33+
return state;
34+
}

src/routes/package/[...package]/+page.svelte

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
)
2222
.sort((a, b) => semver.compare(a.cleanVersion, b.cleanVersion))[0]
2323
);
24+
let showPrereleases = $state(true);
2425
</script>
2526

2627
{#snippet loading()}
@@ -52,6 +53,9 @@
5253
{#await Promise.resolve()}
5354
{@render loading()}
5455
{:then}
56+
{@const displayableReleases = data.releases.filter(release =>
57+
showPrereleases ? true : !release.prerelease
58+
)}
5559
<div class="my-8">
5660
<h1 class="text-5xl font-semibold text-primary">{data.currentPackage.pkg.name}</h1>
5761
<h2 class="text-xl text-muted-foreground">
@@ -64,15 +68,15 @@
6468
<div class="flex gap-8">
6569
<Accordion.Root
6670
type="multiple"
67-
value={data.releases
71+
value={displayableReleases
6872
// Only expand releases that are less than a week old
6973
.filter(({ created_at }) => {
7074
return new Date(created_at).getTime() > new Date().getTime() - 1000 * 60 * 60 * 24 * 7;
7175
})
7276
.map(({ id }) => id.toString())}
7377
class="w-full"
7478
>
75-
{#each data.releases as release, index (release.id)}
79+
{#each displayableReleases as release, index (release.id)}
7680
{@const semVersion = semver.coerce(release.cleanVersion)}
7781
{@const isMajorRelease =
7882
!release.prerelease &&
@@ -102,6 +106,7 @@
102106
packageName={data.currentPackage.pkg.name}
103107
allPackages={data.displayablePackages}
104108
class="h-fit w-[35rem]"
109+
bind:showPrereleases
105110
/>
106111
</div>
107112
{/await}

src/routes/package/[...package]/SidePanel.svelte

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import { page } from "$app/state";
44
import { ChevronRight } from "@lucide/svelte";
55
import type { CategorizedPackage } from "$lib/server/package-discoverer";
6+
import { persisted } from "$lib/persisted.svelte";
67
import { cn } from "$lib/utils";
78
import { Checkbox } from "$lib/components/ui/checkbox";
89
import { Label } from "$lib/components/ui/label";
@@ -17,10 +18,21 @@
1718
"dataFilter" | "metadataFromTag" | "changelogContentsReplacer"
1819
>[];
1920
})[];
21+
showPrereleases?: boolean;
2022
class?: ClassValue;
2123
};
22-
let { packageName = "", allPackages = [], class: className }: Props = $props();
24+
let {
25+
packageName = "",
26+
allPackages = [],
27+
showPrereleases = $bindable(true),
28+
class: className
29+
}: Props = $props();
2330
let id = $props.id();
31+
32+
let storedPrereleaseState = persisted(`show-${packageName}-prereleases`, showPrereleases);
33+
$effect(() => {
34+
storedPrereleaseState.value = showPrereleases;
35+
});
2436
</script>
2537

2638
<div class={cn("flex flex-col *:shadow-lg *:shadow-black", className)}>
@@ -89,7 +101,11 @@
89101
<div
90102
class="-mt-2 flex items-center gap-2 rounded-b-xl border-x border-b bg-card px-4 pt-5 pb-2.5"
91103
>
92-
<Checkbox id="beta-releases-{id}" aria-labelledby="beta-releases-label-{id}" />
104+
<Checkbox
105+
id="beta-releases-{id}"
106+
aria-labelledby="beta-releases-label-{id}"
107+
bind:checked={showPrereleases}
108+
/>
93109
<Label
94110
id="beta-releases-label-{id}"
95111
for="beta-releases-{id}"

0 commit comments

Comments
 (0)