fixes, qol and stuff

This commit is contained in:
2026-07-21 12:30:53 +01:00
parent 8acc692b08
commit 5ffebe4895
22 changed files with 611 additions and 66 deletions
+1
View File
@@ -12,6 +12,7 @@
nodejs
just
podman-compose
ffmpeg
];
env = {
+4
View File
@@ -20,6 +20,7 @@
"mdsvex": "^0.12.7",
"prettier": "^3.8.3",
"prettier-plugin-svelte": "^3.5.1",
"sass": "^1.101.0",
"sass-embedded": "^1.100.0",
"sharp": "^0.34.5",
"svelte": "^5.55.4",
@@ -29,5 +30,8 @@
"typescript": "^5.9.3",
"vite": "^7.3.2",
"vite-tsconfig-paths": "^6.1.1"
},
"dependencies": {
"@lucide/svelte": "^1.25.0"
}
}
+60 -33
View File
@@ -10,19 +10,23 @@ patchedDependencies:
importers:
.:
dependencies:
'@lucide/svelte':
specifier: ^1.25.0
version: 1.25.0(svelte@5.55.4)
devDependencies:
'@sveltejs/adapter-static':
specifier: ^3.0.10
version: 3.0.10(@sveltejs/kit@2.57.1(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.55.4)(vite@7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.100.0)))(svelte@5.55.4)(typescript@5.9.3)(vite@7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.100.0)))
version: 3.0.10(@sveltejs/kit@2.57.1(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.55.4)(vite@7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.101.0)))(svelte@5.55.4)(typescript@5.9.3)(vite@7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.101.0)))
'@sveltejs/enhanced-img':
specifier: ^0.10.4
version: 0.10.4(patch_hash=e313100e058c1ce98f02a1eeb196881f22fcb6af5d992973eaae763037b27509)(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.55.4)(vite@7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.100.0)))(rollup@4.60.2)(svelte@5.55.4)(vite@7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.100.0))
version: 0.10.4(patch_hash=e313100e058c1ce98f02a1eeb196881f22fcb6af5d992973eaae763037b27509)(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.55.4)(vite@7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.101.0)))(rollup@4.60.2)(svelte@5.55.4)(vite@7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.101.0))
'@sveltejs/kit':
specifier: ^2.57.1
version: 2.57.1(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.55.4)(vite@7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.100.0)))(svelte@5.55.4)(typescript@5.9.3)(vite@7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.100.0))
version: 2.57.1(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.55.4)(vite@7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.101.0)))(svelte@5.55.4)(typescript@5.9.3)(vite@7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.101.0))
'@sveltejs/vite-plugin-svelte':
specifier: ^6.2.4
version: 6.2.4(svelte@5.55.4)(vite@7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.100.0))
version: 6.2.4(svelte@5.55.4)(vite@7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.101.0))
'@types/node':
specifier: ^25.9.1
version: 25.9.1
@@ -35,6 +39,9 @@ importers:
prettier-plugin-svelte:
specifier: ^3.5.1
version: 3.5.1(prettier@3.8.3)(svelte@5.55.4)
sass:
specifier: ^1.101.0
version: 1.101.0
sass-embedded:
specifier: ^1.100.0
version: 1.100.0
@@ -49,7 +56,7 @@ importers:
version: 4.4.6(picomatch@4.0.4)(svelte@5.55.4)(typescript@5.9.3)
svelte-preprocess:
specifier: ^6.0.3
version: 6.0.3(postcss@8.5.10)(sass@1.100.0)(svelte@5.55.4)(typescript@5.9.3)
version: 6.0.3(postcss@8.5.10)(sass@1.101.0)(svelte@5.55.4)(typescript@5.9.3)
svelte-preprocess-cssmodules:
specifier: ^3.0.1
version: 3.0.1(svelte@5.55.4)
@@ -58,10 +65,10 @@ importers:
version: 5.9.3
vite:
specifier: ^7.3.2
version: 7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.100.0)
version: 7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.101.0)
vite-tsconfig-paths:
specifier: ^6.1.1
version: 6.1.1(typescript@5.9.3)(vite@7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.100.0))
version: 6.1.1(typescript@5.9.3)(vite@7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.101.0))
packages:
@@ -396,6 +403,11 @@ packages:
'@jridgewell/trace-mapping@0.3.31':
resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
'@lucide/svelte@1.25.0':
resolution: {integrity: sha512-v9m+dD68jxVnqkU3K59mG/RSRFlPGzmKCGSyMfnXcaGv9jODDQMyQkcp1CGvk3Y/cUj9v7f8rw1n//K0B53xGQ==}
peerDependencies:
svelte: ^5
'@parcel/watcher-android-arm64@2.5.6':
resolution: {integrity: sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==}
engines: {node: '>= 10.0.0'}
@@ -1027,6 +1039,11 @@ packages:
engines: {node: '>=20.19.0'}
hasBin: true
sass@1.101.0:
resolution: {integrity: sha512-OL3GoQyoUdDt843DpVmDO6y2k1sc5IhUDSpu8XucEI+35neq5QivZ1iuegnpraEVTJXlQGK1gl27zKcTLEPbQw==}
engines: {node: '>=20.19.0'}
hasBin: true
semver@7.7.4:
resolution: {integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==}
engines: {node: '>=10'}
@@ -1431,6 +1448,10 @@ snapshots:
'@jridgewell/resolve-uri': 3.1.2
'@jridgewell/sourcemap-codec': 1.5.5
'@lucide/svelte@1.25.0(svelte@5.55.4)':
dependencies:
svelte: 5.55.4
'@parcel/watcher-android-arm64@2.5.6':
optional: true
@@ -1583,28 +1604,28 @@ snapshots:
dependencies:
acorn: 8.16.0
'@sveltejs/adapter-static@3.0.10(@sveltejs/kit@2.57.1(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.55.4)(vite@7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.100.0)))(svelte@5.55.4)(typescript@5.9.3)(vite@7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.100.0)))':
'@sveltejs/adapter-static@3.0.10(@sveltejs/kit@2.57.1(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.55.4)(vite@7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.101.0)))(svelte@5.55.4)(typescript@5.9.3)(vite@7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.101.0)))':
dependencies:
'@sveltejs/kit': 2.57.1(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.55.4)(vite@7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.100.0)))(svelte@5.55.4)(typescript@5.9.3)(vite@7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.100.0))
'@sveltejs/kit': 2.57.1(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.55.4)(vite@7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.101.0)))(svelte@5.55.4)(typescript@5.9.3)(vite@7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.101.0))
'@sveltejs/enhanced-img@0.10.4(patch_hash=e313100e058c1ce98f02a1eeb196881f22fcb6af5d992973eaae763037b27509)(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.55.4)(vite@7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.100.0)))(rollup@4.60.2)(svelte@5.55.4)(vite@7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.100.0))':
'@sveltejs/enhanced-img@0.10.4(patch_hash=e313100e058c1ce98f02a1eeb196881f22fcb6af5d992973eaae763037b27509)(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.55.4)(vite@7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.101.0)))(rollup@4.60.2)(svelte@5.55.4)(vite@7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.101.0))':
dependencies:
'@sveltejs/vite-plugin-svelte': 6.2.4(svelte@5.55.4)(vite@7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.100.0))
'@sveltejs/vite-plugin-svelte': 6.2.4(svelte@5.55.4)(vite@7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.101.0))
magic-string: 0.30.21
sharp: 0.34.5
svelte: 5.55.4
svelte-parse-markup: 0.1.5(svelte@5.55.4)
vite: 7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.100.0)
vite: 7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.101.0)
vite-imagetools: 9.0.3(rollup@4.60.2)
zimmerframe: 1.1.4
transitivePeerDependencies:
- rollup
'@sveltejs/kit@2.57.1(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.55.4)(vite@7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.100.0)))(svelte@5.55.4)(typescript@5.9.3)(vite@7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.100.0))':
'@sveltejs/kit@2.57.1(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.55.4)(vite@7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.101.0)))(svelte@5.55.4)(typescript@5.9.3)(vite@7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.101.0))':
dependencies:
'@standard-schema/spec': 1.1.0
'@sveltejs/acorn-typescript': 1.0.9(acorn@8.16.0)
'@sveltejs/vite-plugin-svelte': 6.2.4(svelte@5.55.4)(vite@7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.100.0))
'@sveltejs/vite-plugin-svelte': 6.2.4(svelte@5.55.4)(vite@7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.101.0))
'@types/cookie': 0.6.0
acorn: 8.16.0
cookie: 0.6.0
@@ -1616,26 +1637,26 @@ snapshots:
set-cookie-parser: 3.1.0
sirv: 3.0.2
svelte: 5.55.4
vite: 7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.100.0)
vite: 7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.101.0)
optionalDependencies:
typescript: 5.9.3
'@sveltejs/vite-plugin-svelte-inspector@5.0.2(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.55.4)(vite@7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.100.0)))(svelte@5.55.4)(vite@7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.100.0))':
'@sveltejs/vite-plugin-svelte-inspector@5.0.2(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.55.4)(vite@7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.101.0)))(svelte@5.55.4)(vite@7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.101.0))':
dependencies:
'@sveltejs/vite-plugin-svelte': 6.2.4(svelte@5.55.4)(vite@7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.100.0))
'@sveltejs/vite-plugin-svelte': 6.2.4(svelte@5.55.4)(vite@7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.101.0))
obug: 2.1.1
svelte: 5.55.4
vite: 7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.100.0)
vite: 7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.101.0)
'@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.55.4)(vite@7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.100.0))':
'@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.55.4)(vite@7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.101.0))':
dependencies:
'@sveltejs/vite-plugin-svelte-inspector': 5.0.2(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.55.4)(vite@7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.100.0)))(svelte@5.55.4)(vite@7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.100.0))
'@sveltejs/vite-plugin-svelte-inspector': 5.0.2(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.55.4)(vite@7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.101.0)))(svelte@5.55.4)(vite@7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.101.0))
deepmerge: 4.3.1
magic-string: 0.30.21
obug: 2.1.1
svelte: 5.55.4
vite: 7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.100.0)
vitefu: 1.1.3(vite@7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.100.0))
vite: 7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.101.0)
vitefu: 1.1.3(vite@7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.101.0))
'@types/cookie@0.6.0': {}
@@ -1668,7 +1689,6 @@ snapshots:
chokidar@5.0.0:
dependencies:
readdirp: 5.0.0
optional: true
clsx@2.1.1: {}
@@ -1808,8 +1828,7 @@ snapshots:
readdirp@4.1.2: {}
readdirp@5.0.0:
optional: true
readdirp@5.0.0: {}
rollup@4.60.2:
dependencies:
@@ -1946,6 +1965,14 @@ snapshots:
'@parcel/watcher': 2.5.6
optional: true
sass@1.101.0:
dependencies:
chokidar: 5.0.0
immutable: 5.1.6
source-map-js: 1.2.1
optionalDependencies:
'@parcel/watcher': 2.5.6
semver@7.7.4: {}
set-cookie-parser@3.1.0: {}
@@ -2019,12 +2046,12 @@ snapshots:
magic-string: 0.25.9
svelte: 5.55.4
svelte-preprocess@6.0.3(postcss@8.5.10)(sass@1.100.0)(svelte@5.55.4)(typescript@5.9.3):
svelte-preprocess@6.0.3(postcss@8.5.10)(sass@1.101.0)(svelte@5.55.4)(typescript@5.9.3):
dependencies:
svelte: 5.55.4
optionalDependencies:
postcss: 8.5.10
sass: 1.100.0
sass: 1.101.0
typescript: 5.9.3
svelte@5.55.4:
@@ -2103,17 +2130,17 @@ snapshots:
transitivePeerDependencies:
- rollup
vite-tsconfig-paths@6.1.1(typescript@5.9.3)(vite@7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.100.0)):
vite-tsconfig-paths@6.1.1(typescript@5.9.3)(vite@7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.101.0)):
dependencies:
debug: 4.4.3
globrex: 0.1.2
tsconfck: 3.1.6(typescript@5.9.3)
vite: 7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.100.0)
vite: 7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.101.0)
transitivePeerDependencies:
- supports-color
- typescript
vite@7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.100.0):
vite@7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.101.0):
dependencies:
esbuild: 0.27.7
fdir: 6.5.0(picomatch@4.0.4)
@@ -2124,11 +2151,11 @@ snapshots:
optionalDependencies:
'@types/node': 25.9.1
fsevents: 2.3.3
sass: 1.100.0
sass: 1.101.0
sass-embedded: 1.100.0
vitefu@1.1.3(vite@7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.100.0)):
vitefu@1.1.3(vite@7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.101.0)):
optionalDependencies:
vite: 7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.100.0)
vite: 7.3.2(@types/node@25.9.1)(sass-embedded@1.100.0)(sass@1.101.0)
zimmerframe@1.1.4: {}
+23
View File
@@ -0,0 +1,23 @@
<svelte:options customElement="scubling-card" />
<script lang="ts">
export let title: string = "";
export let description: string = "";
</script>
<div class="scubling-card">
{#if title}
<h3>{title}</h3>
{/if}
{#if description}
<p>{description}</p>
{/if}
<slot />
</div>
<style>
.scubling-card {
padding: 1rem;
border: 2px solid currentColor;
}
</style>
+19 -8
View File
@@ -1,22 +1,32 @@
<script lang="ts">
let meow = "";
<script module lang="ts">
export { storeButton };
import gumroad from "./sidebar/gumroad.png";
import jinxxy from "./sidebar/jinxxy.png";
</script>
{#snippet StoreButton(store: string, url: string)}
<a aria-label="Store Page Button" href={url}"></a>
{#snippet storeButton(store: string, url: string)}
<a aria-label="Store Page Button" class="StoreButton" href={url}>
{#if store == "gumroad"}
<img src={gumroad} />
{:else if store == "jinxxy"}
<img src={jinxxy} />
{/if}
</a>
{/snippet}
<style lang="scss">
.StoreButton {
display: block;
width: fit-content;
height: 30px;
border: 2px outset #1da1f2;
width: 100%;
height: 45px;
border: 3px outset #1da1f2;
background: #1da1f2;
margin: 2px;
padding: 2px;
text-align: center;
img {
height: auto;
width: 45px;
}
}
.StoreButton:hover {
@@ -27,6 +37,7 @@ let meow = "";
border-style: inset;
img {
transform: translate(2px, 2px);
}
}
</style>
View File
+10
View File
@@ -0,0 +1,10 @@
<svelte:options customElement="hint-box" />
<script>
let { name = "world" } = $props();
import "./Commons.scss";
</script>
<h1>Hello {name}!</h1>
<a>meow</a>
<slot />
+4 -2
View File
@@ -1,21 +1,23 @@
.right-sidebar {
margin: 5px;
margin-right: 0px;
height: 800px;
width: 125px;
background-color: var(--secondary);
border: 2px, inset, var(--thirdly);
box-sizing: border-box;
min-height: 900px;
height: 100%;
}
.left-sidebar {
margin: 5px;
margin-left: 0px;
height: 800px;
width: 125px;
background-color: var(--secondary);
border: 2px, inset, var(--thirdly);
box-sizing: border-box;
min-height: 900px;
height: 100%;
}
.side-card {
+3 -1
View File
@@ -1,4 +1,6 @@
<title>Doloro's Site (Which resides on the internet)</title>
<svelte:head>
<title>Doloro Website [Home]</title>
</svelte:head>
<div>
<h1>hi</h1>
+4
View File
@@ -6,6 +6,10 @@
import { commitCard } from "./commitCard.svelte";
</script>
<svelte:head>
<title>Doloro Website [Changelog]</title>
</svelte:head>
<table class="commitContainer">
<caption>Git Commits of the website repo</caption>
<tbody>
+8 -5
View File
@@ -1,14 +1,15 @@
<script lang="ts">
import ScublingCard from "$lib/ScublingCard.svelte";
const videos = import.meta.glob("./*.mp4", {
eager: true,
import: "default",
query: { enhanced: true },
});
console.log(videos);
const scub = videos["./scub.mp4"];
</script>
<svelte:head>
<title>Doloro Website [Scublings]</title>
<meta property="og:type" content="video.other" />
<meta property="og:video" content="https://doloro.co.uk{scub.video.src}" />
<meta property="og:video:type" content="video/mp4" />
@@ -16,12 +17,14 @@
<meta property="og:video:height" content="1080" />
<meta property="og:title" content="Scublings" />
<!-- Optional but helps Discord show a thumbnail -->
<meta
property="og:image"
content="https://yourdomain.com/scub-thumbnail.jpg"
/>
<!-- <meta -->
<!-- property="og:image" -->
<!-- content="https://yourdomain.com/scub-thumbnail.jpg" -->
<!-- /> -->
</svelte:head>
<ScublingCard title="Scublings" description="A scubling video." />
<div class="video-container">
<enhanced:video src={scub}> </enhanced:video>
</div>
+6 -4
View File
@@ -3,16 +3,18 @@ export const prerender = true;
import { execSync } from 'child_process';
export type StoreEntity = {
image: string,
images: string[],
name: string,
description: string,
short: string, // Short Description
category: string,
gumroad?: string,
jinxxy?: string
}
const Catalog: StoreEntity[] = [
{ name: "Magic Circle", image: "MagicCircle", short: "", gumroad: undefined, jinxxy: "" } // Placeholder
];
const Catalog: Record<string, StoreEntity> = {};
Catalog["MagicCircle"] = { images: ["MagicCircle"], name: "Magic Circle", description: "Mreowww", short: "magiccircle", category: "Amulets", gumroad: "https://doloro.gumroad.com/l/Amulet", jinxxy: "" } // Placeholder
export async function load() {
return {
+30 -3
View File
@@ -1,8 +1,35 @@
<script lang="ts">
let { data } = $props();
import { snackProduct } from "./snacks.svelte";
import type { StoreEntity } from "./+page.server.ts";
let { data } = $props();
function groupByCategory(products: Record<string, StoreEntity>) {
const groups: Map<string, string[]> = new Map();
for (const [key, product] of Object.entries(products)) {
const cat = product.category;
if (!groups.has(cat)) {
groups.set(cat, []);
}
groups.get(cat)!.push(key);
}
return groups;
}
const categorized = groupByCategory(data.catalog);
</script>
{#each data.catalog as item}
{@render snackProduct(item)}
<svelte:head>
<title>Doloro Website [Store]</title>
</svelte:head>
{#each Array.from(categorized.entries()) as [category, products]}
<section class="StoreCategory">
<h2 class="StoreCategoryTitle">{category}</h2>
<div class="SnackCatagoryContainer">
{#each products as key}
{@render snackProduct(data.catalog[key], key)}
{/each}
</div>
</section>
{/each}
+32
View File
@@ -0,0 +1,32 @@
export const prerender = true;
import { type StoreEntity } from "../+page.server.ts";
export type ProductPageData = {
product: StoreEntity;
slug: string;
url: string;
}
const Catalog: Record<string, StoreEntity> = {};
Catalog["MagicCircle"] = { images: ["MagicCircle"], name: "Magic Circle", description: "Mreowww", short: "magiccircle", category: "Amulets", gumroad: "https://doloro.gumroad.com/l/Amulet", jinxxy: "" }
export function entries() {
return Object.keys(Catalog).map((slug) => ({ slug }));
}
export async function load({ params }: { params: { slug: string } }) {
const slug = params.slug;
const product = Catalog[slug];
if (!product) {
throw new Error(`Product not found: ${slug}`);
}
return {
product,
slug,
url: `/store/${slug}`
};
}
+223
View File
@@ -0,0 +1,223 @@
<script lang="ts">
import { snackImage, snackImages } from "../func.svelte";
import { storeButton } from "$lib/StoreButtons.svelte";
import type { ProductPageData } from "./+page.server.ts";
let { data } = $props();
let currentImageIndex = 0;
function selectImage(index: number) {
currentImageIndex = index;
}
function prevImage() {
currentImageIndex = (currentImageIndex - 1 + data.product.images.length) % data.product.images.length;
}
function nextImage() {
currentImageIndex = (currentImageIndex + 1) % data.product.images.length;
}
</script>
<style lang="scss">
.ProductPage {
display: flex;
flex-direction: column;
align-items: center;
gap: 30px;
padding: 40px 20px;
}
.ProductPageImageGallery {
width: 100%;
max-width: 600px;
display: flex;
flex-direction: column;
align-items: center;
gap: 12px;
}
.ProductPageImageMain {
width: 100%;
position: relative;
border-width: 4px;
border-style: groove;
border-color: var(--accent-2);
img {
width: 100%;
height: auto;
display: block;
}
.GalleryControls {
position: absolute;
top: 50%;
left: 0;
right: 0;
transform: translateY(-50%);
display: flex;
align-items: center;
justify-content: space-between;
pointer-events: none;
.GalleryNav {
pointer-events: auto;
background: var(--primary);
border: 2px groove var(--accent-2);
color: white;
width: 36px;
height: 36px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
font-size: 1.2rem;
opacity: 0.7;
&:hover {
opacity: 1;
}
}
.GalleryCounter {
color: white;
font-size: 1rem;
background: rgba(0, 0, 0, 0.5);
padding: 4px 10px;
border: 1px groove var(--accent-2);
pointer-events: auto;
user-select: none;
}
}
}
.ProductPageThumbnails {
display: flex;
gap: 8px;
flex-wrap: wrap;
justify-content: center;
.Thumbnail {
width: 60px;
height: 60px;
border: 2px groove var(--accent-2);
cursor: pointer;
opacity: 0.5;
transition: opacity 0.2s;
&:hover {
opacity: 0.8;
}
&.active {
opacity: 1;
border-color: var(--accent-1);
}
img {
width: 100%;
height: 100%;
object-fit: cover;
display: block;
}
}
}
.ProductPageDetails {
display: flex;
flex-direction: column;
align-items: center;
gap: 20px;
width: 100%;
max-width: 600px;
}
.ProductPageInfo {
text-align: center;
display: flex;
flex-direction: column;
gap: 12px;
}
.ProductPageCategory {
font-size: 0.9rem;
text-transform: uppercase;
letter-spacing: 2px;
color: var(--accent-1);
border-bottom: 2px groove var(--accent-2);
padding-bottom: 6px;
width: fit-content;
margin: 0 auto;
}
.ProductPageInfo h1 {
font-size: 2rem;
margin: 0;
}
.ProductPageInfo p {
font-size: 1.1rem;
margin: 0;
max-width: 450px;
}
.ProductPageButtons {
display: flex;
flex-direction: row;
gap: 12px;
padding: 10px;
width: 100%;
max-width: 400px;
justify-content: center;
}
</style>
<svelte:head>
<title>{data.product.name} | Doloro Store</title>
<meta name="description" content={data.product.description} />
<meta property="og:type" content="product" />
<meta property="og:title" content={data.product.name} />
<meta property="og:description" content={data.product.description} />
<meta property="og:url" content={data.url} />
</svelte:head>
<div class="ProductPage">
<div class="ProductPageImageGallery">
<div class="ProductPageImageMain">
{#if data.product.images.length > 1}
<div class="GalleryControls">
<button class="GalleryNav prev" on:click={prevImage}></button>
<span class="GalleryCounter">{currentImageIndex + 1} / {data.product.images.length}</span>
<button class="GalleryNav next" on:click={nextImage}></button>
</div>
{/if}
<enhanced:img src={snackImage(data.product.images[currentImageIndex])} alt={data.product.name} />
</div>
{#if data.product.images.length > 1}
<div class="ProductPageThumbnails">
{#each data.product.images as img, i}
<div class="Thumbnail {i === currentImageIndex ? 'active' : ''}" on:click={() => selectImage(i)}>
<enhanced:img src={snackImage(img)} alt={`${data.product.name} image ${i + 1}`} />
</div>
{/each}
</div>
{/if}
</div>
<div class="ProductPageDetails">
<div class="ProductPageInfo">
<span class="ProductPageCategory">{data.product.category}</span>
<h1>{data.product.name}</h1>
<p>{data.product.description}</p>
</div>
<div class="ProductPageButtons">
{#if data.product.gumroad != undefined}
{@render storeButton("gumroad", data.product.gumroad!)}
{/if}
{#if data.product.jinxxy != undefined}
{@render storeButton("jinxxy", data.product.jinxxy!)}
{/if}
</div>
</div>
</div>
+69
View File
@@ -0,0 +1,69 @@
.ProductPage {
display: flex;
flex-direction: column;
align-items: center;
gap: 30px;
padding: 40px 20px;
}
.ProductPageImage {
width: 100%;
max-width: 600px;
border-width: 4px;
border-style: groove;
border-color: blue;
img {
width: 100%;
height: auto;
display: block;
}
}
.ProductPageDetails {
display: flex;
flex-direction: column;
align-items: center;
gap: 20px;
width: 100%;
max-width: 600px;
}
.ProductPageInfo {
text-align: center;
display: flex;
flex-direction: column;
gap: 12px;
}
.ProductPageCategory {
font-size: 0.9rem;
text-transform: uppercase;
letter-spacing: 2px;
color: #888;
border-bottom: 2px groove blue;
padding-bottom: 6px;
width: fit-content;
margin: 0 auto;
}
.ProductPageInfo h1 {
font-size: 2rem;
margin: 0;
}
.ProductPageInfo p {
font-size: 1.1rem;
margin: 0;
max-width: 450px;
}
.ProductPageButtons {
display: flex;
flex-direction: row;
gap: 12px;
padding: 10px;
width: 100%;
max-width: 400px;
justify-content: center;
}
+5
View File
@@ -0,0 +1,5 @@
import type { StoreEntity } from './+page.server.ts';
export const Catalog: Record<string, StoreEntity> = {};
Catalog["MagicCircle"] = { name: "Magic Circle", description: "Mreowww", image: "MagicCircle", short: "magiccircle", category: "Amulets", gumroad: "https://doloro.gumroad.com/l/Amulet", jinxxy: "" }
+4
View File
@@ -19,4 +19,8 @@
export function snackImage(img: string) {
return trimmedImgs[img];
}
export function snackImages(imgs: string[]) {
return imgs.map(img => trimmedImgs[img]);
}
</script>
+79 -4
View File
@@ -4,29 +4,104 @@
border-width: 3px;
border-style: groove;
border-color: blue;
border-color: var(--accent-2);
width: 300px;
height: 500px;
min-height: 500px;
picture {
width: 300px;
width: 100%;
height: 300px;
}
img {
width: 300px;
width: 100%;
height: 300px;
object-fit: cover;
}
}
.SnackProductLink {
text-decoration: none;
color: inherit;
picture {
display: block;
}
}
.SnackProductName {
margin: 0;
text-align: center;
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
h1 {
margin: 0;
text-align: center;
}
}
.SnackProductPopOut {
display: inline-flex;
align-items: center;
color: var(--accent-1);
text-decoration: none;
svg {
stroke: currentColor;
}
&:hover {
color: var(--accent-2);
}
}
.SnackProductDetails {
display: flex;
flex-direction: column;
background-color: var(--card-field);
align-items: center;
justify-content: space-between;
height: 100%;
padding: 12px;
gap: 12px;
}
.SnackProductButtons {
display: flex;
width: 100%;
flex-direction: row;
padding: 10px;
box-sizing: border-box;
gap: 8px;
}
.SnackCatagoryContainer {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: flex-start;
row-gap: 25px;
column-gap: 20px;
padding: 10px 0;
}
.StoreCategory {
margin-bottom: 40px;
&:last-child {
margin-bottom: 0;
}
}
.StoreCategoryTitle {
font-family: inherit;
font-size: 1.8rem;
margin: 0 0 15px 0;
padding-bottom: 8px;
border-bottom: 3px groove var(--accent-2);
color: var(--card-raised);
}
+23 -4
View File
@@ -1,16 +1,35 @@
<script lang="ts" module>
import { type StoreEntity } from "./+page.server.ts";
import { snackImage } from "./func.svelte";
import { storeButton } from "$lib/StoreButtons.svelte";
import { ExternalLink } from "@lucide/svelte";
import "./snacks.scss";
export { snackProduct };
</script>
{#snippet snackProduct(product: StoreEntity)}
{#snippet snackProduct(product: StoreEntity, slug: string)}
<div class="SnackProductContainer">
<enhanced:img src={snackImage(product.image)} />
<a href="/store/{slug}" class="SnackProductLink">
<enhanced:img src={snackImage(product.images[0])} alt={product.name} />
</a>
<div class="SnackProductDetails">
<h1>{product.name}</h1>
<div class="SnackProductButtons"></div>
<div>
<h1 class="SnackProductName">
{product.name}
<a href="/store/{slug}" class="SnackProductPopOut">
<ExternalLink size={16} />
</a>
</h1>
<p>{product.description}</p>
</div>
<div class="SnackProductButtons">
{#if product.gumroad != undefined}
{@render storeButton("gumroad", product.gumroad!)}
{/if}
{#if product.jinxxy != undefined}
{@render storeButton("jinxxy", product.jinxxy!)}
{/if}
</div>
</div>
</div>
{/snippet}
+3 -1
View File
@@ -19,7 +19,9 @@
body {
background-image: url("/bg.png");
margin: 40px auto;
max-width: 1280px;
min-width: 0;
padding: 0 40px;
box-sizing: border-box;
}
header {