chore: migrate to svelte 5

This commit is contained in:
dusk 2025-02-22 12:50:34 +03:00
parent b08362f51e
commit ff558b3f97
Signed by: dusk
SSH Key Fingerprint: SHA256:Abmvag+juovVufZTxyWY8KcVgrznxvBjQpJesv071Aw
15 changed files with 184 additions and 77 deletions

BIN
bun.lockb

Binary file not shown.

View File

@ -14,7 +14,7 @@
"devDependencies": { "devDependencies": {
"@sveltejs/enhanced-img": "^0.3.10", "@sveltejs/enhanced-img": "^0.3.10",
"@sveltejs/kit": "^2.17.2", "@sveltejs/kit": "^2.17.2",
"@sveltejs/vite-plugin-svelte": "^3.1.2", "@sveltejs/vite-plugin-svelte": "^4.0.0",
"@tailwindcss/forms": "^0.5.10", "@tailwindcss/forms": "^0.5.10",
"@tailwindcss/typography": "^0.5.16", "@tailwindcss/typography": "^0.5.16",
"@types/eslint": "^9.6.1", "@types/eslint": "^9.6.1",
@ -28,9 +28,9 @@
"postcss": "^8.5.3", "postcss": "^8.5.3",
"prettier": "^3.5.2", "prettier": "^3.5.2",
"prettier-plugin-svelte": "^3.3.3", "prettier-plugin-svelte": "^3.3.3",
"svelte": "^4.2.19", "svelte": "^5.0.0",
"svelte-adapter-bun": "^0.5.2", "svelte-adapter-bun": "^0.5.2",
"svelte-check": "^3.8.6", "svelte-check": "^4.0.0",
"sveltekit-rate-limiter": "^0.6.1", "sveltekit-rate-limiter": "^0.6.1",
"tailwindcss": "^3.4.17", "tailwindcss": "^3.4.17",
"tslib": "^2.8.1", "tslib": "^2.8.1",

View File

@ -2,13 +2,23 @@
import Window from './window.svelte' import Window from './window.svelte'
import '../styles/app.css' import '../styles/app.css'
export let title interface Props {
export let sticky title: any;
export let prose = true sticky: any;
prose?: boolean;
children?: import('svelte').Snippet;
}
let {
title,
sticky,
prose = true,
children
}: Props = $props();
</script> </script>
<Window {title} {sticky}> <Window {title} {sticky}>
<div class="{prose ? "prose prose-ralsei leading-6 prose-ul:leading-5" : ""}"> <div class="{prose ? "prose prose-ralsei leading-6 prose-ul:leading-5" : ""}">
<slot /> {@render children?.()}
</div> </div>
</Window> </Window>

View File

@ -1,8 +1,17 @@
<script lang="ts"> <script lang="ts">
export let highlight: boolean = false; interface Props {
export let name: string; highlight?: boolean;
export let href: string; name: string;
export let iconUri: string; href: string;
iconUri: string;
}
let {
highlight = false,
name,
href,
iconUri
}: Props = $props();
</script> </script>
<a <a

View File

@ -1,4 +1,4 @@
<script context="module" lang="ts"> <script module lang="ts">
import type { Post } from "@skyware/bot"; import type { Post } from "@skyware/bot";
export interface OutgoingLink { export interface OutgoingLink {
@ -26,10 +26,19 @@
<script lang="ts"> <script lang="ts">
import Token from "./token.svelte"; import Token from "./token.svelte";
export let note: NoteData; interface Props {
export let isHighlighted = false; note: NoteData;
export let onlyContent = false; isHighlighted?: boolean;
export let showOutgoing = true; onlyContent?: boolean;
showOutgoing?: boolean;
}
let {
note,
isHighlighted = false,
onlyContent = false,
showOutgoing = true
}: Props = $props();
const renderDate = (timestamp: number) => { const renderDate = (timestamp: number) => {
return (new Date(timestamp)).toLocaleString("en-GB", { return (new Date(timestamp)).toLocaleString("en-GB", {

View File

@ -1,12 +1,23 @@
<script lang="ts"> <script lang="ts">
export let punct: boolean = false;
export let keywd: boolean = false;
export let funct: boolean = false;
export let str: boolean = false;
export let small: boolean = false;
export let v: string; interface Props {
punct?: boolean;
keywd?: boolean;
funct?: boolean;
str?: boolean;
small?: boolean;
v: string;
}
let {
punct = false,
keywd = false,
funct = false,
str = false,
small = false,
v
}: Props = $props();
const ty = const ty =
punct ? "punctuation" punct ? "punctuation"

View File

@ -1,17 +1,30 @@
<script lang="ts"> <script lang="ts">
import Window from "./window.svelte"; import Window from "./window.svelte";
export let x: string = "translate-x-none" interface Props {
export let y: string = "translate-y-full" x?: string;
export let targetY: string = "group-hover:-translate-y-[105%]" y?: string;
export let targetX: string = "group-hover:-translate-x-2/3" targetY?: string;
targetX?: string;
tooltipContent?: import('svelte').Snippet;
children?: import('svelte').Snippet;
}
let {
x = "translate-x-none",
y = "translate-y-full",
targetY = "group-hover:-translate-y-[105%]",
targetX = "group-hover:-translate-x-2/3",
tooltipContent,
children
}: Props = $props();
</script> </script>
<div class="group"> <div class="group">
<div class="absolute scale-0 transition-all [transition-timing-function:cubic-bezier(0.4,0,0.2,1.6)] [transition-duration:300ms] opacity-0 group-hover:scale-100 group-hover:opacity-100 {y} {x} {targetY} {targetX}"> <div class="absolute scale-0 transition-all [transition-timing-function:cubic-bezier(0.4,0,0.2,1.6)] [transition-duration:300ms] opacity-0 group-hover:scale-100 group-hover:opacity-100 {y} {x} {targetY} {targetX}">
<Window tooltip> <Window tooltip>
<slot name="tooltipContent">Hello world!</slot> {#if tooltipContent}{@render tooltipContent()}{:else}Hello world!{/if}
</Window> </Window>
</div> </div>
<slot/> {@render children?.()}
</div> </div>

View File

@ -2,16 +2,33 @@
import { highestZIndex, isMobile } from '$lib/window.ts'; import { highestZIndex, isMobile } from '$lib/window.ts';
import { draggable } from '@neodrag/svelte'; import { draggable } from '@neodrag/svelte';
export let title: string | undefined = undefined; interface Props {
export let iconUri: string = ''; title?: string | undefined;
export let id: string = ''; iconUri?: string;
export let sticky: boolean = false; id?: string;
export let entry: boolean = false; sticky?: boolean;
export let removePadding: boolean = false; entry?: boolean;
export let center: boolean = false; removePadding?: boolean;
export let layered: boolean = false; center?: boolean;
export let style: string = ""; layered?: boolean;
export let tooltip: boolean = false; style?: string;
tooltip?: boolean;
children?: import('svelte').Snippet;
}
let {
title = undefined,
iconUri = '',
id = '',
sticky = false,
entry = false,
removePadding = false,
center = false,
layered = false,
style = "",
tooltip = false,
children
}: Props = $props();
const scaleKeyframes = [ const scaleKeyframes = [
"window-open", "window-open",
@ -24,7 +41,7 @@
"window-open-move-left", "window-open-move-left",
"window-open-move-right", "window-open-move-right",
]; ];
$: chosenKeyframe = scaleKeyframes.at(Math.floor(Math.random() * scaleKeyframes.length)) let chosenKeyframe = $derived(scaleKeyframes.at(Math.floor(Math.random() * scaleKeyframes.length)))
const isOnMobile = isMobile() const isOnMobile = isMobile()
const _draggable = isOnMobile ? () => {} : draggable; const _draggable = isOnMobile ? () => {} : draggable;
@ -35,8 +52,8 @@
} }
</script> </script>
<!-- svelte-ignore a11y-no-static-element-interactions --> <!-- svelte-ignore a11y_no_static_element_interactions -->
<!-- svelte-ignore a11y-click-events-have-key-events --> <!-- svelte-ignore a11y_click_events_have_key_events -->
<div <div
use:_draggable={{ use:_draggable={{
disabled: isOnMobile, disabled: isOnMobile,
@ -44,7 +61,7 @@
handle: '.window-titlebar', handle: '.window-titlebar',
onDragStart: (data) => {focusWindow(data.currentNode)}, onDragStart: (data) => {focusWindow(data.currentNode)},
}} }}
on:click={(data) => {focusWindow(data.currentTarget)}} onclick={(data) => {focusWindow(data.currentTarget)}}
class=" class="
relative {layered ? "col-[1] row-[1]" : ""} flex flex-col {sticky ? 'md:sticky md:-top-9' : ''} {center ? "mx-auto" : ""} relative {layered ? "col-[1] row-[1]" : ""} flex flex-col {sticky ? 'md:sticky md:-top-9' : ''} {center ? "mx-auto" : ""}
max-w-screen-md xl:max-w-screen-lg 2xl:max-w-screen-xl {tooltip ? "min-w-fit" : "min-w-[30ch] lg:min-w-[40ch]"} w-full md:w-fit [height:fit-content] max-w-screen-md xl:max-w-screen-lg 2xl:max-w-screen-xl {tooltip ? "min-w-fit" : "min-w-[30ch] lg:min-w-[40ch]"} w-full md:w-fit [height:fit-content]
@ -87,6 +104,6 @@
{removePadding ? "" : tooltip ? "p-1" : "p-2"} bg-gradient-to-tl {removePadding ? "" : tooltip ? "p-1" : "p-2"} bg-gradient-to-tl
to-ralsei-pink-neon/15 from-ralsei-pink-regular/20 to-ralsei-pink-neon/15 from-ralsei-pink-regular/20
"> ">
<slot /> {@render children?.()}
</div> </div>
</div> </div>

View File

@ -4,7 +4,12 @@
import Tooltip from '../components/tooltip.svelte'; import Tooltip from '../components/tooltip.svelte';
import '../styles/app.css'; import '../styles/app.css';
export let data; interface Props {
data: any;
children?: import('svelte').Snippet;
}
let { data, children }: Props = $props();
interface MenuItem { interface MenuItem {
href: string; href: string;
@ -19,9 +24,9 @@
{ href: 'about', name: 'about', iconUri: '/icons/about.webp' } { href: 'about', name: 'about', iconUri: '/icons/about.webp' }
]; ];
$: routeComponents = data.route.split('/'); let routeComponents = $derived(data.route.split('/'));
$: doAddPostItem = routeComponents.length > 3 && routeComponents[1] === 'entries'; let doAddPostItem = $derived(routeComponents.length > 3 && routeComponents[1] === 'entries');
$: isRoute = (_route: string) => { let isRoute = $derived((_route: string) => {
if (doAddPostItem) { if (doAddPostItem) {
if (_route === 'entries') { if (_route === 'entries') {
return false; return false;
@ -30,9 +35,9 @@
} }
} }
return _route === routeComponents[1]; return _route === routeComponents[1];
}; });
$: title = getTitle(data.route); let title = $derived(getTitle(data.route));
const svgSquiggles = [[2], [3], [2], [3], [1]]; const svgSquiggles = [[2], [3], [2], [3], [1]];
</script> </script>
@ -49,13 +54,13 @@
app-grid-background motion-safe:app-grid-background-anim app-grid-background motion-safe:app-grid-background-anim
fixed -z-10 w-full [height:100%] top-0 left-0 fixed -z-10 w-full [height:100%] top-0 left-0
" "
/> ></div>
<div <div
class=" class="
app-grid-background-second-layer motion-safe:app-grid-background-second-layer-anim app-grid-background-second-layer motion-safe:app-grid-background-second-layer-anim
fixed -z-20 w-full [height:100%] top-0 left-0 fixed -z-20 w-full [height:100%] top-0 left-0
" "
/> ></div>
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
@ -130,7 +135,7 @@
</svg> </svg>
<div class="md:h-[96vh] pb-[8vh] lg:px-[1vw] 2xl:px-[2vw] lg:pb-[3vh] lg:pt-[1vh] overflow-x-hidden [scrollbar-gutter:stable]"> <div class="md:h-[96vh] pb-[8vh] lg:px-[1vw] 2xl:px-[2vw] lg:pb-[3vh] lg:pt-[1vh] overflow-x-hidden [scrollbar-gutter:stable]">
<slot /> {@render children?.()}
</div> </div>
<nav class="w-full min-h-[5vh] max-h-[6vh] fixed bottom-0 z-[999] bg-ralsei-black overflow-visible"> <nav class="w-full min-h-[5vh] max-h-[6vh] fixed bottom-0 z-[999] bg-ralsei-black overflow-visible">
@ -150,19 +155,21 @@
<NavButton highlight name={routeComponents[2]} href={data.route.slice(1)} iconUri='/icons/entry.webp'/> <NavButton highlight name={routeComponents[2]} href={data.route.slice(1)} iconUri='/icons/entry.webp'/>
{/if} {/if}
{/each} {/each}
<div class="hidden md:block grow" /> <div class="hidden md:block grow"></div>
<div class="navbox"> <div class="navbox">
<a title="previous site" class="hover:underline" href="https://xn--sr8hvo.ws/previous"></a> <a title="previous site" class="hover:underline" href="https://xn--sr8hvo.ws/previous"></a>
<a class="hover:underline" href="https://xn--sr8hvo.ws">indieweb 🕸💍</a> <a class="hover:underline" href="https://xn--sr8hvo.ws">indieweb 🕸💍</a>
<a title="next site" class="hover:underline" href="https://xn--sr8hvo.ws/next"></a> <a title="next site" class="hover:underline" href="https://xn--sr8hvo.ws/next"></a>
</div> </div>
<Tooltip> <Tooltip>
<svelte:fragment slot="tooltipContent"> {#snippet tooltipContent()}
<p class="font-monospace">
<nobr>total visits = <span class="text-ralsei-green-light text-shadow-green">{data.visitCount.toString().padStart(9, ".")}</span></nobr> <p class="font-monospace">
<nobr>uniq recent visits = <span class="text-ralsei-green-light text-shadow-green">{data.lastVisitors.size.toString().padStart(3, ".")}</span></nobr> <nobr>total visits = <span class="text-ralsei-green-light text-shadow-green">{data.visitCount.toString().padStart(9, ".")}</span></nobr>
</p> <nobr>uniq recent visits = <span class="text-ralsei-green-light text-shadow-green">{data.lastVisitors.size.toString().padStart(3, ".")}</span></nobr>
</svelte:fragment> </p>
{/snippet}
<div class="navbox"><p><span class="text-ralsei-green-light text-shadow-green">{data.recentVisitCount}</span> recent clicks</p></div> <div class="navbox"><p><span class="text-ralsei-green-light text-shadow-green">{data.recentVisitCount}</span> recent clicks</p></div>
</Tooltip> </Tooltip>
{#if isRoute("entries") || isRoute("log")} {#if isRoute("entries") || isRoute("log")}

View File

@ -5,7 +5,11 @@
import Window from '../components/window.svelte'; import Window from '../components/window.svelte';
import LatestStuff from './lateststuff.md'; import LatestStuff from './lateststuff.md';
export let data; interface Props {
data: any;
}
let { data }: Props = $props();
const renderDate = (timestamp: number) => { const renderDate = (timestamp: number) => {
return (new Date(timestamp)).toLocaleString("en-GB", { return (new Date(timestamp)).toLocaleString("en-GB", {
@ -81,7 +85,7 @@
></i ></i
> >
</p> </p>
<div class="grow" /> <div class="grow"></div>
<a <a
class=" class="
place-self-end [font-family:'Doll_Mono'] text-ralsei-pink-neon text-shadow-none hover:text-shadow-pink place-self-end [font-family:'Doll_Mono'] text-ralsei-pink-neon text-shadow-none hover:text-shadow-pink
@ -163,7 +167,7 @@
{/if} {/if}
{#if data.lastTrack} {#if data.lastTrack}
<div class="flex flex-row m-1.5 border-4 border-double bg-ralsei-black"> <div class="flex flex-row m-1.5 border-4 border-double bg-ralsei-black">
<!-- svelte-ignore a11y-missing-attribute --> <!-- svelte-ignore a11y_missing_attribute -->
{#if data.lastTrack.image} {#if data.lastTrack.image}
<img <img
class="border-4 w-16 h-16" class="border-4 w-16 h-16"
@ -201,7 +205,7 @@
{/if} {/if}
{#if data.lastGame} {#if data.lastGame}
<div class="flex flex-row m-1.5 border-4 border-double bg-ralsei-black"> <div class="flex flex-row m-1.5 border-4 border-double bg-ralsei-black">
<!-- svelte-ignore a11y-missing-attribute --> <!-- svelte-ignore a11y_missing_attribute -->
<img <img
class="border-4 w-16 h-16" class="border-4 w-16 h-16"
style="border-style: none double none none;" style="border-style: none double none none;"
@ -218,7 +222,7 @@
>{data.lastGame.name}</a >{data.lastGame.name}</a
> >
</p> </p>
<!-- svelte-ignore a11y-missing-attribute --> <!-- svelte-ignore a11y_missing_attribute -->
<a <a
href="https://steamcommunity.com/id/yusdacra" href="https://steamcommunity.com/id/yusdacra"
class="text-xs hover:underline text-shadow-green text-ralsei-green-light" class="text-xs hover:underline text-shadow-green text-ralsei-green-light"

View File

@ -4,13 +4,18 @@
import Stuff from './stuff.md' import Stuff from './stuff.md'
import '../../styles/app.css' import '../../styles/app.css'
export let title; interface Props {
title: any;
children?: import('svelte').Snippet;
}
let { title, children }: Props = $props();
</script> </script>
<div class="flex flex-wrap md:flex-nowrap gap-4 md:gap-8"> <div class="flex flex-wrap md:flex-nowrap gap-4 md:gap-8">
<Window {title} style="ml-auto"> <Window {title} style="ml-auto">
<div class="prose prose-ralsei leading-6 prose-ul:leading-5 max-w-[80ch]"> <div class="prose prose-ralsei leading-6 prose-ul:leading-5 max-w-[80ch]">
<slot /> {@render children?.()}
</div> </div>
</Window> </Window>
<div class="sticky flex flex-col mr-auto gap-4 md:gap-8 !leading-6 prose-ul:!leading-5"> <div class="sticky flex flex-col mr-auto gap-4 md:gap-8 !leading-6 prose-ul:!leading-5">

View File

@ -3,7 +3,11 @@
import type { PostData } from './+layout.server.js'; import type { PostData } from './+layout.server.js';
import LogPage from '../log/+page.svelte'; import LogPage from '../log/+page.svelte';
export let data; interface Props {
data: any;
}
let { data }: Props = $props();
let posts: PostData[] = data.posts as PostData[]; let posts: PostData[] = data.posts as PostData[];
</script> </script>

View File

@ -4,11 +4,21 @@
import '../../styles/app.css'; import '../../styles/app.css';
import { page } from '$app/stores'; import { page } from '$app/stores';
export let title; interface Props {
export let date; title: any;
export let excerpt; date: any;
excerpt: any;
children?: import('svelte').Snippet;
}
$: showMetadata = excerpt !== undefined && excerpt !== null; let {
title,
date,
excerpt,
children
}: Props = $props();
let showMetadata = $derived(excerpt !== undefined && excerpt !== null);
</script> </script>
<svelte:head> <svelte:head>
@ -20,7 +30,7 @@
<article class="mx-auto max-w-fit flex flex-wrap lg:flex-nowrap gap-4 h-entry"> <article class="mx-auto max-w-fit flex flex-wrap lg:flex-nowrap gap-4 h-entry">
<Window {title} iconUri="/icons/entry.webp" entry> <Window {title} iconUri="/icons/entry.webp" entry>
<div class="prose prose-ralsei max-w-[80ch] e-content"> <div class="prose prose-ralsei max-w-[80ch] e-content">
<slot /> {@render children?.()}
</div> </div>
</Window> </Window>
{#if showMetadata} {#if showMetadata}

View File

@ -3,7 +3,11 @@
import Token from '../../components/token.svelte'; import Token from '../../components/token.svelte';
import Window from '../../components/window.svelte'; import Window from '../../components/window.svelte';
export let data; interface Props {
data: any;
}
let { data }: Props = $props();
function resetEntriesAnimation() { function resetEntriesAnimation() {
var el = document.getElementById('guestbookentries'); var el = document.getElementById('guestbookentries');
@ -30,7 +34,7 @@
placeholder="say meow!" placeholder="say meow!"
maxlength="300" maxlength="300"
required required
/> ></textarea>
</div> </div>
<div class="flex flex-row gap-1 mt-1"> <div class="flex flex-row gap-1 mt-1">
<input <input
@ -87,7 +91,7 @@
{#each data.entries as note, index} {#each data.entries as note, index}
<Note showOutgoing={false} {note}/> <Note showOutgoing={false} {note}/>
{#if index < data.entries.length - 1} {#if index < data.entries.length - 1}
<div class="mt-3"/> <div class="mt-3"></div>
{/if} {/if}
{/each} {/each}
</nobr></code></pre> </nobr></code></pre>

View File

@ -3,7 +3,11 @@
import Token from '../../components/token.svelte'; import Token from '../../components/token.svelte';
import Note from '../../components/note.svelte'; import Note from '../../components/note.svelte';
export let data; interface Props {
data: any;
}
let { data }: Props = $props();
</script> </script>
<Window title="terminal" removePadding> <Window title="terminal" removePadding>
@ -25,7 +29,7 @@
{#each data.feedPosts as note, index} {#each data.feedPosts as note, index}
<Note {note}/> <Note {note}/>
{#if index < data.feedPosts.length - 1} {#if index < data.feedPosts.length - 1}
<div class="mt-3"/> <div class="mt-3"></div>
{/if} {/if}
{/each} {/each}
</nobr></code></pre> </nobr></code></pre>