From b7a062fc0c3034998221199af3202d76ca60c214 Mon Sep 17 00:00:00 2001 From: DarthGigi <47110839+DarthGigi@users.noreply.github.com> Date: Sat, 6 Jun 2026 15:35:04 +0200 Subject: [PATCH 01/11] style: add dynamic glass utilities --- .changeset/clean-glass-utilities.md | 5 ++ src/app.css | 41 +++++++++ src/app.html | 2 +- src/context/preferences.svelte.spec.ts | 90 +++++++++++++++++++ src/context/preferences.svelte.ts | 6 +- .../components/header/settings/Misc.svelte | 4 +- .../header/settings/Settings.svelte | 11 ++- src/lib/components/item/Item.svelte | 2 +- src/lib/components/misc/CommandPalette.svelte | 12 ++- .../components/misc/CommandSearchGroup.svelte | 7 +- .../misc/CommandSettingsGroup.svelte | 3 +- .../components/misc/ContributorCard.svelte | 5 +- .../misc/ContributorCardSkeleton.svelte | 6 +- src/lib/components/misc/CtaCard.svelte | 6 +- src/lib/components/misc/Navbar.svelte | 3 +- .../components/newsroom/NewPostsToast.svelte | 7 +- src/lib/components/newsroom/PostCard.svelte | 6 +- src/lib/components/notices/BetaNotice.svelte | 9 +- src/lib/components/notices/Notice.svelte | 4 +- src/lib/components/stats/CardBuilder.svelte | 8 +- src/lib/layouts/stats/AdditionalStats.svelte | 7 +- src/lib/layouts/stats/Main.svelte | 6 +- src/lib/layouts/stats/PlayerProfile.svelte | 7 +- src/lib/sections/Sections.svelte | 5 +- src/lib/sections/stats/Bestiary.svelte | 2 +- src/lib/sections/stats/Collections.svelte | 2 +- src/lib/sections/stats/Rift.svelte | 4 +- src/lib/sections/stats/farming/garden.svelte | 10 +-- src/lib/sections/stats/misc/chips.svelte | 2 +- src/lib/sections/stats/skills/foraging.svelte | 2 +- src/lib/sections/stats/skills/mining.svelte | 2 +- src/routes/+error.svelte | 6 +- src/routes/+layout.svelte | 5 +- src/routes/+page.svelte | 13 ++- src/routes/login/+page.svelte | 6 +- src/routes/newsroom/+error.svelte | 6 +- src/routes/newsroom/+page.svelte | 11 +-- src/routes/newsroom/[slug]/+page.svelte | 8 +- .../stats/[ign]/[[profile]]/+error.svelte | 6 +- .../stats/[ign]/[[profile]]/+page.svelte | 3 +- 40 files changed, 216 insertions(+), 134 deletions(-) create mode 100644 .changeset/clean-glass-utilities.md diff --git a/.changeset/clean-glass-utilities.md b/.changeset/clean-glass-utilities.md new file mode 100644 index 000000000..d9598359e --- /dev/null +++ b/.changeset/clean-glass-utilities.md @@ -0,0 +1,5 @@ +--- +"skycrypt-frontend": patch +--- + +Convert performance-mode glass styling to dynamic Tailwind utilities. diff --git a/src/app.css b/src/app.css index 9d4ac0038..4c9d41df7 100644 --- a/src/app.css +++ b/src/app.css @@ -3,6 +3,8 @@ @source inline("{group-data-[rainbow=false]/html:,}{text-,bg-}minecraft-{0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f}"); @custom-variant dark (&:where(.dark, .dark *)); @custom-variant light (&:where(.light, .light *)); +@custom-variant performance (&:where([data-performance="true"], [data-performance="true"] *)); +@custom-variant standard (&:where([data-performance="false"], [data-performance="false"] *)); @plugin "tailwindcss-motion"; @@ -345,6 +347,45 @@ @apply overflow-hidden before:pointer-events-none before:absolute before:inset-0 before:z-8 before:size-full before:animate-shine before:rounded-lg before:bg-linear-to-t before:from-[oklch(1_0_0/0)] before:via-[oklch(1_0_0/0.50)] before:to-[oklch(0.77_0.09_243.21/0)]; } +@utility glass { + --glass-bg: transparent; + --glass-performance-bg: var(--color-background-grey); + --glass-brightness: 50%; + --glass-contrast: 100%; + + background-color: var(--glass-bg); + + @variant standard { + backdrop-filter: blur(var(--blur-lg)) brightness(var(--glass-brightness)) contrast(var(--glass-contrast)); + } + + @variant performance { + background-color: var(--glass-performance-bg); + } +} + +@utility glass-bg-* { + --glass-performance-bg: --value(--color-*, [color]); + --glass-performance-bg: --alpha(--value(--color-*, [color]) / calc(--modifier(integer) * 1%)); + --glass-performance-bg: --alpha(--value(--color-*, [color]) / --modifier([percentage])); +} + +@utility glass-standard-bg-* { + --glass-bg: --value(--color-*, [color]); + --glass-bg: --alpha(--value(--color-*, [color]) / calc(--modifier(integer) * 1%)); + --glass-bg: --alpha(--value(--color-*, [color]) / --modifier([percentage])); +} + +@utility glass-brightness-* { + --glass-brightness: calc(--value(integer) * 1%); + --glass-brightness: --value([percentage]); +} + +@utility glass-contrast-* { + --glass-contrast: calc(--value(integer) * 1%); + --glass-contrast: --value([percentage]); +} + @utility enchanted { filter: url(#enchanted-glint); } diff --git a/src/app.html b/src/app.html index 56e866700..9c5b3e780 100644 --- a/src/app.html +++ b/src/app.html @@ -1,5 +1,5 @@ - + diff --git a/src/context/preferences.svelte.spec.ts b/src/context/preferences.svelte.spec.ts index e073c382b..f56b9268a 100644 --- a/src/context/preferences.svelte.spec.ts +++ b/src/context/preferences.svelte.spec.ts @@ -7,10 +7,14 @@ import { PreferencesContext } from "./preferences.svelte"; describe("PreferencesContext Tests", () => { beforeEach(() => { localStorage.clear(); + delete document.documentElement.dataset.performance; + delete document.documentElement.dataset.rainbow; }); afterEach(() => { localStorage.clear(); + delete document.documentElement.dataset.performance; + delete document.documentElement.dataset.rainbow; }); describe("Initialization", () => { @@ -461,6 +465,90 @@ describe("PreferencesContext Tests", () => { }); }); + describe("performanceMode document.dataset", () => { + it("sets document.documentElement.dataset.performance to 'false' by default", ({ expect }) => { + const cleanup = $effect.root(() => { + const prefs = new PreferencesContext(); + + untrack(() => { + flushSync(); + + expect(prefs.performanceMode).toBe(false); + expect(document.documentElement.dataset.performance).toBe("false"); + }); + }); + + cleanup(); + }); + + it("sets document.documentElement.dataset.performance to 'true' when enabled", ({ expect }) => { + const cleanup = $effect.root(() => { + const prefs = new PreferencesContext(); + + untrack(() => { + prefs.performanceMode = true; + flushSync(); + + expect(document.documentElement.dataset.performance).toBe("true"); + }); + }); + + cleanup(); + }); + + it("updates document.dataset on toggle", ({ expect }) => { + const cleanup = $effect.root(() => { + const prefs = new PreferencesContext(); + + untrack(() => { + prefs.performanceMode = true; + flushSync(); + const first = document.documentElement.dataset.performance; + + prefs.performanceMode = false; + flushSync(); + const second = document.documentElement.dataset.performance; + + prefs.performanceMode = true; + flushSync(); + const third = document.documentElement.dataset.performance; + + expect(first).toBe("true"); + expect(second).toBe("false"); + expect(third).toBe("true"); + }); + }); + + cleanup(); + }); + + it("applies performance setting on construction via $effect.pre", ({ expect }) => { + localStorage.setItem( + "skycryptPreferences", + JSON.stringify({ + sectionOrder: sections, + performanceMode: true, + keybind: "/", + showGlint: true, + rainbowEnchantments: false, + mctooltip: false + }) + ); + + const cleanup = $effect.root(() => { + const prefs = new PreferencesContext(); + + untrack(() => { + flushSync(); + expect(document.documentElement.dataset.performance).toBe("true"); + expect(prefs.performanceMode).toBe(true); + }); + }); + + cleanup(); + }); + }); + describe("Migration via loadOldSettings", () => { it("migrates sectionOrderPreferences from old storage key", ({ expect }) => { const oldOrder: SectionID[] = [sections[2], sections[1], sections[0]]; @@ -488,6 +576,7 @@ describe("PreferencesContext Tests", () => { untrack(() => { flushSync(); expect(prefs.performanceMode).toBe(true); + expect(document.documentElement.dataset.performance).toBe("true"); expect(localStorage.getItem("performanceMode")).toBeNull(); }); }); @@ -504,6 +593,7 @@ describe("PreferencesContext Tests", () => { untrack(() => { flushSync(); expect(prefs.performanceMode).toBe(true); + expect(document.documentElement.dataset.performance).toBe("true"); expect(localStorage.getItem("performanceMode")).toBeNull(); }); }); diff --git a/src/context/preferences.svelte.ts b/src/context/preferences.svelte.ts index 0098376dc..1dca9ef44 100644 --- a/src/context/preferences.svelte.ts +++ b/src/context/preferences.svelte.ts @@ -29,7 +29,8 @@ export class PreferencesContext { untrack(() => { this.loadOldSettings(); this.sectionOrder = this.#data.current.sectionOrder; - // Apply rainbow setting on load + // Apply document-level styling flags on load. + this.performanceMode = !!this.performanceMode; this.rainbowEnchantments = !!this.rainbowEnchantments; }); }); @@ -74,6 +75,9 @@ export class PreferencesContext { set performanceMode(value: boolean) { this.#data.current = { ...this.#data.current, performanceMode: value }; + if (browser) { + document.documentElement.dataset.performance = value ? "true" : "false"; + } } get keybind() { diff --git a/src/lib/components/header/settings/Misc.svelte b/src/lib/components/header/settings/Misc.svelte index 9b068544d..10ed82fe2 100644 --- a/src/lib/components/header/settings/Misc.svelte +++ b/src/lib/components/header/settings/Misc.svelte @@ -1,7 +1,7 @@ {#snippet settings()} - + Packs @@ -64,7 +63,7 @@ {/snippet} - + {#snippet child({ props, open })} {#if open}
@@ -72,7 +71,7 @@ {/snippet}
- + {#snippet child({ props, open })} {#if open}
diff --git a/src/lib/components/item/Item.svelte b/src/lib/components/item/Item.svelte index 5d746ee50..25cab9a0f 100644 --- a/src/lib/components/item/Item.svelte +++ b/src/lib/components/item/Item.svelte @@ -39,7 +39,7 @@ { if (skyblockItem.containsItems) { diff --git a/src/lib/components/misc/CommandPalette.svelte b/src/lib/components/misc/CommandPalette.svelte index 0d746c29d..9122fdee6 100644 --- a/src/lib/components/misc/CommandPalette.svelte +++ b/src/lib/components/misc/CommandPalette.svelte @@ -1,9 +1,9 @@ {#snippet playerItem(item: { ign: string; uuid?: string })} - + diff --git a/src/lib/components/misc/CommandSettingsGroup.svelte b/src/lib/components/misc/CommandSettingsGroup.svelte index 0a5b26a7f..09df26af9 100644 --- a/src/lib/components/misc/CommandSettingsGroup.svelte +++ b/src/lib/components/misc/CommandSettingsGroup.svelte @@ -1,7 +1,6 @@ {#snippet tooltipContent()} @@ -36,7 +35,7 @@ {/snippet}
- + diff --git a/src/lib/components/misc/ContributorCardSkeleton.svelte b/src/lib/components/misc/ContributorCardSkeleton.svelte index 5bdce4bc3..541490a40 100644 --- a/src/lib/components/misc/ContributorCardSkeleton.svelte +++ b/src/lib/components/misc/ContributorCardSkeleton.svelte @@ -1,11 +1,7 @@ -
+
diff --git a/src/lib/components/misc/CtaCard.svelte b/src/lib/components/misc/CtaCard.svelte index eb8376dfa..ff4ca4296 100644 --- a/src/lib/components/misc/CtaCard.svelte +++ b/src/lib/components/misc/CtaCard.svelte @@ -1,6 +1,4 @@ - + {img.alt.slice(0, 2)} diff --git a/src/lib/components/misc/Navbar.svelte b/src/lib/components/misc/Navbar.svelte index 6ec682911..91bc75edf 100644 --- a/src/lib/components/misc/Navbar.svelte +++ b/src/lib/components/misc/Navbar.svelte @@ -4,7 +4,6 @@ import { getInternalState, getPreferences, getProfileContext } from "$ctx"; import ScrollAreaPrimitive from "$lib/components/ScrollAreaPrimitive.svelte"; import type { SectionName } from "$lib/sections/types"; - import { cn } from "$lib/shared/utils"; import ChevronLeft from "@lucide/svelte/icons/chevron-left"; import ChevronRight from "@lucide/svelte/icons/chevron-right"; import { Button, ScrollArea } from "bits-ui"; @@ -139,7 +138,7 @@ {#snippet viewportChildren()}
-
+
{#each filteredSectionOrderPreferences as section, index (index)} handleSectionClick(section.name)}> {section.name?.replaceAll("_", " ")} diff --git a/src/lib/components/newsroom/NewPostsToast.svelte b/src/lib/components/newsroom/NewPostsToast.svelte index e60b9efc7..b9ce76500 100644 --- a/src/lib/components/newsroom/NewPostsToast.svelte +++ b/src/lib/components/newsroom/NewPostsToast.svelte @@ -1,7 +1,6 @@ -
+
{#if thumb && newestUnseen.heroImage} diff --git a/src/lib/components/newsroom/PostCard.svelte b/src/lib/components/newsroom/PostCard.svelte index 9ba8c478b..c93beea32 100644 --- a/src/lib/components/newsroom/PostCard.svelte +++ b/src/lib/components/newsroom/PostCard.svelte @@ -1,8 +1,6 @@ - +
{#if thumb && post.heroImage} diff --git a/src/lib/components/notices/BetaNotice.svelte b/src/lib/components/notices/BetaNotice.svelte index 061e2d0e5..f11f6a9f8 100644 --- a/src/lib/components/notices/BetaNotice.svelte +++ b/src/lib/components/notices/BetaNotice.svelte @@ -1,6 +1,6 @@ @@ -31,14 +30,14 @@ {#snippet desktopNotice()} - + {#snippet child({ props, open })} {#if open}
{/if} {/snippet}
- + {#snippet child({ props, open })} {#if open}
diff --git a/src/lib/components/notices/Notice.svelte b/src/lib/components/notices/Notice.svelte index 0ce9bdcd1..82a7acd1a 100644 --- a/src/lib/components/notices/Notice.svelte +++ b/src/lib/components/notices/Notice.svelte @@ -1,5 +1,4 @@ -
+
{#if type === "error"} diff --git a/src/lib/components/stats/CardBuilder.svelte b/src/lib/components/stats/CardBuilder.svelte index 558bcd80f..51febc2af 100644 --- a/src/lib/components/stats/CardBuilder.svelte +++ b/src/lib/components/stats/CardBuilder.svelte @@ -1,7 +1,7 @@ @@ -118,7 +117,7 @@ Networth: {#if isHttpError(err)} - + {#snippet child({ wrapperProps, props, open })} {#if open}
diff --git a/src/lib/layouts/stats/Main.svelte b/src/lib/layouts/stats/Main.svelte index a85ff6851..2a8e0fd55 100644 --- a/src/lib/layouts/stats/Main.svelte +++ b/src/lib/layouts/stats/Main.svelte @@ -14,7 +14,7 @@ import Sections from "$lib/sections/Sections.svelte"; import type { ModelsStatsOutput } from "$lib/shared/api/orval-generated"; import { getCombined } from "$lib/shared/api/skycrypt-api.remote"; - import { cn, flyAndScale } from "$lib/shared/utils"; + import { flyAndScale } from "$lib/shared/utils"; import Image from "@lucide/svelte/icons/image"; import { Avatar, Dialog } from "bits-ui"; import { Pane } from "paneforge"; @@ -185,7 +185,7 @@ onResize={(size) => { rightSize = size; }}> -
+
@@ -218,7 +218,7 @@ {/if}
-
+
{#if getProfileContext().current}
diff --git a/src/lib/layouts/stats/PlayerProfile.svelte b/src/lib/layouts/stats/PlayerProfile.svelte index 196caa3ab..92cb77815 100644 --- a/src/lib/layouts/stats/PlayerProfile.svelte +++ b/src/lib/layouts/stats/PlayerProfile.svelte @@ -1,6 +1,6 @@
-
+

Oops! Something went wrong

Try again or contact us if the problem persists.

Go home diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 79b5f9dc9..a46a99943 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -12,7 +12,6 @@ import { listLatestPostsForNotifications } from "$lib/shared/api/cms-api.remote"; import { getPacks } from "$lib/shared/api/skycrypt-api.remote"; import { parseThemeFromURL } from "$lib/shared/themes/sharing"; - import { cn } from "$lib/shared/utils"; import Wifi from "@lucide/svelte/icons/wifi"; import WifiOff from "@lucide/svelte/icons/wifi-off"; import { Tooltip } from "bits-ui"; @@ -209,7 +208,7 @@ class="sm:mr-8" pauseWhenPageIsHidden={true} toastOptions={{ - class: cn("gap-2! font-semibold! group rounded-lg! text-text/80! border-none!", preferences.performanceMode ? "bg-background-grey!" : "backdrop-blur-lg! backdrop-brightness-50! bg-transparent!"), + class: "glass! gap-2! rounded-lg! border-none! font-semibold! text-text/80! glass-brightness-50", classes: { closeButton: "text-text/80! border-none! hover:opacity-60! bg-background-grey! hover:bg-background-grey!", @@ -244,7 +243,7 @@ {#if internalState.themeEditorOpen && !isMobile.current} -
+
{/if} diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index d2518fee0..08d273582 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -1,14 +1,13 @@
-
+
@@ -156,10 +153,10 @@ {#snippet pending()}
-
+
{#each new Array(3) as _, i (i)} -
+
@@ -176,7 +173,7 @@ {@const newsroom = await listPosts({ page: 1, limit: 3 })} {#if newsroom.docs.length > 0}
-
+

Newsroom

Latest announcements and updates

diff --git a/src/routes/login/+page.svelte b/src/routes/login/+page.svelte index cabb30c2b..699e465b2 100644 --- a/src/routes/login/+page.svelte +++ b/src/routes/login/+page.svelte @@ -1,15 +1,11 @@
-
+
diff --git a/src/routes/newsroom/+error.svelte b/src/routes/newsroom/+error.svelte index 184f4f723..ca03a2a28 100644 --- a/src/routes/newsroom/+error.svelte +++ b/src/routes/newsroom/+error.svelte @@ -1,14 +1,10 @@
-
+

{page.status === 404 ? "Post not found" : "Something went wrong"} diff --git a/src/routes/newsroom/+page.svelte b/src/routes/newsroom/+page.svelte index 4c6001e64..42a01120c 100644 --- a/src/routes/newsroom/+page.svelte +++ b/src/routes/newsroom/+page.svelte @@ -1,17 +1,14 @@
-
+

Oops! Something went wrong

An error occurred while trying to fetch the stats for '{page.params.ign}'

Try again or contact us if the problem persists.

diff --git a/src/routes/stats/[ign]/[[profile]]/+page.svelte b/src/routes/stats/[ign]/[[profile]]/+page.svelte index 26fa015cd..cf4b88952 100644 --- a/src/routes/stats/[ign]/[[profile]]/+page.svelte +++ b/src/routes/stats/[ign]/[[profile]]/+page.svelte @@ -8,7 +8,6 @@ import Main from "$lib/layouts/stats/Main.svelte"; import type { SectionName } from "$lib/sections/types"; import { getProfileStats } from "$lib/shared/api/skycrypt-api.remote"; - import { cn } from "$lib/shared/utils"; import LoaderCircle from "@lucide/svelte/icons/loader-circle"; import { type PageServerData } from "./$types"; @@ -47,7 +46,7 @@ {#snippet pending()}
-
+
Loading profile... From 2ba78417b17abb4815b78655d529835bd6e34568 Mon Sep 17 00:00:00 2001 From: DarthGigi <47110839+DarthGigi@users.noreply.github.com> Date: Sat, 6 Jun 2026 15:41:37 +0200 Subject: [PATCH 02/11] chore: move app.css to routes/layout.css and update references --- .changeset/brown-clowns-dress.md | 5 +++++ .prettierrc | 2 +- AGENTS.md | 2 +- src/lib/shared/themes/presets.ts | 2 +- src/lib/shared/themes/schema.ts | 4 ++-- src/routes/+layout.svelte | 2 +- src/{app.css => routes/layout.css} | 0 src/routes/stats/[ign]/[[profile]]/card/+server.ts | 2 +- 8 files changed, 12 insertions(+), 7 deletions(-) create mode 100644 .changeset/brown-clowns-dress.md rename src/{app.css => routes/layout.css} (100%) diff --git a/.changeset/brown-clowns-dress.md b/.changeset/brown-clowns-dress.md new file mode 100644 index 000000000..92f51afed --- /dev/null +++ b/.changeset/brown-clowns-dress.md @@ -0,0 +1,5 @@ +--- +"skycrypt-frontend": patch +--- + +Move app.css to routes/layout.css diff --git a/.prettierrc b/.prettierrc index 0f2cb621a..e2d48df97 100644 --- a/.prettierrc +++ b/.prettierrc @@ -14,7 +14,7 @@ } } ], - "tailwindStylesheet": "./src/app.css", + "tailwindStylesheet": "./src/routes/layout.css", "tailwindAttributes": ["class", "class:*", "class:name", "payload"], "tailwindFunctions": ["cn"], "tailwindPreserveWhitespace": false diff --git a/AGENTS.md b/AGENTS.md index 6d8628bab..c9f09a706 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -134,7 +134,7 @@ All content injection uses Svelte 5 snippets. No `` usage. ### Styling - Tailwind v4 primary, `cn()` helper (clsx + twMerge) from `$lib/shared/utils.ts` -- MC color CSS vars: `--§a` (green), `--§b` (aqua), `--§c` (red), etc. in `app.css` +- MC color CSS vars: `--§a` (green), `--§b` (aqua), `--§c` (red), etc. in `layout.css` - Theme plugin: `src/plugins/themes.ts` → `:root[data-theme="..."]` CSS vars ### Formatting diff --git a/src/lib/shared/themes/presets.ts b/src/lib/shared/themes/presets.ts index 3c290d241..34b79287a 100644 --- a/src/lib/shared/themes/presets.ts +++ b/src/lib/shared/themes/presets.ts @@ -1,5 +1,5 @@ /** - * Minecraft color palettes extracted from app.css utilities + * Minecraft color palettes extracted from layout.css utilities * Each palette maps §0–§f color codes to OKLCH color values */ diff --git a/src/lib/shared/themes/schema.ts b/src/lib/shared/themes/schema.ts index 7b5d5bc34..51d828915 100644 --- a/src/lib/shared/themes/schema.ts +++ b/src/lib/shared/themes/schema.ts @@ -7,7 +7,7 @@ import { z } from "zod"; * Organized into logical groups: colors, backgrounds, minecraft, enchantedGlint, meta. * * Color and background properties are OPTIONAL — when omitted, the CSS cascade - * provides the correct values (e.g., the `light` utility class in app.css). + * provides the correct values (e.g., the `light` utility class in layout.css). * Only DEFAULT_THEME is expected to have all properties fully specified. */ @@ -91,7 +91,7 @@ const backgroundsSchema = z.object({ * * Color and background properties are individually optional. * When a CSS property is omitted, it won't be applied to the DOM, - * allowing the CSS cascade (e.g., app.css light/dark defaults) to take effect. + * allowing the CSS cascade (e.g., layout.css light/dark defaults) to take effect. */ export const themeV3Schema = z.object({ schema: z.literal(3), diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index a46a99943..74e872d55 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -22,7 +22,7 @@ import { writable } from "svelte/store"; import { fly } from "svelte/transition"; import { Drawer } from "vaul-svelte"; - import "../app.css"; + import "./layout.css"; let { children }: { children: Snippet } = $props(); let isMobile = $state(new IsMobile()); diff --git a/src/app.css b/src/routes/layout.css similarity index 100% rename from src/app.css rename to src/routes/layout.css diff --git a/src/routes/stats/[ign]/[[profile]]/card/+server.ts b/src/routes/stats/[ign]/[[profile]]/card/+server.ts index 4a25e5b82..32fde4610 100644 --- a/src/routes/stats/[ign]/[[profile]]/card/+server.ts +++ b/src/routes/stats/[ign]/[[profile]]/card/+server.ts @@ -1,6 +1,6 @@ import { building, dev } from "$app/environment"; import { env } from "$env/dynamic/public"; -import appStyles from "$src/app.css?inline"; +import appStyles from "$routes/layout.css?inline"; import { DefaultCard } from "$src/lib/components/cards"; import ErrorCard from "$src/lib/components/cards/default/ErrorCard.svelte"; import { parseSettingsFromParams } from "$src/lib/components/cards/default/schema"; From bd953662c9e8425fa0b9b55af66e7348ed3c6de8 Mon Sep 17 00:00:00 2001 From: DarthGigi <47110839+DarthGigi@users.noreply.github.com> Date: Tue, 16 Jun 2026 16:17:02 +0200 Subject: [PATCH 03/11] feat: update Tailwind CSS configuration and integrate new utility paths --- .prettierrc | 10 +++++----- .vscode/settings.json | 11 +++++++++-- vite.config.ts | 20 ++++++++++++++++---- 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/.prettierrc b/.prettierrc index e2d48df97..b218a0006 100644 --- a/.prettierrc +++ b/.prettierrc @@ -6,6 +6,10 @@ "bracketSameLine": true, "printWidth": 999999, "plugins": ["prettier-plugin-svelte", "prettier-plugin-tailwindcss"], + "tailwindStylesheet": "src/routes/layout.css", + "tailwindAttributes": ["class", "class:*", "class:name", "payload", "/.*Classes/"], + "tailwindFunctions": ["cn", "clsx", "payload"], + "tailwindPreserveWhitespace": false, "overrides": [ { "files": "*.svelte", @@ -13,9 +17,5 @@ "parser": "svelte" } } - ], - "tailwindStylesheet": "./src/routes/layout.css", - "tailwindAttributes": ["class", "class:*", "class:name", "payload"], - "tailwindFunctions": ["cn"], - "tailwindPreserveWhitespace": false + ] } diff --git a/.vscode/settings.json b/.vscode/settings.json index c9e1763da..aa2520306 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -12,9 +12,10 @@ "git.autofetch": true, "svelte.enable-ts-plugin": true, "svelte.plugin.svelte.defaultScriptLanguage": "ts", - "tailwindCSS.classAttributes": ["class", "class:*", "class:name", "payload"], + "tailwindCSS.emmetCompletions": true, - "tailwindCSS.classFunctions": ["cn", "clsx"], + "tailwindCSS.colorDecorators": true, + "tailwindCSS.experimental.configFile": "./src/routes/layout.css", "tailwindCSS.includeLanguages": { "html": "html", "plaintext": "html", @@ -22,6 +23,12 @@ "typescript": "typescript", "svelte": "html" }, + "tailwindCSS.classFunctions": ["cn", "clsx", "payload"], + "tailwindCSS.classAttributes": ["class", "className", "ngClass", "class:list", "payload"], + "tailwindCSS.experimental.classRegex": [ + ["\\b\\w*Classes\\s*=\\s*[\"']([^\"']*)[\"']", "([^\\s]+)"], + ["\\b\\w*Classes\\s*=\\s*\\{\\s*[\"']([^\"']*)[\"']\\s*\\}", "([^\\s]+)"] + ], "js/ts.updateImportsOnFileMove.enabled": "prompt", "eslint.validate": ["javascript", "typescript", "svelte"], "prettier.documentSelectors": ["**/*.svelte"], diff --git a/vite.config.ts b/vite.config.ts index 4ba5a4061..09d4c6256 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -13,7 +13,6 @@ export default defineConfig({ project: "skycrypt-sveltekit", adapter: "node" }), - tailwindcss(), sveltekit({ // Consult https://svelte.dev/docs/kit/integrations // for more information about preprocessors @@ -32,7 +31,13 @@ export default defineConfig({ $constants: "./src/lib/server/constants", $ctx: "./src/context", $routes: "./src/routes", - $src: "./src" + $src: "./src", + $ui: "./src/lib/components/ui", + $lib: "./src/lib", + $utils: "./src/lib/shared/utils.ts", + $hooks: "./src/lib/hooks", + $components: "./src/lib/components", + "$utils.js": "./src/lib/shared/utils.ts" }, csrf: { trustedOrigins: ["https://cupcake.shiiyu.moe", "https://sky.shiiyu.moe", "http://localhost:5173", "http://localhost:4173", "http://localhost:3000", "http://localhost:8080"] @@ -43,7 +48,7 @@ export default defineConfig({ "script-src": ["self", "unsafe-inline"], "worker-src": ["self", "blob:"], "style-src": ["self", "unsafe-inline", "https://fonts.googleapis.com"], - "img-src": ["self", "data:", "https://textures.minecraft.net", "http://localhost:8080", "https://cupcake.shiiyu.moe", "https://sky.shiiyu.moe", "https://nmsr.nickac.dev", "https://cms.shiiyu.moe", "http://localhost:3000"], + "img-src": ["self", "data:", "https://textures.minecraft.net", "http://localhost:8080", "https://cupcake.shiiyu.moe", "https://sky.shiiyu.moe", "https://nmsr.nickac.dev", "https://cms.shiiyu.moe", "http://localhost:3000", "https://eliteskyblock.com"], "connect-src": ["self", "https://mowojang.matdoes.dev", "https://mowojang.seraph.si", "http://localhost:8080", "https://cupcake.shiiyu.moe", "https://sky.shiiyu.moe", "https://cms.shiiyu.moe", "http://localhost:3000"], "font-src": ["self", "https://fonts.gstatic.com"], "frame-ancestors": ["self", "https://cms.shiiyu.moe", "http://localhost:3000"], @@ -60,8 +65,15 @@ export default defineConfig({ ...config, include: [...config.include, "../drizzle.config.ts"] }) + }, + vitePlugin: { + experimental: { + sendWarningsToBrowser: process.env.NODE_ENV === "development" + }, + inspector: process.env.NODE_ENV === "development" } - }) + }), + tailwindcss() ], build: { sourcemap: true }, test: { From 7244b342c921940cfae96ef9b856def4e7a93430 Mon Sep 17 00:00:00 2001 From: DarthGigi <47110839+DarthGigi@users.noreply.github.com> Date: Tue, 16 Jun 2026 16:17:33 +0200 Subject: [PATCH 04/11] feat: add optional 'important' parameter to getRarityClass function --- src/lib/shared/helper.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/shared/helper.ts b/src/lib/shared/helper.ts index 6e47ceebd..213ed106b 100644 --- a/src/lib/shared/helper.ts +++ b/src/lib/shared/helper.ts @@ -44,10 +44,10 @@ export function titleCase(string: string): string { * @param {"bg" | "text"} type the type of color to get * @returns {string} the tailwind css color class */ -export function getRarityClass(rarity: string, type: "bg" | "text"): string { +export function getRarityClass(rarity: string, type: "bg" | "text", important?: true): string { const rarityColor = RARITY_COLORS[rarity.toLowerCase() as keyof typeof RARITY_COLORS]; // minecraft colors are safelisted in the tailwind config, so they are always generated - return rarityColor ? `${type}-minecraft-${rarityColor}` : ""; + return rarityColor ? `${type}-minecraft-${rarityColor}${important ? "!" : ""}` : ""; } /** From 84ec8b391f49c24f522912dee7632b6e80398657 Mon Sep 17 00:00:00 2001 From: DarthGigi <47110839+DarthGigi@users.noreply.github.com> Date: Tue, 16 Jun 2026 16:25:39 +0200 Subject: [PATCH 05/11] feat: enhance layout styles with new utility classes and font adjustments --- src/routes/layout.css | 440 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 364 insertions(+), 76 deletions(-) diff --git a/src/routes/layout.css b/src/routes/layout.css index 4c9d41df7..130c9132c 100644 --- a/src/routes/layout.css +++ b/src/routes/layout.css @@ -1,8 +1,12 @@ @import "tailwindcss"; +@import "tw-animate-css"; +@import "shadcn-svelte/tailwind.css"; +@import "@fontsource-variable/montserrat"; +@import "@fontsource/unifontex"; @source "app.html"; -@source inline("{group-data-[rainbow=false]/html:,}{text-,bg-}minecraft-{0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f}"); -@custom-variant dark (&:where(.dark, .dark *)); -@custom-variant light (&:where(.light, .light *)); +@source inline("{group-data-[rainbow=false]/html:,}{text-,bg-}minecraft-{0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f}{,!}"); +@custom-variant dark (&:is(.dark *)); +@custom-variant light (&:is(.light *)); @custom-variant performance (&:where([data-performance="true"], [data-performance="true"] *)); @custom-variant standard (&:where([data-performance="false"], [data-performance="false"] *)); @@ -13,7 +17,7 @@ --color-icon: var(--icon); --color-link: var(--link); --color-hover: var(--hover); - --color-skillbar: var(--skillbar); + --color-skillbar: var(--primary); --color-maxedbar: var(--maxedbar); --color-maxed: var(--maxed); --color-gold: var(--gold); @@ -58,10 +62,51 @@ } /* Fonts */ - --font-icomoon: "icomoon", Montserrat; - --font-sans: Montserrat, ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; - --font-minecraft: "Minecraft", var(--font-icomoon), var(--font-sans); - --font-minecraft-upper: "Minecraft-Upper", var(--font-sans); + --font-sans: "Montserrat Variable", ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + --font-skyblock-icons: "SkyBlockIcons", var(--font-sans); + --font-unifontex: "UnifontEX", var(--font-sans); + --font-minecraft: "Minecraft", var(--font-unifontex), var(--font-sans); + --font-heading: var(--font-sans); + --color-sidebar-ring: var(--sidebar-ring); + --color-sidebar-border: var(--sidebar-border); + --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); + --color-sidebar-accent: var(--sidebar-accent); + --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); + --color-sidebar-primary: var(--sidebar-primary); + --color-sidebar-foreground: var(--sidebar-foreground); + --color-sidebar: var(--sidebar); + --color-chart-5: var(--chart-5); + --color-chart-4: var(--chart-4); + --color-chart-3: var(--chart-3); + --color-chart-2: var(--chart-2); + --color-chart-1: var(--chart-1); + --color-ring: var(--ring); + --color-input: var(--input); + --color-border: var(--border); + --color-destructive: var(--destructive); + --color-accent-foreground: var(--accent-foreground); + --color-accent: var(--accent); + --color-accent-2: var(--accent-2); + --color-accent-3: var(--accent-3); + --color-accent-4: var(--accent-4); + --color-muted-foreground: var(--muted-foreground); + --color-muted: var(--muted); + --color-secondary-foreground: var(--secondary-foreground); + --color-secondary: var(--secondary); + --color-primary-foreground: var(--primary-foreground); + --color-primary: var(--primary); + --color-popover-foreground: var(--popover-foreground); + --color-popover: var(--popover); + --color-card-foreground: var(--card-foreground); + --color-card: var(--card); + --color-foreground: var(--foreground); + --radius-sm: calc(var(--radius) * 0.6); + --radius-md: calc(var(--radius) * 0.8); + --radius-lg: var(--radius); + --radius-xl: calc(var(--radius) * 1.4); + --radius-2xl: calc(var(--radius) * 1.8); + --radius-3xl: calc(var(--radius) * 2.2); + --radius-4xl: calc(var(--radius) * 2.6); } @theme inline { @@ -85,63 +130,23 @@ @layer base { @font-face { - font-family: "Montserrat"; - font-style: italic; - font-weight: 100 900; - font-display: swap; - src: url("/fonts/montserrat/montserrat-italic.woff2") format("woff2"); - unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; - } - - @font-face { - font-family: "Montserrat"; - font-style: normal; - font-weight: 100 900; - font-display: swap; - src: url("/fonts/montserrat/montserrat-normal.woff2") format("woff2"); - unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; - } - - @font-face { - font-family: "icomoon"; - src: - url("/fonts/icomoon/icomoon.woff2") format("woff2"), - url("/fonts/icomoon/icomoon.woff") format("woff"), - url("/fonts/icomoon/icomoon.ttf") format("truetype"), - url("/fonts/icomoon/icomoon.svg#icomoon") format("svg"); - font-weight: normal; + font-family: "SkyBlockIcons"; font-style: normal; font-display: block; + font-weight: 400; + src: + url("@fontsource/unifontex/files/unifontex-latin-400-normal.woff2") format("woff2"), + url("@fontsource/unifontex/files/unifontex-latin-400-normal.woff") format("woff"); unicode-range: - /* ✪ dungeon-star */ - U+272A, - /* ⍟ dungeon-master-star (no longer used) */ U+235F, - /* ⚔ attack-speed */ U+2694, - /* ☣ critical-chance */ U+2623, - /* ☠ critical-damage */ U+2620, - /* ❈ defense */ U+2748, - /* ☘ fortune */ U+2618, - /* ⫽ ferocity */ U+2AFD, - /* ❤ health */ U+2764, - /* ✎ intelligence */ U+270E, - /* ✯ magic-find */ U+272F, - /* ⸕ mining-speed */ U+2E15, - /* ♣ pet-luck */ U+2663, - /* ✧ pristine */ U+2727, - /* α sea-creature-chance */ U+03B1, - /* ✦ speed */ U+2726, - /* ❁ strength */ U+2741, - /* ๑ ability-damage */ U+0E51, - /* ➊ 1-dungeon-star */ U+278A, - /* ➋ 2-dungeon-star */ U+278B, - /* ➌ 3-dungeon-star */ U+278C, - /* ➍ 4-dungeon-star */ U+278D, - /* ➎ 5-dungeon-star */ U+278E, - /* ❂ true-defense, */ U+2742, - /* ⸎ soulflow */ U+2E0E, - /* ᠅ powder, */ U+1805, - /* ✿ dye, */ U+273F, - /* ⚚ dungeon-upgrade, */ U+269A; + /* Greek and Coptic, e.g. α */ + U+0370-03FF, + /* Malayalam, e.g. ൠ */ U+0D00-0D7F, + /* Thai, e.g. ๑ */ U+0E00-0E7F, + /* Mongolian, e.g. ᠅ */ U+1800-18AF, + /* Letterlike and enclosed symbols, e.g. Ⓟ and Ⓢ */ U+2100-24FF, + /* Box drawing, symbols, dingbats, arrows, operators, e.g. ❤, ☘, ⚔, ➊ */ U+2500-2BFF, + /* Supplemental punctuation, e.g. ⸕ and ⸎ */ U+2E00-2E7F, + /* Text presentation selector for emoji-capable symbols */ U+FE0E; } @font-face { @@ -152,19 +157,11 @@ font-display: swap; } - @font-face { - font-family: "Minecraft-Upper"; - src: url("/fonts/minecraft/MinecraftTenv2-Regular.woff2") format("woff2"); - font-weight: normal; - font-style: normal; - font-display: swap; - text-transform: uppercase; - } - /* For color preview to work you need to have the 'naumovs.color-highlight' extension installed */ :root { /* Icon Green (used for Skill Icons, Underlines etc.) */ - --icon: oklch(73.62% 0.2129 147.69); + /* --icon: oklch(73.62% 0.2129 147.69); */ + --icon: var(--chart-2); /* Link Green (used for Links, Unclaimed Slayers, Crafted Minions etc.) */ --link: oklch(81.56% 0.2459 146.24); @@ -173,7 +170,8 @@ --hover: oklch(83.81% 0.2303 149.89); /* Skill Bar Green (used for Skill Progress Bars) */ - --skillbar: oklch(63.98% 0.1731 150.18); + /* --skillbar: oklch(63.98% 0.1731 150.18); */ + --skillbar: var(--primary); /* Maxed Bar Gold (used for Maxed Progress Bars) */ --maxedbar: oklch(69.69% 0.1423 76.74); @@ -189,8 +187,6 @@ /* Most of the text */ --text: oklch(1 0 0); - /* background to make text more visible */ - --background: oklch(0 0 0); /* background of the header */ --header: oklch(0.28 0 0); /* used for info box and theme/pack selector */ @@ -226,6 +222,79 @@ --§f: oklch(0.66 0 0); color-scheme: dark; + + --background: oklch(1 0 0); + --foreground: oklch(0.145 0 0); + --card: oklch(1 0 0); + --card-foreground: oklch(0.145 0 0); + --popover: oklch(1 0 0); + --popover-foreground: oklch(0.145 0 0); + --primary: var(--chart-3); + --primary-foreground: oklch(0.982 0.018 155.826); + --secondary: oklch(0.967 0.001 286.375); + --secondary-foreground: oklch(0.21 0.006 285.885); + --muted: oklch(0.97 0 0); + --muted-foreground: oklch(0.556 0 0); + --accent: oklch(0.527 0.154 150.069); + --accent-foreground: oklch(0.982 0.018 155.826); + --accent-2: oklch(72.84% 0.1506 75.86); + --accent-3: oklch(69.69% 0.1423 76.74); + --accent-4: oklch(82.84% 0.1548 78.27); + --destructive: oklch(0.577 0.245 27.325); + --border: oklch(0.922 0 0); + --input: oklch(0.922 0 0); + --ring: oklch(0.708 0 0); + --chart-1: oklch(0.871 0.15 154.449); + --chart-2: oklch(0.723 0.219 149.579); + --chart-3: oklch(0.627 0.194 149.214); + --chart-4: oklch(0.527 0.154 150.069); + --chart-5: oklch(0.448 0.119 151.328); + --radius: 0.625rem; + --sidebar: oklch(0.985 0 0); + --sidebar-foreground: oklch(0.145 0 0); + --sidebar-primary: oklch(0.627 0.194 149.214); + --sidebar-primary-foreground: oklch(0.982 0.018 155.826); + --sidebar-accent: oklch(0.97 0 0); + --sidebar-accent-foreground: oklch(0.205 0 0); + --sidebar-border: oklch(0.922 0 0); + --sidebar-ring: oklch(0.708 0 0); + } + + .dark { + --background: oklch(0.145 0 0); + --foreground: oklch(0.985 0 0); + --card: oklch(0.205 0 0); + --card-foreground: oklch(0.985 0 0); + --popover: oklch(0.205 0 0); + --popover-foreground: oklch(0.985 0 0); + --primary: var(--chart-3); + --primary-foreground: oklch(0.982 0.018 155.826); + --secondary: oklch(0.274 0.006 286.033); + --secondary-foreground: oklch(0.985 0 0); + --muted: oklch(0.269 0 0); + --muted-foreground: oklch(0.708 0 0); + --accent: oklch(0.448 0.119 151.328); + --accent-foreground: oklch(0.982 0.018 155.826); + --accent-2: oklch(72.84% 0.1506 75.86); + --accent-3: oklch(69.69% 0.1423 76.74); + --accent-4: oklch(82.84% 0.1548 78.27); + --destructive: oklch(0.704 0.191 22.216); + --border: oklch(1 0 0 / 10%); + --input: oklch(1 0 0 / 15%); + --ring: oklch(0.556 0 0); + --chart-1: oklch(0.871 0.15 154.449); + --chart-2: oklch(0.723 0.219 149.579); + --chart-3: oklch(0.627 0.194 149.214); + --chart-4: oklch(0.527 0.154 150.069); + --chart-5: oklch(0.448 0.119 151.328); + --sidebar: oklch(0.205 0 0); + --sidebar-foreground: oklch(0.985 0 0); + --sidebar-primary: oklch(0.723 0.219 149.579); + --sidebar-primary-foreground: oklch(0.982 0.018 155.826); + --sidebar-accent: oklch(0.269 0 0); + --sidebar-accent-foreground: oklch(0.985 0 0); + --sidebar-border: oklch(1 0 0 / 10%); + --sidebar-ring: oklch(0.556 0 0); } ::-webkit-scrollbar { @@ -281,6 +350,39 @@ clip-path: polygon(50% -71%, -50% 71%, 50% 171%, 171% 50%); } } + + @keyframes scroll-fade-out { + from { + opacity: 1; + } + to { + opacity: 0; + } + } + + * { + @apply border-border outline-ring/50; + } + + body { + @apply bg-background text-foreground; + } + + html { + @apply scrollbar-gutter-stable font-sans; + } + + [data-slot="scroll-area-thumb"] { + @apply bg-primary! group-data-[orientation=horizontal]/scroll:px-2 group-data-[orientation=vertical]/scroll:py-2; + } + + [data-slot="collapsible-content"] { + @apply overflow-clip duration-150 ease-out data-[state=closed]:animate-collapsible-up data-[state=open]:animate-collapsible-down; + } + + .\@container-scroll { + container-type: scroll-state; + } } @layer components { @@ -340,7 +442,8 @@ --grey_background: oklch(0.92 0 0); --lore_background: oklch(1 0 0 / 0.93); - --bg: oklch(1 0 0) color-scheme: light; + --bg: oklch(1 0 0); + color-scheme: light; } @utility shine { @@ -461,3 +564,188 @@ @utility minecraft-tooltip { @apply relative rounded-sm border-2 border-solid border-transparent bg-mctooltip-bg px-1 pt-1 pb-0.75 indent-[initial] font-minecraft text-[0.9375rem] leading-4.5 font-normal text-pretty [border-image:linear-gradient(to_bottom,oklch(48.503%_0.297_278.42/0.31),oklch(29.365%_0.17619_281.21/0.31))_1] text-shadow-[0.09375rem_0.09375rem_oklch(36.768%,0.00004,271.152)]; } + +@utility hit-area-debug { + position: relative; + &::before { + content: ""; + position: absolute; + top: var(--hit-area-t, 0px); + right: var(--hit-area-r, 0px); + bottom: var(--hit-area-b, 0px); + left: var(--hit-area-l, 0px); + pointer-events: inherit; + @apply border border-dashed border-blue-500 bg-blue-500/10; + } + &:hover::before { + @apply border border-dashed border-green-500 bg-green-500/10; + } +} + +@utility hit-area { + position: relative; + &::before { + content: ""; + position: absolute; + top: var(--hit-area-t, 0px); + right: var(--hit-area-r, 0px); + bottom: var(--hit-area-b, 0px); + left: var(--hit-area-l, 0px); + pointer-events: inherit; + } +} + +@utility hit-area-* { + position: relative; + --hit-area-t: --spacing(--value(number) * -1); + --hit-area-t: calc(--value([*]) * -1); + --hit-area-b: --spacing(--value(number) * -1); + --hit-area-b: calc(--value([*]) * -1); + --hit-area-l: --spacing(--value(number) * -1); + --hit-area-l: calc(--value([*]) * -1); + --hit-area-r: --spacing(--value(number) * -1); + --hit-area-r: calc(--value([*]) * -1); + &::before { + content: ""; + position: absolute; + top: var(--hit-area-t, 0px); + right: var(--hit-area-r, 0px); + bottom: var(--hit-area-b, 0px); + left: var(--hit-area-l, 0px); + pointer-events: inherit; + } +} + +@utility hit-area-l-* { + position: relative; + --hit-area-l: --spacing(--value(number) * -1); + --hit-area-l: calc(--value([*]) * -1); + &::before { + content: ""; + position: absolute; + top: var(--hit-area-t, 0px); + right: var(--hit-area-r, 0px); + bottom: var(--hit-area-b, 0px); + left: var(--hit-area-l, 0px); + pointer-events: inherit; + } +} + +@utility hit-area-r-* { + position: relative; + --hit-area-r: --spacing(--value(number) * -1); + --hit-area-r: calc(--value([*]) * -1); + &::before { + content: ""; + position: absolute; + top: var(--hit-area-t, 0px); + right: var(--hit-area-r, 0px); + bottom: var(--hit-area-b, 0px); + left: var(--hit-area-l, 0px); + pointer-events: inherit; + } +} + +@utility hit-area-t-* { + position: relative; + --hit-area-t: --spacing(--value(number) * -1); + --hit-area-t: calc(--value([*]) * -1); + &::before { + content: ""; + position: absolute; + top: var(--hit-area-t, 0px); + right: var(--hit-area-r, 0px); + bottom: var(--hit-area-b, 0px); + left: var(--hit-area-l, 0px); + pointer-events: inherit; + } +} + +@utility hit-area-b-* { + position: relative; + --hit-area-b: --spacing(--value(number) * -1); + --hit-area-b: calc(--value([*]) * -1); + &::before { + content: ""; + position: absolute; + top: var(--hit-area-t, 0px); + right: var(--hit-area-r, 0px); + bottom: var(--hit-area-b, 0px); + left: var(--hit-area-l, 0px); + pointer-events: inherit; + } +} + +@utility hit-area-x-* { + position: relative; + --hit-area-l: --spacing(--value(number) * -1); + --hit-area-l: calc(--value([*]) * -1); + --hit-area-r: --spacing(--value(number) * -1); + --hit-area-r: calc(--value([*]) * -1); + &::before { + content: ""; + position: absolute; + top: var(--hit-area-t, 0px); + right: var(--hit-area-r, 0px); + bottom: var(--hit-area-b, 0px); + left: var(--hit-area-l, 0px); + pointer-events: inherit; + } +} + +@utility hit-area-y-* { + position: relative; + --hit-area-t: --spacing(--value(number) * -1); + --hit-area-t: calc(--value([*]) * -1); + --hit-area-b: --spacing(--value(number) * -1); + --hit-area-b: calc(--value([*]) * -1); + &::before { + content: ""; + position: absolute; + top: var(--hit-area-t, 0px); + right: var(--hit-area-r, 0px); + bottom: var(--hit-area-b, 0px); + left: var(--hit-area-l, 0px); + pointer-events: inherit; + } +} + +/* On the scroll container: expose a named scroll-progress timeline per axis. */ +@utility scroll-fade-track-y { + scroll-timeline-name: --scroll-fade-y; + scroll-timeline-axis: block; +} + +@utility scroll-fade-track-x { + scroll-timeline-name: --scroll-fade-x; + scroll-timeline-axis: inline; +} + +@utility scroll-fade-track-both { + scroll-timeline-name: --scroll-fade-y, --scroll-fade-x; + scroll-timeline-axis: block, inline; +} + +@utility scroll-fade-y { + opacity: 0; + animation-name: scroll-fade-out; + animation-timing-function: linear; + animation-fill-mode: both; + animation-timeline: --scroll-fade-y; +} + +@utility scroll-fade-x { + opacity: 0; + animation-name: scroll-fade-out; + animation-timing-function: linear; + animation-fill-mode: both; + animation-timeline: --scroll-fade-x; +} + +@custom-variant @stuck-top { + @supports (container-type: scroll-state) { + @container scroll-state(stuck: top) { + @slot; + } + } +} From a80e39162044f99f6fdfdb04e6a7f6355f712702 Mon Sep 17 00:00:00 2001 From: DarthGigi <47110839+DarthGigi@users.noreply.github.com> Date: Tue, 16 Jun 2026 16:26:46 +0200 Subject: [PATCH 06/11] chore(fonts): remove unused fonts --- static/fonts/icomoon/README.md | 30 -------------- static/fonts/icomoon/icomoon.svg | 38 ------------------ static/fonts/icomoon/icomoon.ttf | Bin 8828 -> 0 bytes static/fonts/icomoon/icomoon.woff | Bin 8904 -> 0 bytes static/fonts/icomoon/icomoon.woff2 | Bin 5020 -> 0 bytes static/fonts/icomoon/selection.json | 36 ----------------- .../minecraft/MinecraftTenv2-Regular.woff2 | Bin 8912 -> 0 bytes .../fonts/montserrat/montserrat-italic.woff2 | Bin 37120 -> 0 bytes .../fonts/montserrat/montserrat-normal.woff2 | Bin 35508 -> 37956 bytes 9 files changed, 104 deletions(-) delete mode 100644 static/fonts/icomoon/README.md delete mode 100644 static/fonts/icomoon/icomoon.svg delete mode 100644 static/fonts/icomoon/icomoon.ttf delete mode 100644 static/fonts/icomoon/icomoon.woff delete mode 100644 static/fonts/icomoon/icomoon.woff2 delete mode 100644 static/fonts/icomoon/selection.json delete mode 100644 static/fonts/minecraft/MinecraftTenv2-Regular.woff2 delete mode 100644 static/fonts/montserrat/montserrat-italic.woff2 diff --git a/static/fonts/icomoon/README.md b/static/fonts/icomoon/README.md deleted file mode 100644 index da3ab0117..000000000 --- a/static/fonts/icomoon/README.md +++ /dev/null @@ -1,30 +0,0 @@ -# SkyCrypt custom icon font - -This font is loaded on top of the normal fonts and replaces only specific characters (icons such as the item stars, dungeon master stars) with svg icons. - -## How to edit - -You can import _selection.json_ back to the IcoMoon app using the _Import Icons_ button (or via Main Menu → Manage Projects) to retrieve your icon selection. - -## How to add new icons/characters - -First off find the UNICODE character you want to edit, you can use [this website](https://www.babelstone.co.uk/Unicode/whatisit.html). - -Then import the icomoon font in the app and add a new character by dropping an svg in the selection. At this point go to "Generate Font" and make sure to associate your newly imported icon to the correct character. - -If you want you can resize the icon: - -- for dungeon stars and dungeon master stars I scaled down 10 times the icons (by using IcoMoon GUI, clicking 10 times the "scale down" button) and then aligned the svg bottom center -- for skill icons I kept their original size and centered them middle center. - -Download the generated SVG font, replace the files in the `/public/resources/fonts/icomoon/` directory: - -- Font files -- selection.json - -Update the `_fonts.scss` file: - -- Bump the cachebusting version (ex: `?v2` -> `?v3`) -- Add the UNICODE characters to the list in the css property `unicode-range` - -And you are done! diff --git a/static/fonts/icomoon/icomoon.svg b/static/fonts/icomoon/icomoon.svg deleted file mode 100644 index 97319566e..000000000 --- a/static/fonts/icomoon/icomoon.svg +++ /dev/null @@ -1,38 +0,0 @@ - - - -Generated by IcoMoon - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/static/fonts/icomoon/icomoon.ttf b/static/fonts/icomoon/icomoon.ttf deleted file mode 100644 index 63df20ab4e6b351954ddff80f7eba5ade90786bd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8828 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 J_@%tJ{{O4CcJ%-N diff --git a/static/fonts/icomoon/icomoon.woff b/static/fonts/icomoon/icomoon.woff deleted file mode 100644 index 02f7b8fcb0e772db224729882ddd3c37094bfe59..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8904 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 diff --git a/static/fonts/icomoon/selection.json b/static/fonts/icomoon/selection.json deleted file mode 100644 index 6130dc09a..000000000 --- a/static/fonts/icomoon/selection.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "IcoMoonType": "selection", - "icons": [ - { "icon": { "paths": ["M0 144.22q49.18-2.62 95.72-6.22t82.6-3.6q8.5 0 19.34 6.54c8.288 5.305 15.405 11.493 21.515 18.575l0.105 0.125c7.604 8.655 14.467 18.317 20.28 28.648l0.44 0.852c6.268 10.948 11.827 23.645 16.005 36.953l0.375 1.387c17.11-13.028 37.678-22.451 60.071-26.735l0.909-0.145v-68.18c3.638 1.806 7.865 3.277 12.293 4.2l0.347 0.060c5.222 1.043 11.227 1.64 17.37 1.64s12.147-0.597 17.957-1.736l-0.587 0.096c4.824-0.974 9.1-2.446 13.097-4.4l-0.317 0.14v68.18c23.301 4.437 43.867 13.859 61.339 27.141l-0.359-0.261c4.553-14.695 10.112-27.392 16.886-39.308l-0.506 0.968c6.235-11.185 13.079-20.847 20.828-29.696l-0.168 0.196c6.215-7.207 13.332-13.395 21.234-18.468l0.386-0.232q10.82-6.54 19.34-6.54 36 0 82.62 3.6t95.7 6.22v29.5l-118.66-7.86 104.32 28.14-11.14 26.88-109.48-34.7 88.5 50.48-22.36 19.66-85.82-51.12 62.28 59.66-29.5 11.14-57.68-59.66 30.16 61.66h-30.16l-33.44-53.8-11.84 36.72c8.42 12.144 15.337 26.172 20.025 41.185l0.295 1.095c4.583 14.49 7.223 31.154 7.223 48.435 0 0.374-0.001 0.748-0.004 1.122l0-0.057c0.002 0.331 0.004 0.723 0.004 1.115 0 18.941-3.246 37.123-9.213 54.021l0.35-1.136c-6.065 17.359-14.499 32.383-25.092 45.6l0.232-0.3c-21.289 26.385-51.141 45.109-85.284 51.963l-0.936 0.157v489.72q0 15.080-8.84 22.62c-5.768 4.696-13.207 7.541-21.31 7.541s-15.542-2.845-21.372-7.59l0.062 0.049q-8.84-7.52-8.84-22.62v-489.7c-35.077-7.030-64.925-25.758-86.002-51.861l-0.218-0.279c-10.37-12.9-18.816-27.902-24.572-44.175l-0.328-1.065c-5.617-15.763-8.864-33.945-8.864-52.885 0-0.392 0.001-0.784 0.004-1.175l-0 0.060c-0.002-0.316-0.003-0.69-0.003-1.065 0-17.281 2.641-33.946 7.54-49.612l-0.317 1.176c4.983-16.107 11.899-30.136 20.657-42.794l-0.337 0.514-11.8-36.72-33.44 53.74h-30.16l30.16-61.62-57.62 59.62-29.5-11.14 62.22-59.66-85.88 51.12-22.3-19.66 88.5-50.48-109.48 34.74-11.14-26.92 104.24-28.14-118.66 7.86zM255.68 352.7q0 33.42 16.38 59c10.502 16.53 26.142 28.985 44.643 35.225l0.597 0.175v-189.46c-19.221 6.033-34.962 18.459-45.101 34.736l-0.199 0.344q-16.32 25.9-16.32 59.98zM409.68 62.28c0.009 0.391 0.014 0.852 0.014 1.313 0 16.813-6.892 32.016-18.006 42.938l-0.009 0.009c-10.924 11.122-26.122 18.014-42.93 18.014-0.461 0-0.92-0.005-1.378-0.015l0.068 0.001c-0.365 0.008-0.795 0.012-1.226 0.012-16.941 0-32.273-6.885-43.352-18.010l-0.002-0.002c-11.331-10.873-18.372-26.143-18.372-43.057 0-0.423 0.004-0.845 0.013-1.266l-0.001 0.063c-0.008-0.356-0.012-0.775-0.012-1.196 0-16.926 7.049-32.206 18.371-43.065l0.021-0.020c11.093-11.127 26.435-18.012 43.386-18.012 0.42 0 0.839 0.004 1.256 0.013l-0.063-0.001c0.38-0.009 0.828-0.014 1.277-0.014 16.818 0 32.026 6.892 42.954 18.005l0.008 0.008c11.146 10.937 18.054 26.159 18.054 42.994 0 0.452-0.005 0.903-0.015 1.353l0.001-0.067zM439.18 352.7q0-34-16.4-60c-10.324-16.611-26.042-29.034-44.665-34.923l-0.575-0.157v189.46c19.098-6.415 34.738-18.87 45.036-35.056l0.204-0.344q16.44-25.54 16.46-58.98z"], "attrs": [{}], "width": 695, "isMulticolor": false, "isMulticolor2": false, "grid": 0, "tags": ["dungeon_upgrade"] }, "attrs": [{}], "properties": { "order": 42, "id": 28, "name": "dungeon_upgrade", "prevSize": 32, "code": 9882 }, "setIdx": 0, "setId": 2, "iconIdx": 0 }, - { "icon": { "paths": ["M512 16c0.657-0.007 1.432-0.010 2.209-0.010 28.073 0 55.001 4.899 79.978 13.888l-1.646-0.517c24.66 8.746 45.893 21.477 64.034 37.609l-0.194-0.169c34.954 31.433 56.836 76.807 56.836 127.292 0 0.833-0.006 1.664-0.018 2.494l0.001-0.126c-0.036 16.232-1.738 32.046-4.945 47.307l0.265-1.507c-4.275 19.104-10.472 35.947-18.56 51.657l0.56-1.197q32.7-29.4 69.48-42.72c22.047-8.392 47.541-13.285 74.168-13.36l0.032-0c0.249-0.001 0.545-0.002 0.84-0.002 25.775 0 50.405 4.904 73.007 13.831l-1.347-0.469c46.638 18.088 83.031 53.831 101.567 98.814l0.433 1.186q15.3 36.32 15.3 83.080 0 54.82-20.38 91.58c-13.31 24.124-31.574 43.994-53.543 58.782l-0.597 0.378c-21.998 14.568-47.76 25.579-75.415 31.478l-1.465 0.262c-22.979 5.201-49.368 8.181-76.453 8.181-4.018 0-8.021-0.066-12.008-0.196l0.581 0.015q68.16 30 102.6 79.2c21.532 30.096 34.429 67.649 34.429 108.214 0 0.628-0.003 1.255-0.009 1.882l0.001-0.096c0.007 0.67 0.011 1.463 0.011 2.256 0 27.087-4.656 53.087-13.211 77.243l0.5-1.618c-8.492 24.055-21.626 44.607-38.445 61.485l0.005-0.005q-25.74 25.74-64.16 40.44t-90.58 14.7q-54.12 0-91.24-17.7t-60.82-45.56c-15.151-17.514-27.311-38.113-35.381-60.658l-0.419-1.342c-7.207-19.636-12.819-42.617-15.835-66.408l-0.165-1.592c-2.68 25.186-8.102 48.22-16.031 70.050l0.651-2.050c-8.454 23.974-20.693 44.638-36.191 62.383l0.191-0.223c-16.777 18.897-37.12 34.217-60.027 44.982l-1.133 0.478q-37.12 17.7-91.24 17.7-52.14 0-90.58-14.7t-63.9-40.52c-16.65-16.914-29.666-37.459-37.747-60.333l-0.353-1.147c-8.056-22.512-12.712-48.484-12.712-75.543 0-0.822 0.004-1.643 0.013-2.462l-0.001 0.125c-0.006-0.544-0.009-1.187-0.009-1.83 0-40.551 12.898-78.089 34.814-108.737l-0.385 0.567q34.4-49.12 102.6-79.2c-3.49 0.12-7.593 0.188-11.712 0.188-27.223 0-53.75-2.983-79.271-8.639l2.423 0.451c-29.002-6.111-54.658-17.127-77.345-32.245l0.805 0.505c-22.464-15.281-40.7-35.122-53.696-58.298l-0.444-0.862q-20.72-36.64-20.72-91.56 0-46.78 15.38-83.22c9.968-24.002 23.991-44.452 41.403-61.444l0.037-0.036c16.879-16.228 36.99-29.239 59.253-37.957l1.227-0.423c21.362-8.459 46.11-13.364 72.003-13.364 0.421 0 0.841 0.001 1.261 0.004l-0.065-0c26.652 0.078 52.139 4.97 75.667 13.853l-1.487-0.493q36.76 13.38 69.52 42.78c-7.512-14.476-13.822-31.294-18.066-48.918l-0.314-1.542c-3.16-13.753-4.987-29.554-5.020-45.777l-0-0.023c-0.011-0.722-0.017-1.574-0.017-2.428 0-50.485 21.883-95.859 56.681-127.154l0.156-0.138c17.945-15.967 39.179-28.699 62.505-37.024l1.335-0.416c23.33-8.472 50.258-13.37 78.331-13.37 0.777 0 1.552 0.004 2.327 0.011l-0.118-0.001zM689.12 511.28c0.002-0.276 0.003-0.602 0.003-0.929 0-24.316-5.154-47.428-14.428-68.304l0.426 1.073c-18.61-42.456-51.804-75.65-93.103-93.806l-1.157-0.454c-20.205-8.862-43.755-14.020-68.51-14.020s-48.305 5.158-69.634 14.457l1.124-0.437c-42.445 18.619-75.629 51.81-93.786 93.103l-0.454 1.157c-8.849 19.777-14.003 42.861-14.003 67.149 0 0.356 0.001 0.711 0.003 1.066l-0-0.055c-0.003 0.391-0.005 0.853-0.005 1.316 0 24.423 5.154 47.643 14.433 68.63l-0.428-1.086c9.563 21.788 22.396 40.4 38.103 56.143l-0.003-0.003c15.689 15.66 34.312 28.386 54.973 37.281l1.147 0.439c20.237 8.664 43.785 13.701 68.51 13.701s48.273-5.037 69.675-14.141l-1.165 0.44c21.826-9.338 40.464-22.078 56.161-37.761l-0.001 0.001c15.704-15.74 28.537-34.352 37.642-54.978l0.458-1.162c8.863-19.934 14.024-43.192 14.024-67.654 0-0.41-0.001-0.819-0.004-1.228l0 0.063z"], "attrs": [{}], "isMulticolor": false, "isMulticolor2": false, "grid": 0, "tags": ["dye"] }, "attrs": [{}], "properties": { "order": 41, "id": 27, "name": "dye", "prevSize": 32, "code": 10047 }, "setIdx": 0, "setId": 2, "iconIdx": 1 }, - { "icon": { "paths": ["M111.66 327.76l111.66 184-111.66 184-111.66-184.080zM275.22 0l111.66 184-111.66 184-111.66-184zM275.22 656.18l111.66 184-111.66 184-111.66-184.18zM440 327.76l111.66 184-111.66 184-111.66-184z"], "attrs": [{}], "width": 552, "isMulticolor": false, "isMulticolor2": false, "grid": 0, "tags": ["powder"] }, "attrs": [{}], "properties": { "order": 40, "id": 26, "name": "powder", "prevSize": 32, "code": 6149 }, "setIdx": 0, "setId": 2, "iconIdx": 2 }, - { "icon": { "paths": ["M357.58 582.44q-15.080 0-24-9.58t-8.96-24.7c-0.002-0.133-0.003-0.291-0.003-0.449 0-3.474 0.461-6.84 1.324-10.040l-0.062 0.269c0.872-3.164 2.166-5.933 3.844-8.421l-0.064 0.101h-329.66v-35.86h328.64c-2.534-4.753-4.022-10.394-4.022-16.383 0-0.435 0.008-0.868 0.023-1.3l-0.002 0.062q0-15.72 9.28-25.3t25-9.6q15.080 0 24 9.44c5.568 5.991 8.985 14.047 8.985 22.902 0 0.456-0.009 0.911-0.027 1.363l0.002-0.065c0.006 0.247 0.009 0.537 0.009 0.828 0 6.596-1.631 12.812-4.512 18.265l0.103-0.213h330.52v35.86h-330.86c2.969 4.666 4.731 10.352 4.731 16.449 0 0.292-0.004 0.583-0.012 0.874l0.001-0.043q0 16-9.44 25.8t-24.84 9.74zM84.92 395.32h548.16v34.92h-548.16zM84.92 592.82h548.16v35.86h-548.16zM169.82 296.82h378.34v34.98h-378.34zM169.82 691.84h378.34v35.22h-378.34zM254.74 198.44h208.52v34.92h-208.52zM254.74 790.32h208.52v35.24h-208.52zM391.86 131.78h-70.14v-60.7l24.54-71.080h34.6l-20.76 61.64h31.76zM322 892.22h70.14v60.7l-24.5 71.080h-34.58l20.74-61.64h-31.8zM358.2 457.6c-0.209-0.011-0.454-0.018-0.7-0.018-4.239 0-8.037 1.884-10.605 4.859l-0.015 0.018c-2.521 3.34-4.038 7.562-4.038 12.137 0 0.437 0.014 0.871 0.041 1.301l-0.003-0.059c-0.020 0.332-0.032 0.721-0.032 1.112 0 4.506 1.516 8.658 4.066 11.974l-0.034-0.046c2.583 3.005 6.389 4.897 10.636 4.897 0.24 0 0.48-0.006 0.717-0.018l-0.033 0.001h1.26c4.175-0.234 7.851-2.188 10.362-5.158l0.018-0.022c2.383-3.19 3.815-7.211 3.815-11.567 0-0.413-0.013-0.823-0.038-1.229l0.003 0.056c0.024-0.371 0.038-0.805 0.038-1.243 0-4.576-1.517-8.797-4.075-12.189l0.037 0.051c-2.583-2.997-6.383-4.883-10.624-4.883-0.28 0-0.558 0.008-0.834 0.024l0.038-0.002zM358.2 529.6c-0.209-0.011-0.454-0.018-0.7-0.018-4.239 0-8.037 1.884-10.605 4.859l-0.015 0.018c-2.521 3.34-4.038 7.562-4.038 12.137 0 0.437 0.014 0.871 0.041 1.301l-0.003-0.059c-0.020 0.332-0.032 0.721-0.032 1.112 0 4.506 1.516 8.658 4.066 11.974l-0.034-0.046c2.85 3.006 6.871 4.877 11.33 4.877s8.48-1.871 11.323-4.87l0.007-0.007c2.516-3.269 4.032-7.421 4.032-11.928 0-0.391-0.011-0.78-0.034-1.166l0.002 0.053c0.021-0.345 0.033-0.747 0.033-1.153 0-4.414-1.43-8.495-3.853-11.803l0.039 0.056c-2.489-3.074-6.176-5.092-10.341-5.338l-0.039-0.002z"], "attrs": [{}], "width": 718, "isMulticolor": false, "isMulticolor2": false, "grid": 0, "tags": ["soulflow"] }, "attrs": [{}], "properties": { "order": 39, "id": 25, "name": "soulflow", "prevSize": 32, "code": 11790 }, "setIdx": 0, "setId": 2, "iconIdx": 3 }, - { "icon": { "paths": ["M0 511.66c-0.002-0.501-0.003-1.094-0.003-1.688 0-47.687 6.676-93.814 19.144-137.499l-0.861 3.527c24.909-88.679 70.491-164.726 131.352-225.472l0.008-0.008c30.235-30.36 64.165-57.003 101.068-79.207l2.352-1.313c73.917-44.010 162.992-70.026 258.143-70.026 48.254 0 94.945 6.691 139.196 19.195l-3.599-0.869c131.502 37.36 239.143 121.769 305.892 233.439l1.308 2.361c21.028 35.052 38.674 75.534 50.849 118.32l0.871 3.58c11.607 40.191 18.282 86.356 18.282 134.080 0 0.555-0.001 1.11-0.003 1.665l0-0.086c0.001 0.395 0.002 0.863 0.002 1.331 0 187.527-101.24 351.408-252.045 439.968l-2.397 1.301c-35.279 20.781-76.044 38.329-119.054 50.54l-3.706 0.9c-40.727 11.619-87.503 18.3-135.84 18.3s-95.113-6.681-139.455-19.17l3.615 0.87c-46.407-13.003-86.925-30.556-124.373-52.741l2.373 1.301c-39.274-23.257-73.207-49.659-103.436-79.776l0.016 0.016c-30.393-30.151-56.895-64.152-78.731-101.23l-1.269-2.33c-20.823-35.228-38.368-75.93-50.532-118.893l-0.888-3.667c-11.608-40.426-18.283-86.859-18.283-134.85 0-0.657 0.001-1.314 0.004-1.971l-0 0.101zM228.94 511.66c-0-0.208-0.001-0.455-0.001-0.701 0-16.066 1.112-31.873 3.264-47.347l-0.204 1.788c2.272-16.584 6.008-31.501 11.166-45.736l-0.486 1.536-207.52 90.46 207.56 90.44q-13.8-40.7-13.78-90.44zM257.2 387.36c14.581-29.109 32.668-54.050 54.148-75.608l-0.008 0.008c21.030-21.133 45.51-38.808 72.53-52.112l1.59-0.708-210.32-83.56zM385.46 766.44c-28.508-14.85-52.942-33.004-74.091-54.411l-0.029-0.029c-21.192-21.395-39.236-45.96-53.344-72.911l-0.796-1.669-82 211.3zM758.52 511.66c0.001-0.309 0.002-0.674 0.002-1.040 0-34.218-7.236-66.745-20.262-96.136l0.599 1.515c-25.758-59.529-72.215-106.045-130.090-131.255l-1.61-0.625c-27.937-12.44-60.535-19.684-94.824-19.684-0.484 0-0.967 0.001-1.451 0.004l0.075-0c-0.457-0.003-0.997-0.005-1.538-0.005-34.111 0-66.53 7.245-95.801 20.281l1.499-0.596c-59.294 25.984-105.599 72.457-130.733 130.262l-0.627 1.618c-12.433 28.31-19.668 61.31-19.668 96s7.236 67.69 20.28 97.573l-0.612-1.573c25.761 59.423 72.066 105.896 129.753 131.25l1.607 0.63c27.772 12.44 60.191 19.685 94.302 19.685 0.541 0 1.081-0.002 1.621-0.005l-0.083 0c0.409 0.003 0.892 0.004 1.376 0.004 34.289 0 66.887-7.244 96.345-20.285l-1.521 0.601c59.485-25.835 105.942-72.351 131.076-130.267l0.624-1.613c12.428-27.978 19.664-60.618 19.664-94.948 0-0.489-0.001-0.978-0.004-1.467l0 0.075zM420.64 244.44c12.33-4.567 27.048-8.524 42.215-11.174l1.565-0.226c13.806-2.418 29.702-3.801 45.921-3.801 0.218 0 0.435 0 0.652 0.001l-0.034-0c0.003-0 0.007-0 0.011-0 32.356 0 63.411 5.568 92.26 15.797l-1.931-0.597-90.34-209.22zM601.3 780.26c-12.579 4.639-27.448 8.487-42.803 10.869l-1.337 0.171c-13.936 2.202-30.006 3.46-46.37 3.46s-32.434-1.258-48.119-3.683l1.749 0.223c-16.578-2.586-31.321-6.431-45.444-11.569l1.664 0.529 90.32 207.84zM635.080 258.94c29.303 13.826 54.378 31.533 75.88 52.84l-0.020-0.020c21.5 21.323 39.301 46.333 52.384 74.010l0.676 1.59 83.44-212zM764 637.32c-14.073 28.821-31.829 53.486-53.056 74.676l-0.004 0.004c-21.62 21.626-46.647 39.844-74.207 53.782l-1.653 0.758 212.4 82.18zM777.78 421.2c10.047 26.909 15.861 58 15.861 90.45s-5.814 63.542-16.457 92.291l0.597-1.841 208.94-90.44z"], "attrs": [{}], "isMulticolor": false, "isMulticolor2": false, "grid": 0, "tags": ["true_defense"] }, "attrs": [{}], "properties": { "order": 38, "id": 24, "name": "true_defense", "prevSize": 32, "code": 10050 }, "setIdx": 0, "setId": 2, "iconIdx": 4 }, - { "icon": { "paths": ["M797.563 267.845q138.529 124.767 145.654 292.144 10.652 203.109-124.328 338.512-117.231 117.6-273.521 124.718-202.503 10.678-337.505-124.718-127.86-128.228-127.86-306.455 0-156.701 99.46-274.324 120.741-146.072 298.404-156.78 191.824-10.702 319.71 106.898zM584.429 887.863v-602.21h-95.901q3.486 71.33-131.443 71.281v74.813h103.019v456.135z"], "attrs": [{}], "isMulticolor": false, "isMulticolor2": false, "grid": 0, "tags": ["1"] }, "attrs": [{}], "properties": { "order": 33, "id": 23, "name": "1", "prevSize": 32, "code": 10122 }, "setIdx": 0, "setId": 2, "iconIdx": 5 }, - { "icon": { "paths": ["M797.563 267.845q138.529 124.767 145.654 292.144 10.652 203.109-124.328 338.512-117.231 117.6-273.521 124.718-202.503 10.678-337.505-124.718-127.86-128.228-127.86-306.455 0-156.701 99.46-274.324 120.741-146.072 298.404-156.78 191.824-10.702 319.71 106.898zM715.865 549.337c15.632-26.257 24.869-57.894 24.869-91.687 0-0.342-0.001-0.675-0.004-1.001v0.052q0-74.817-60.395-124.706-56.849-42.783-138.538-46.342-110.138-3.486-177.613 53.461-63.942 53.437-81.689 138.961l149.166 17.792q3.51-42.759 24.866-74.817 24.812-28.498 60.395-32.058 35.444 3.591 56.832 28.498 17.722 21.38 17.747 39.2 3.51 64.121-42.63 96.194-145.704 114.068-245.114 238.747v96.194h419.145v-110.397h-262.83q17.722-17.792 92.362-78.4 70.987-56.947 102.945-81.959 35.469-24.866 60.457-67.698z"], "attrs": [{}], "isMulticolor": false, "isMulticolor2": false, "grid": 0, "tags": ["2"] }, "attrs": [{}], "properties": { "order": 34, "id": 22, "name": "2", "prevSize": 32, "code": 10123 }, "setIdx": 0, "setId": 2, "iconIdx": 6 }, - { "icon": { "paths": ["M797.563 267.845q138.529 124.767 145.654 292.144 10.652 203.109-124.328 338.512-117.231 117.6-273.521 124.718-202.503 10.678-337.505-124.718-127.86-128.228-127.86-306.455 0-156.701 99.46-274.324 120.741-146.072 298.404-156.78 191.824-10.702 319.71 106.898zM698.103 834.402q39.028-46.269 39.067-110.457 7.093-124.693-124.328-138.961 113.648-35.591 113.69-142.538 0-71.232-67.501-117.578-56.849-42.759-138.587-42.759c-0.419-0.004-0.925-0.006-1.431-0.006-45.6 0-88.096 13.285-123.832 36.201l0.917-0.554q-74.597 46.356-102.945 117.578l135.002 28.498q7.093-28.473 28.423-53.437 17.747-17.792 49.73-21.38 35.444-3.51 60.395 21.38 14.162 14.282 17.747 46.318 3.486 53.461-24.864 64.121-24.913 10.678-113.69 10.678v96.194q92.341 3.591 124.328 17.82 35.444 21.356 28.423 78.376-3.559 32.058-21.307 53.461-24.866 28.547-67.501 21.38-71.11-3.51-92.367-74.84l-135.002 21.38q49.706 149.681 213.152 156.78 142.039 7.241 202.479-67.649z"], "attrs": [{}], "isMulticolor": false, "isMulticolor2": false, "grid": 0, "tags": ["3"] }, "attrs": [{}], "properties": { "order": 35, "id": 21, "name": "3", "prevSize": 32, "code": 10124 }, "setIdx": 0, "setId": 2, "iconIdx": 7 }, - { "icon": { "paths": ["M797.563 267.845q138.529 124.767 145.654 292.144 10.652 203.109-124.328 338.512-117.231 117.6-273.521 124.718-202.503 10.678-337.505-124.718-127.86-128.228-127.86-306.455 0-156.701 99.46-274.324 120.741-146.072 298.404-156.78 191.824-10.702 319.71 106.898zM648.373 731.056h113.672v-103.323h-113.672v-342.095h-135.002l-252.209 338.463v106.887h266.421v156.872h120.79zM527.583 438.87v188.857h-142.147z"], "attrs": [{}], "isMulticolor": false, "isMulticolor2": false, "grid": 0, "tags": ["4"] }, "attrs": [{}], "properties": { "order": 36, "id": 20, "name": "4", "prevSize": 32, "code": 10125 }, "setIdx": 0, "setId": 2, "iconIdx": 8 }, - { "icon": { "paths": ["M797.563 267.845q138.529 124.767 145.654 292.144 10.652 203.109-124.328 338.512-117.231 117.6-273.521 124.718-202.503 10.678-337.505-124.718-127.86-128.228-127.86-306.455 0-156.701 99.46-274.324 120.741-146.072 298.404-156.78 191.824-10.702 319.71 106.898zM655.44 859.341q74.597-56.947 81.689-149.652 10.652-121.133-60.382-185.298-56.886-49.866-135.002-46.318-60.449 3.591-103.019 42.759l7.101-110.457h234.511v-110.457h-358.782l-7.101 310.014 110.112 24.939q28.374-49.866 92.367-53.437 74.594 0 78.153 89.078 7.047 78.484-31.983 110.554-24.89 24.963-56.832 21.38-60.449 0-85.248-71.281l-135.002 21.38q49.704 146.072 198.969 149.582 106.529 7.192 170.441-42.759z"], "attrs": [{}], "isMulticolor": false, "isMulticolor2": false, "grid": 0, "tags": ["5"] }, "attrs": [{}], "properties": { "order": 37, "id": 19, "name": "5", "prevSize": 32, "code": 10126 }, "setIdx": 0, "setId": 2, "iconIdx": 9 }, - { "icon": { "paths": ["M512 921.6l38.912-153.6c-166.912-10.752-315.904-81.921-358.912-175.104-4.608 24.576-11.264 47.104-21.504 64-33.792 59.904-102.4 59.904-170.496 59.904 56.32 0 76.8-80.385 76.8-179.2s-20.48-179.2-76.8-179.2c68.097 0 136.704 0 170.496 59.904 10.24 16.896 16.896 39.424 21.504 64 33.28-72.705 131.584-131.584 251.392-158.721l-84.993-169.984c102.4 0 204.801 0 272.896 34.304 57.856 28.672 91.137 81.921 120.832 138.753 149.505 35.84 271.872 116.736 271.872 210.945 0 96.256-128.001 179.2-281.601 212.992-42.496 56.32-83.968 108.544-119.296 136.704-43.008 34.304-76.8 34.304-111.105 34.304zM768 460.8c-28.277 0-51.2 22.924-51.2 51.2v0c0 28.277 22.924 51.2 51.2 51.2v0c28.277 0 51.2-22.924 51.2-51.2v0c0-28.277-22.924-51.2-51.2-51.2v0z"], "attrs": [{}], "isMulticolor": false, "isMulticolor2": false, "grid": 0, "tags": ["fish"] }, "attrs": [{}], "properties": { "order": 23, "id": 17, "name": "sea-creature-chance", "prevSize": 32, "code": 945 }, "setIdx": 0, "setId": 2, "iconIdx": 11 }, - { "icon": { "paths": ["M512 781.824l316.416 190.977-83.968-359.937 279.552-242.176-368.128-31.744-143.872-338.944-143.872 338.944-368.128 31.744 279.040 242.176-83.457 359.937 316.416-190.977z"], "attrs": [{}], "isMulticolor": false, "isMulticolor2": false, "grid": 0, "tags": ["star"] }, "attrs": [{}], "properties": { "order": 22, "id": 16, "name": "magic-find", "prevSize": 32, "code": 10031 }, "setIdx": 0, "setId": 2, "iconIdx": 12 }, - { "icon": { "paths": ["M512 0l-139.636 372.364-372.364 139.636 372.364 139.636 139.636 372.364 139.636-372.364 372.364-139.636-372.364-139.636-139.636-372.364z"], "attrs": [{}], "isMulticolor": false, "isMulticolor2": false, "grid": 0, "tags": ["star-four-points"] }, "attrs": [{}], "properties": { "order": 21, "id": 15, "name": "speed", "prevSize": 32, "code": 10022 }, "setIdx": 0, "setId": 2, "iconIdx": 13 }, - { "icon": { "paths": ["M232.704 51.644l573.037 573.037 102.087-102.087 67.898 67.898-118.942 118.942 153.131 153.131c18.78 18.78 18.78 49.118 0 67.898l-34.189 34.189c-8.682 8.701-20.688 14.083-33.949 14.083s-25.266-5.382-33.948-14.082l-0.001-0.001-155.058-152.649-117.497 118.942-67.898-67.898 102.087-102.087-573.037-573.037v-136.277h136.277zM699.32 415.691l228.252-228.252v-135.796h-136.277l-228.252 228.252 136.277 135.796zM460.956 656.463l-136.277-138.203-106.421 106.421-102.087-102.087-67.898 67.898 118.942 118.942-153.131 153.613c-8.701 8.682-14.083 20.688-14.083 33.949s5.382 25.266 14.082 33.948l34.19 34.19c18.78 18.78 49.118 18.78 67.898 0l155.058-153.131 117.497 118.942 67.898-67.898-102.087-102.087 106.421-104.496z"], "attrs": [{}], "isMulticolor": false, "isMulticolor2": false, "grid": 0, "tags": ["sword-cross"] }, "attrs": [{}], "properties": { "order": 25, "id": 14, "name": "attack-speed", "prevSize": 32, "code": 9876 }, "setIdx": 0, "setId": 2, "iconIdx": 14 }, - { "icon": { "paths": ["M706.559 844.799l307.2 81.92-20.48 97.28-481.28-128-481.28 128-25.6-97.28 307.2-81.92-312.32-81.92 25.6-97.28 481.28 128 481.28-128 25.6 97.28-307.2 81.92zM819.2 307.2c0 92.16-40.96 168.96-102.4 225.279v133.12h-102.4v-102.4h-51.2v102.4h-102.4v-102.4h-51.2v102.4h-102.4v-133.12c-61.44-56.32-102.4-133.12-102.4-225.279 0-169.662 137.538-307.2 307.2-307.2v0c169.662 0 307.2 137.538 307.2 307.2v0zM460.8 281.6c0-40.96-35.84-76.8-76.8-76.8s-76.8 35.84-76.8 76.8 35.84 76.8 76.8 76.8 76.8-35.84 76.8-76.8zM563.2 460.8l-51.2-102.4-51.2 102.4h102.4zM716.8 281.6c0-40.96-35.84-76.8-76.8-76.8s-76.8 35.84-76.8 76.8 35.84 76.8 76.8 76.8 76.8-35.84 76.8-76.8z"], "attrs": [{}], "isMulticolor": false, "isMulticolor2": false, "grid": 0, "tags": ["skull-crossbones"] }, "attrs": [{}], "properties": { "order": 19, "id": 13, "name": "critical-damage", "prevSize": 32, "code": 9760 }, "setIdx": 0, "setId": 2, "iconIdx": 15 }, - { "icon": { "paths": ["M512 0.001l-418.909 186.182v279.273c0 258.327 178.734 499.898 418.909 558.545 240.174-58.647 418.909-300.218 418.909-558.545v-279.273l-418.909-186.182z"], "attrs": [{}], "isMulticolor": false, "isMulticolor2": false, "grid": 0, "tags": ["shield"] }, "attrs": [{}], "properties": { "order": 18, "id": 12, "name": "defense", "prevSize": 32, "code": 10056 }, "setIdx": 0, "setId": 2, "iconIdx": 16 }, - { "icon": { "paths": ["M772.576 12.922c-20.997 0-41.455 8.076-57.606 23.688l-114.136 114.136 285.341 285.88 114.136-113.060c32.303-32.842 32.303-83.987 0-115.214l-170.666-171.744c-16.151-15.613-36.609-23.688-57.069-23.688zM562.608 188.972l-436.088 436.627 137.826 15.075 9.691 123.289 122.751 9.152 15.613 137.826 436.088-436.627zM94.755 675.668l-94.217 360.176 360.715-96.37-12.921-116.29-124.366-9.152-9.691-124.905z"], "attrs": [{}], "isMulticolor": false, "isMulticolor2": false, "grid": 0, "tags": ["lead-pencil"] }, "attrs": [{}], "properties": { "order": 17, "id": 11, "name": "intelligence", "prevSize": 32, "code": 9998 }, "setIdx": 0, "setId": 2, "iconIdx": 17 }, - { "icon": { "paths": ["M512 990.719l-74.24-67.584c-263.679-239.103-437.76-397.311-437.76-590.336 0-158.208 123.904-281.6 281.6-281.6 89.088 0 174.591 41.472 230.4 106.496 55.808-65.024 141.312-106.496 230.4-106.496 157.695 0 281.6 123.392 281.6 281.6 0 193.023-174.080 351.231-437.76 590.336l-74.24 67.584z"], "attrs": [{}], "isMulticolor": false, "isMulticolor2": false, "grid": 0, "tags": ["heart"] }, "attrs": [{}], "properties": { "order": 16, "id": 10, "name": "health", "prevSize": 32, "code": 10084 }, "setIdx": 0, "setId": 2, "iconIdx": 18 }, - { "icon": { "paths": ["M512 452.094c33.085 0 59.906 26.821 59.906 59.906v0c0 33.085-26.821 59.906-59.906 59.906v0c-33.085 0-59.906-26.821-59.906-59.906v0c0-33.085 26.821-59.906 59.906-59.906v0zM45.932 45.932c85.665-85.665 271.373-47.326 466.068 80.273 194.694-127.599 380.401-165.94 466.068-80.273s47.326 271.373-80.273 466.068c127.599 194.694 165.94 380.401 80.273 466.068s-271.373 47.326-466.068-80.273c-194.694 127.599-380.401 165.94-466.068 80.273s-47.326-271.373 80.273-466.068c-127.599-194.694-165.94-380.401-80.273-466.068zM724.067 299.933c36.543 37.141 70.090 74.882 101.241 112.622 82.67-127.599 112.622-237.227 67.693-281.557-44.33-44.929-153.957-14.977-281.557 67.693 37.741 31.151 75.481 64.698 112.622 101.241zM299.933 724.067c-36.543-37.141-70.090-74.882-101.241-112.622-82.67 127.599-112.622 237.227-67.693 281.557 44.33 44.929 153.957 14.977 281.557-67.693-37.741-31.151-75.481-64.698-112.622-101.241zM130.999 130.999c-44.929 44.33-14.977 153.957 67.693 281.557 31.151-37.741 64.698-75.481 101.241-112.622 37.141-36.543 74.882-70.090 112.622-101.241-127.599-82.67-237.227-112.622-281.557-67.693zM385 639c41.935 41.935 85.067 80.273 127 114.42 41.935-34.146 85.067-72.486 127-114.42s80.273-85.067 114.42-127c-34.146-41.935-72.486-85.067-114.42-127s-85.067-80.273-127-114.42c-41.935 34.146-85.067 72.486-127 114.42s-80.273 85.067-114.42 127c34.146 41.935 72.486 85.067 114.42 127zM893.001 893.001c44.929-44.33 14.977-153.957-67.693-281.557-31.151 37.741-64.698 75.481-101.241 112.622-37.141 36.543-74.882 70.090-112.622 101.241 127.599 82.67 237.227 112.622 281.557 67.693z"], "attrs": [{}], "isMulticolor": false, "isMulticolor2": false, "grid": 0, "tags": ["atom"] }, "attrs": [{}], "properties": { "order": 15, "id": 9, "name": "critical-chance", "prevSize": 32, "code": 9763 }, "setIdx": 0, "setId": 2, "iconIdx": 19 }, - { "icon": { "paths": ["M844.8 512c98.97 0 179.2-80.231 179.2-179.2v0c0-183.801-148.999-332.8-332.8-332.8v0c-98.97 0-179.2 80.231-179.2 179.2v0c0-98.97-80.231-179.2-179.2-179.2v0c-183.801 0-332.8 148.999-332.8 332.8v0c0 98.97 80.231 179.2 179.2 179.2v0c-98.97 0-179.2 80.231-179.2 179.2v0c0 183.801 148.999 332.8 332.8 332.8v0c98.97 0 179.2-80.231 179.2-179.2v0c0 98.97 80.231 179.2 179.2 179.2v0c183.801 0 332.8-148.999 332.8-332.8v0c0-98.97-80.231-179.2-179.2-179.2v0zM512 716.801c-113.109 0-204.801-91.692-204.801-204.801v0c0-113.109 91.692-204.801 204.801-204.801v0c113.109 0 204.801 91.692 204.801 204.801v0c0 113.109-91.692 204.801-204.801 204.801v0zM640.001 512c0 70.692-57.307 128.001-128.001 128.001v0c-70.692 0-128.001-57.307-128.001-128.001v0c0-70.692 57.307-128.001 128.001-128.001v0c70.692 0 128.001 57.307 128.001 128.001v0z"], "attrs": [{}], "isMulticolor": false, "isMulticolor2": false, "grid": 0, "tags": ["flower-poppy"] }, "attrs": [{}], "properties": { "order": 14, "id": 8, "name": "strength", "prevSize": 32, "code": 10049 }, "setIdx": 0, "setId": 2, "iconIdx": 20 }, - { "icon": { "paths": ["M701.411 306.007c82.68 94.587 192.67 163.412 317.627 194.23l4.243 0.885v21.363c-140.77 40.254-259.937 118.388-349.558 222.652l-0.794 0.947c-71.255 75.217-123.525 169.123-148.7 273.588l-0.84 4.13h-22.788c-32.565-120.753-94.559-224.274-177.921-306.102l-0.103-0.101c-84.796-91.708-193.902-159.766-317.092-193.983l-4.776-1.132v-21.363c129.942-29.515 240.502-98.833 321.154-194.248l0.714-0.868c86.435-79.908 149.166-184.289 177.205-302.117l0.821-4.086h22.788c25.636 108.239 85.452 209.357 178.024 306.203zM511.993 72.438c-17.913 122.616-56.953 233.048-113.516 332.187l2.428-4.622c-95.003 53.696-205.732 93.097-323.362 111.775l-5.628 0.737c140.996 28.484 250.659 65.513 328.989 111.087 48.422 81.179 85.452 190.843 111.087 327.566 24.114-123.339 62.578-233.012 114.405-334.74l-3.317 7.174c95.122-50.128 205.47-88.739 321.874-110.009l7.116-1.080c-123.33-20.515-233.913-59.806-334.351-115.224l5.361 2.713c-50.034-94.698-88.632-204.548-109.997-320.436l-1.092-7.129z"], "attrs": [{}], "isMulticolor": false, "isMulticolor2": false, "grid": 0, "tags": ["pristine"] }, "attrs": [{}], "properties": { "order": 13, "id": 7, "name": "pristine", "prevSize": 32, "code": 10023 }, "setIdx": 0, "setId": 2, "iconIdx": 21 }, - { "icon": { "paths": ["M307.131 56.442l-13.128-10.211c52.613-29.38 115.431-46.681 182.289-46.681 0.529 0 1.059 0.001 1.588 0.004h-0.082c49.595 0 96.273 8.752 144.409 23.34 129.193 45.084 231.154 139.912 284.689 260.946l1.214 3.076c20.451 45.943 32.714 99.472 33.546 155.77l0.004 0.308-1.459 37.926c-2.028 14.314-4.576 26.657-7.807 38.721l0.513-2.254-11.669-8.752c-0.715-30.552-6.538-59.531-16.642-86.414l0.596 1.81c-26.62-70.652-64.731-131.273-112.62-182.663l0.301 0.326c-25.378-29.698-53.098-56.031-83.317-79.277l-1.287-0.951-561.594 862.083h-64.183l580.558-892.716c-75.96-48.986-166.89-81.478-264.651-90.273l-2.289-0.166c-0.362-0.002-0.792-0.004-1.22-0.004-31.54 0-61.703 5.889-89.454 16.624l1.694-0.576z"], "attrs": [{}], "isMulticolor": false, "isMulticolor2": false, "grid": 0, "tags": ["mining_speed"] }, "attrs": [{}], "properties": { "order": 12, "id": 6, "name": "mining-speed", "prevSize": 32, "code": 11797 }, "setIdx": 0, "setId": 2, "iconIdx": 22 }, - { "icon": { "paths": ["M11.145 393.026c0-14.141 1.414-26.87 7.071-41.011 4.622-13.105 11.355-24.393 19.893-34.049l-0.094 0.108c10.764-10.432 23.41-19 37.367-25.135l0.817-0.32c14.708-5.416 31.695-8.549 49.412-8.549 1.521 0 3.038 0.023 4.549 0.069l-0.221-0.005c21.213 0 41.011 2.829 60.81 11.314 41.099 19.548 76.481 43.171 107.942 71.114l-0.463-0.404 55.154 43.84c41.325 31.448 89.117 57.338 140.635 75.271l3.612 1.094c-19.634-54.519-44.961-101.737-76.083-144.463l1.132 1.63-45.254-55.154c-15.556-16.97-28.284-35.355-41.011-52.325-24.357-32.433-39.527-73-41.003-117.036l-0.010-0.343c0-21.213 2.829-39.597 9.899-55.154 5.78-14.307 13.919-26.532 24.052-36.779l-0.011 0.011c20.744-16.484 47.316-26.448 76.213-26.448 12.665 0 24.882 1.914 36.38 5.468l-0.872-0.232c11.52 4.357 21.304 9.114 30.584 14.63l-0.886-0.487c8.672 6.063 16.125 13.067 22.463 21l0.164 0.212 16.97 22.627h2.829l16.97-22.627c6.949-8.123 14.857-15.132 23.624-20.952l0.417-0.261c17.455-12.425 39.209-19.864 62.702-19.864 1.324 0 2.642 0.024 3.956 0.071l-0.19-0.005c12.728 0 26.87 2.829 39.597 7.071 13.814 4.516 25.653 11.793 35.376 21.234l-0.022-0.022c10.757 9.818 19.022 22.184 23.856 36.153l0.185 0.616c5.983 16.482 9.444 35.508 9.444 55.34 0 21.282-3.983 41.632-11.247 60.348l0.388-1.138c-9.572 20.844-19.478 38.469-30.615 55.203l0.916-1.464-41.011 53.739c-49.764 56.547-90.396 122.628-118.659 194.908l-1.547 4.492c54.858-17.354 102.406-43.426 143.617-76.984l-0.784 0.618 56.568-43.84c30.557-27.597 65.48-51.217 103.43-69.561l2.634-1.149c16.662-7.195 36.063-11.379 56.441-11.379 1.537 0 3.068 0.024 4.593 0.071l-0.224-0.006c21.213 0 39.597 2.829 55.154 8.485 14.133 6.857 26.26 15.368 36.817 25.501l-0.048-0.046c9.427 9.222 16.704 20.602 21.037 33.343l0.177 0.598c3.572 11.643 5.629 25.026 5.629 38.891s-2.057 27.247-5.881 39.861l0.254-0.972c-3.218 11.32-8.058 21.205-14.34 29.99l0.198-0.291c-11.308 16.499-26.018 29.852-43.193 39.272l-0.647 0.325v4.243c17.822 9.744 32.532 23.099 43.566 39.175l0.274 0.423c6.083 8.492 10.923 18.379 13.975 29.019l0.166 0.678c3.635 11.421 5.728 24.558 5.728 38.184s-2.095 26.761-5.979 39.105l0.25-0.921c-4.509 13.339-11.787 24.718-21.198 33.926l-0.016 0.014c-9.999 10.91-22.278 19.557-36.099 25.212l-0.67 0.243c-14.948 5.428-32.204 8.567-50.191 8.567-1.745 0-3.483-0.030-5.214-0.088l0.251 0.007c-1.306 0.040-2.842 0.063-4.383 0.063-20.857 0-40.738-4.181-58.851-11.75l1.009 0.374c-20.576-8.208-38.269-17.705-54.709-28.907l0.969 0.624c-19.587-13.337-36.657-26.813-52.729-41.372l0.404 0.361-56.568-45.254c-39.834-31.73-86.344-57.237-136.83-74.036l-3.175-0.915c5.656 29.698 11.314 56.568 14.141 83.437 2.312 22.194 3.63 47.952 3.63 74.019 0 44.792-3.892 88.674-11.357 131.33l0.657-4.533c-7.32 41.404-19.607 78.413-36.45 112.783l1.096-2.476c-14.863 32.581-35.92 59.979-61.869 81.732l-0.356 0.29c-23.307 19.396-53.557 31.169-86.555 31.169-1.39 0-2.776-0.020-4.155-0.063l0.202 0.005c-0.564 0.005-1.232 0.007-1.899 0.007-16.823 0-33.286-1.547-49.253-4.504l1.656 0.255c-24.12-6.841-37.781-11.188-51.352-15.727l10.341 3v-52.325c0.833 0.013 1.816 0.019 2.801 0.019 33.62 0 65.284-8.38 93.016-23.165l-1.067 0.52c30.935-17.459 56.835-40.199 77.329-67.259l0.451-0.622c22.342-32.439 40.244-70.083 51.674-110.445l0.651-2.69c13.61-46.044 21.442-98.946 21.442-153.676 0-28.608-2.14-56.715-6.267-84.172l0.382 3.091c-54.931 16.192-102.604 41.899-143.537 75.512l0.704-0.56c-20.498 14.911-38.478 29.751-55.518 45.59l0.366-0.336c-15.407 13.045-32.46 26.055-50.158 38.193l-2.167 1.404c-32.433 24.357-73 39.527-117.036 41.003l-0.343 0.010c-1.021 0.023-2.225 0.036-3.433 0.036-18.512 0-36.295-3.12-52.853-8.864l1.132 0.342c-14.49-5.898-26.77-14.546-36.702-25.381l-0.067-0.075c-8.444-9.547-15.177-20.836-19.578-33.228l-0.22-0.712c-4.52-11.014-7.144-23.798-7.144-37.195 0-1.342 0.026-2.678 0.078-4.007l-0.006 0.191c0-12.728 1.414-25.455 5.656-35.355 3.218-11.32 8.058-21.205 14.34-29.99l-0.198 0.291c11.308-16.499 26.018-29.852 43.193-39.272l0.647-0.325v-4.243c-9.132-4.992-17.016-10.622-24.15-17.066l0.108 0.096-19.799-22.627c-6.083-8.492-10.923-18.379-13.975-29.019l-0.166-0.678c-3.62-9.943-5.714-21.421-5.714-33.388 0-1.189 0.020-2.373 0.061-3.552l-0.005 0.171z"], "attrs": [{}], "isMulticolor": false, "isMulticolor2": false, "grid": 0, "tags": ["fortune"] }, "attrs": [{}], "properties": { "order": 10, "id": 5, "name": "fortune", "prevSize": 32, "code": 9752 }, "setIdx": 0, "setId": 2, "iconIdx": 23 }, - { "icon": { "paths": ["M56.889 1024l455.111-1024h142.223l-455.111 1024h28.444zM369.777 1024l455.111-1024h142.223l-455.111 1024h-284.444z"], "attrs": [{}], "isMulticolor": false, "isMulticolor2": false, "grid": 0, "tags": ["ferocity"] }, "attrs": [{}], "properties": { "order": 11, "id": 4, "name": "ferocity", "prevSize": 32, "code": 11005 }, "setIdx": 0, "setId": 2, "iconIdx": 24 }, - { "icon": { "paths": ["M512-0.001c117.76 0 220.16 102.4 220.16 215.040-1.375 83.167-47.152 155.338-114.6 193.973l-1.112 0.587c51.2-25.6 125.952-25.6 125.952-25.6 128 0 230.4 92.16 230.4 220.16s-102.4 215.040-230.4 215.040c0 0-76.8 0-179.2-51.2 0 0-15.36 102.4 102.4 256h-307.2c117.76-153.6 102.4-256 102.4-256-102.4 51.2-179.2 51.2-179.2 51.2-128 0-230.4-87.040-230.4-215.040s102.4-220.16 230.4-220.16c0 0 74.752 0 125.952 25.6-15.36-8.704-111.104-62.976-115.712-194.56 0-112.64 102.4-215.040 220.16-215.040z"], "attrs": [{}], "isMulticolor": false, "isMulticolor2": false, "grid": 0, "tags": ["cards-club"] }, "attrs": [{}], "properties": { "order": 9, "id": 3, "name": "pet-luck", "prevSize": 32, "code": 9827 }, "setIdx": 0, "setId": 2, "iconIdx": 25 }, - { "icon": { "paths": ["M475.787 738.703c-44.105-6.651-81.689-30.346-106.484-64.036l-0.313-0.446c-25.138-32.321-40.303-73.483-40.303-118.187 0-0.246 0-0.493 0.001-0.738v0.038c0-52.391 18.135-94.707 54.406-130.978 32.941-33.591 78.799-54.412 129.518-54.412 0.513 0 1.025 0.002 1.537 0.006h-0.079c54.406 0 98.737 18.135 137.023 56.421 34.898 34.377 56.519 82.147 56.519 134.969 0 2.139-0.036 4.271-0.105 6.394l0.008-0.309c0.261 5.616 0.409 12.201 0.409 18.82 0 104.008-36.651 199.456-97.743 274.133l0.613-0.772c-55.846 70.337-141.351 115.042-237.296 115.042-3.711 0-7.407-0.067-11.086-0.2l0.532 0.016c-0.449 0.002-0.979 0.004-1.509 0.004-103.625 0-195.689-49.507-253.826-126.16l-0.575-0.792c-66.648-81.461-107.035-186.659-107.035-301.29 0-5.3 0.086-10.58 0.257-15.838l-0.020 0.767c0-139.038 50.376-253.896 149.113-346.587 91.418-83.837 213.79-135.213 348.163-135.213 5.115 0 10.211 0.074 15.29 0.223l-0.745-0.017c143.068 0 263.971 44.331 362.707 135.007 91.845 83.955 149.235 204.282 149.235 338.014 0 3.723-0.044 7.436-0.133 11.136l0.011-0.549c-1.097 154.436-35.89 300.477-97.375 431.503l2.669-6.329h-203.519v-10.075c74.929-117.86 120.374-260.921 122.909-414.419l0.008-0.68c0.151-3.596 0.237-7.816 0.237-12.056 0-87.151-36.4-165.801-94.825-221.575l-0.12-0.114c-60.296-55.119-140.92-88.887-229.431-88.887-4.351 0-8.685 0.081-12.997 0.243l0.622-0.018c-3.69-0.144-8.022-0.225-12.375-0.225-88.511 0-169.135 33.768-229.692 89.122l0.261-0.236c-59.668 55.375-96.886 134.226-96.886 221.77 0 3.502 0.060 6.991 0.178 10.465l-0.013-0.505c-0.152 3.818-0.239 8.3-0.239 12.802 0 70.266 21.155 135.589 57.445 189.951l-0.784-1.248c36.271 54.406 80.602 80.602 132.993 80.602 60.451 0 96.722-24.181 112.843-74.556zM518.102 629.891c20.15 0 38.285-8.060 52.391-22.166 13.627-12.547 22.141-30.464 22.166-50.372v-0.005c0.007-0.401 0.012-0.875 0.012-1.348 0-20.757-8.483-39.533-22.17-53.050l-0.007-0.007c-13.228-13.795-31.808-22.367-52.391-22.367s-39.164 8.572-52.367 22.342l-0.024 0.025c-13.695 13.526-22.178 32.301-22.178 53.058 0 0.474 0.005 0.948 0.013 1.419l-0.001-0.071c0 20.15 8.060 36.271 22.166 50.376 13.211 13.675 31.712 22.166 52.197 22.166 0.068 0 0.136 0 0.205 0h-0.011z"], "attrs": [{}], "isMulticolor": false, "isMulticolor2": false, "grid": 0, "tags": ["ability_damage"] }, "attrs": [{}], "properties": { "order": 8, "id": 2, "name": "ability-damage", "prevSize": 32, "code": 3665 }, "setIdx": 0, "setId": 2, "iconIdx": 26 }, - { "icon": { "paths": ["M512 160c238.434 0 432 193.566 432 432s-193.566 432-432 432c-238.434 0-432-193.566-432-432s193.566-432 432-432zM422.585 368.013h-103.72l-138.591 447.979h134.122l67.063-245.892 130.545 240.54 130.545-240.54 67.063 245.892h134.122l-138.591-447.979h-103.72l-89.415 209.231-89.415-209.231zM749.846 591.214v1.593l0.791-0.791-0.791-0.786z"], "attrs": [{}], "isMulticolor": false, "isMulticolor2": false, "grid": 0, "tags": ["dungeon_item_master_star"] }, "attrs": [{}], "properties": { "order": 6, "id": 1, "name": "dungeon-master-star", "prevSize": 32, "code": 9055 }, "setIdx": 0, "setId": 2, "iconIdx": 27 }, - { "icon": { "paths": ["M512 160c-238.437 0-432 193.563-432 432s193.563 432 432 432c238.437 0 432-193.563 432-432s-193.563-432-432-432zM512 253.343l79.029 243.243h255.754l-206.901 150.32 79.029 243.243-206.901-150.32-206.901 150.32 79.029-243.243-206.901-150.32h255.754l79.029-243.243z"], "attrs": [{}], "isMulticolor": false, "isMulticolor2": false, "grid": 0, "tags": ["dungeon_item_star"] }, "attrs": [{}], "properties": { "order": 7, "id": 0, "name": "dungeon-star", "prevSize": 32, "code": 10026 }, "setIdx": 0, "setId": 2, "iconIdx": 28 } - ], - "height": 1024, - "metadata": { "name": "icomoon" }, - "preferences": { "showGlyphs": true, "showQuickUse": true, "showQuickUse2": true, "showSVGs": true, "fontPref": { "prefix": "icon-", "metadata": { "fontFamily": "icomoon" }, "metrics": { "emSize": 1024, "baseline": 6.25, "whitespace": 50 }, "embed": false, "autoHost": true }, "imagePref": { "prefix": "icon-", "png": true, "useClassSelector": true, "color": 0, "bgColor": 16777215, "classSelector": ".icon", "name": "icomoon" }, "historySize": 50, "showCodes": true, "gridSize": 16, "quickUsageToken": { "UntitledProject": "NjhhODJjMzk5ZDBjYmFjMTBkNzg2OTg5NTJhYzYyMjMjMSMxNjIxMjAxMjA2IyMj" }, "showGrid": false } -} diff --git a/static/fonts/minecraft/MinecraftTenv2-Regular.woff2 b/static/fonts/minecraft/MinecraftTenv2-Regular.woff2 deleted file mode 100644 index a75a8ed40f76be77ea33005d80a5b2580027d625..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8912 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 diff --git a/static/fonts/montserrat/montserrat-italic.woff2 b/static/fonts/montserrat/montserrat-italic.woff2 deleted file mode 100644 index b0cfe1fc067b13d0499923b4dfbc7939ee19ba5c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37120 zcmV)1K+V5*Pew8T0RR910FeLy6aWAK0d)KT0FZ|O0RR9100000000000000000000 z0000QhD95Ko?sk}20utvK~je^KTTFaQbq<~KT}jeRDm=nG6024FMbgS3W1Dx@IDKL z1^_UD>OuiF0we>92m~Mnj5r66Wn0=}QNlI`mbbdAI=UO&zN01^ci?vT_wi0_PNthX zr8f&<`@3#KjQ>9|L5&y<@S6qnRQ0v0G9pQlL}pTzw5bvaHzTN}t*gnQc~LoG>%11} zq)paUu5g7dJMO?vTLunyns5vm1K0FH<&-OWJB*0eG5Kx`H?TQP+oSXtA)lB$9w1<- zSGVpRDE_i5nimt3(kZ|Z;GWy-JO0@pTOT|6ZEXsqNJQHQxb62ZkUI(fnTV&Ni`T3I zW0%K>sO^cD=b!ld^4C7~8XQDYPlr-KC8X86lfyW~!V^7gP>zzauu($$umBZ30_e zX_BrPB(@i!mSOsGdynEKO{f`i4!vjgdnBhMG6%vHtEj9`SiZK&AXj% zomX@)r!0PK+YksG3%3AeKomRtvGa8c4FxW|;;^ z_OJ{T8|@=_5j+Xtw*=S?04`#1fNl2AOw%w3L9NgLRs% znDySzyrx7d(UpNUUFo8* z0v?`mHuFG4BVAWY|1E_}MT%%1NQ&%S#%~Hzz$2ZU6;z&ofJ559ZMx>9yB05G};O8 zS>yLZW6s39w#$IB@xK8*T_RaGlmrq;xC-erM055(=ZGd7Lt?~iH{uXCAYzz=;!-zW zMfA7yQ#tL4_ss0jrW&@pS6mP!DsW&bPMh>6Tc61M4s0!Z%KBbQgfrpdwu~h$ZFa|h zQljDJd-4aqQeXK_GW$S@)ILTw(MFa>V;Nfa&_1-8*^6Fzqr8m5ghHV(VFJ(F?mr0t z0&Fx{cS&1oxo4BP@ee?bxP*Z+3RSE6z5tkj7S&^GTPGCOHAO;$n8`1WT6!@*@xS-g zvh;rv2l{9WVBBMCy7c5)FH3uYHE07%XmpxQHvdun%?A9kZ zmZmM`tiJ@s*+*i`Z^)rZ8Or)-jpuro8kf1$xM-7Xqj=-ZeHd&UuK)i_O*;4A{X71d zlOz3|EpocHYn>**wN9bwS`ansB1&FE<~k{vr?uh-e-^)LkQ`O0LtZs&||C(g1G-%SVEvKg#zkSpbh~X1FVe$!64uj z|D-mMwYs7WY(LP!RZ16aKg7O6>^#h_!!;i7;t5Wi>?=?}M1QLudiCwH|6gf+uKoS? z=I19EKiBuowUiW-Vn#YuJX4%ke)?rmEvn6MO0Vk8Fbs!QIHPLRjE14CHm*seNjwsg zh)$LNR&Fw%1uSHY3Fd5am5@gwO5B8{EEQ>*N;`%tg>EQItZuu`BOytVGC@e~qC- z_w-m#Y-PuGW=}qR&-eYv&-}t~<2)|oDsJOTGWYT@&+{TL^E#hLiUL6p6=FeLhz|)N zIW&Y3V1yVE2F6IROe~B=uzs8rr^fT~2wsMlJm*!M`?j1DyuBh zmzm0}<+^fXxs&)I(T`{(nn`Aog=8h!$SSgxVxib6ZmN;$qIxRq6+W7S>0$+0adwi^ z%xU39cyduA+=w(vx};sI@xHcvmE9dMfIxr$2jT>sE>4FyD~cn}f>&1P5ynht

25w?W$EMkztJ_kpj4nsDLLuYj*=|4v#kJkP|Gx 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 z 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 M|D`1-O8@`>0P9TohyVZp diff --git a/static/fonts/montserrat/montserrat-normal.woff2 b/static/fonts/montserrat/montserrat-normal.woff2 index 61220a0f6bb5d74f2cea3c53094c31e2a875f90f..3b2eaa95e30d5f6c73336d32576b705d4cc6c118 100644 GIT binary patch literal 37956 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 Q_E!toNJ=CTA}<5i2^w)qP5=M^ literal 35508 zcmV(|K+(Tml0E#>S0RR9100000000000000000000 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

mPeq-^~Dpo?-?IXGp_*-O!$G2*y8 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 Mf=qr{x!xuK0M-?I3IG5A From 99cd9e42c08656f323062da3c525e8eaa6f1afed Mon Sep 17 00:00:00 2001 From: DarthGigi <47110839+DarthGigi@users.noreply.github.com> Date: Tue, 16 Jun 2026 16:28:11 +0200 Subject: [PATCH 07/11] feat: setup and install shadcn-svelte --- components.json | 20 +++++ package.json | 6 ++ pnpm-lock.yaml | 68 +++++++++++++++ .../components/ui/avatar/avatar-badge.svelte | 26 ++++++ .../ui/avatar/avatar-fallback.svelte | 20 +++++ .../ui/avatar/avatar-group-count.svelte | 23 ++++++ .../components/ui/avatar/avatar-group.svelte | 23 ++++++ .../components/ui/avatar/avatar-image.svelte | 17 ++++ src/lib/components/ui/avatar/avatar.svelte | 26 ++++++ src/lib/components/ui/avatar/index.ts | 22 +++++ src/lib/components/ui/button/button.svelte | 82 +++++++++++++++++++ src/lib/components/ui/button/index.ts | 17 ++++ .../ui/collapsible/collapsible-content.svelte | 7 ++ .../ui/collapsible/collapsible-trigger.svelte | 7 ++ .../ui/collapsible/collapsible.svelte | 11 +++ src/lib/components/ui/collapsible/index.ts | 13 +++ .../components/ui/dialog/dialog-close.svelte | 11 +++ .../ui/dialog/dialog-content.svelte | 48 +++++++++++ .../ui/dialog/dialog-description.svelte | 17 ++++ .../components/ui/dialog/dialog-footer.svelte | 32 ++++++++ .../components/ui/dialog/dialog-header.svelte | 20 +++++ .../ui/dialog/dialog-overlay.svelte | 17 ++++ .../components/ui/dialog/dialog-portal.svelte | 7 ++ .../components/ui/dialog/dialog-title.svelte | 17 ++++ .../ui/dialog/dialog-trigger.svelte | 11 +++ src/lib/components/ui/dialog/dialog.svelte | 7 ++ src/lib/components/ui/dialog/index.ts | 34 ++++++++ .../components/ui/drawer/drawer-close.svelte | 7 ++ .../ui/drawer/drawer-content.svelte | 33 ++++++++ .../ui/drawer/drawer-description.svelte | 17 ++++ .../components/ui/drawer/drawer-footer.svelte | 20 +++++ .../components/ui/drawer/drawer-header.svelte | 20 +++++ .../components/ui/drawer/drawer-nested.svelte | 12 +++ .../ui/drawer/drawer-overlay.svelte | 17 ++++ .../components/ui/drawer/drawer-portal.svelte | 7 ++ .../components/ui/drawer/drawer-title.svelte | 17 ++++ .../ui/drawer/drawer-trigger.svelte | 7 ++ src/lib/components/ui/drawer/drawer.svelte | 12 +++ src/lib/components/ui/drawer/index.ts | 38 +++++++++ .../components/ui/empty/empty-content.svelte | 23 ++++++ .../ui/empty/empty-description.svelte | 23 ++++++ .../components/ui/empty/empty-header.svelte | 20 +++++ .../components/ui/empty/empty-media.svelte | 41 ++++++++++ .../components/ui/empty/empty-title.svelte | 20 +++++ src/lib/components/ui/empty/empty.svelte | 23 ++++++ src/lib/components/ui/empty/index.ts | 22 +++++ src/lib/components/ui/input/index.ts | 7 ++ src/lib/components/ui/input/input.svelte | 48 +++++++++++ src/lib/components/ui/item/index.ts | 34 ++++++++ .../components/ui/item/item-actions.svelte | 20 +++++ .../components/ui/item/item-content.svelte | 23 ++++++ .../ui/item/item-description.svelte | 23 ++++++ src/lib/components/ui/item/item-footer.svelte | 20 +++++ src/lib/components/ui/item/item-group.svelte | 21 +++++ src/lib/components/ui/item/item-header.svelte | 20 +++++ src/lib/components/ui/item/item-media.svelte | 42 ++++++++++ .../components/ui/item/item-separator.svelte | 19 +++++ src/lib/components/ui/item/item-title.svelte | 20 +++++ src/lib/components/ui/item/item.svelte | 61 ++++++++++++++ src/lib/components/ui/label/index.ts | 7 ++ src/lib/components/ui/label/label.svelte | 20 +++++ src/lib/components/ui/popover/index.ts | 28 +++++++ .../ui/popover/popover-close.svelte | 7 ++ .../ui/popover/popover-content.svelte | 31 +++++++ .../ui/popover/popover-description.svelte | 20 +++++ .../ui/popover/popover-header.svelte | 20 +++++ .../ui/popover/popover-portal.svelte | 7 ++ .../ui/popover/popover-title.svelte | 20 +++++ .../ui/popover/popover-trigger.svelte | 17 ++++ src/lib/components/ui/popover/popover.svelte | 7 ++ src/lib/components/ui/progress/index.ts | 7 ++ .../components/ui/progress/progress.svelte | 27 ++++++ src/lib/components/ui/scroll-area/index.ts | 10 +++ .../scroll-area/scroll-area-scrollbar.svelte | 30 +++++++ .../ui/scroll-area/scroll-area.svelte | 45 ++++++++++ src/lib/components/ui/separator/index.ts | 7 ++ .../components/ui/separator/separator.svelte | 23 ++++++ src/lib/components/ui/spinner/index.ts | 1 + src/lib/components/ui/spinner/spinner.svelte | 18 ++++ src/lib/components/ui/switch/index.ts | 7 ++ src/lib/components/ui/switch/switch.svelte | 31 +++++++ src/lib/components/ui/tabs/index.ts | 18 ++++ .../components/ui/tabs/tabs-content.svelte | 17 ++++ src/lib/components/ui/tabs/tabs-list.svelte | 40 +++++++++ .../components/ui/tabs/tabs-trigger.svelte | 23 ++++++ src/lib/components/ui/tabs/tabs.svelte | 19 +++++ src/lib/components/ui/tooltip/index.ts | 19 +++++ .../ui/tooltip/tooltip-content.svelte | 52 ++++++++++++ .../ui/tooltip/tooltip-portal.svelte | 7 ++ .../ui/tooltip/tooltip-provider.svelte | 7 ++ .../ui/tooltip/tooltip-trigger.svelte | 7 ++ src/lib/components/ui/tooltip/tooltip.svelte | 7 ++ src/lib/shared/utils.ts | 9 +- 93 files changed, 1960 insertions(+), 1 deletion(-) create mode 100644 components.json create mode 100644 src/lib/components/ui/avatar/avatar-badge.svelte create mode 100644 src/lib/components/ui/avatar/avatar-fallback.svelte create mode 100644 src/lib/components/ui/avatar/avatar-group-count.svelte create mode 100644 src/lib/components/ui/avatar/avatar-group.svelte create mode 100644 src/lib/components/ui/avatar/avatar-image.svelte create mode 100644 src/lib/components/ui/avatar/avatar.svelte create mode 100644 src/lib/components/ui/avatar/index.ts create mode 100644 src/lib/components/ui/button/button.svelte create mode 100644 src/lib/components/ui/button/index.ts create mode 100644 src/lib/components/ui/collapsible/collapsible-content.svelte create mode 100644 src/lib/components/ui/collapsible/collapsible-trigger.svelte create mode 100644 src/lib/components/ui/collapsible/collapsible.svelte create mode 100644 src/lib/components/ui/collapsible/index.ts create mode 100644 src/lib/components/ui/dialog/dialog-close.svelte create mode 100644 src/lib/components/ui/dialog/dialog-content.svelte create mode 100644 src/lib/components/ui/dialog/dialog-description.svelte create mode 100644 src/lib/components/ui/dialog/dialog-footer.svelte create mode 100644 src/lib/components/ui/dialog/dialog-header.svelte create mode 100644 src/lib/components/ui/dialog/dialog-overlay.svelte create mode 100644 src/lib/components/ui/dialog/dialog-portal.svelte create mode 100644 src/lib/components/ui/dialog/dialog-title.svelte create mode 100644 src/lib/components/ui/dialog/dialog-trigger.svelte create mode 100644 src/lib/components/ui/dialog/dialog.svelte create mode 100644 src/lib/components/ui/dialog/index.ts create mode 100644 src/lib/components/ui/drawer/drawer-close.svelte create mode 100644 src/lib/components/ui/drawer/drawer-content.svelte create mode 100644 src/lib/components/ui/drawer/drawer-description.svelte create mode 100644 src/lib/components/ui/drawer/drawer-footer.svelte create mode 100644 src/lib/components/ui/drawer/drawer-header.svelte create mode 100644 src/lib/components/ui/drawer/drawer-nested.svelte create mode 100644 src/lib/components/ui/drawer/drawer-overlay.svelte create mode 100644 src/lib/components/ui/drawer/drawer-portal.svelte create mode 100644 src/lib/components/ui/drawer/drawer-title.svelte create mode 100644 src/lib/components/ui/drawer/drawer-trigger.svelte create mode 100644 src/lib/components/ui/drawer/drawer.svelte create mode 100644 src/lib/components/ui/drawer/index.ts create mode 100644 src/lib/components/ui/empty/empty-content.svelte create mode 100644 src/lib/components/ui/empty/empty-description.svelte create mode 100644 src/lib/components/ui/empty/empty-header.svelte create mode 100644 src/lib/components/ui/empty/empty-media.svelte create mode 100644 src/lib/components/ui/empty/empty-title.svelte create mode 100644 src/lib/components/ui/empty/empty.svelte create mode 100644 src/lib/components/ui/empty/index.ts create mode 100644 src/lib/components/ui/input/index.ts create mode 100644 src/lib/components/ui/input/input.svelte create mode 100644 src/lib/components/ui/item/index.ts create mode 100644 src/lib/components/ui/item/item-actions.svelte create mode 100644 src/lib/components/ui/item/item-content.svelte create mode 100644 src/lib/components/ui/item/item-description.svelte create mode 100644 src/lib/components/ui/item/item-footer.svelte create mode 100644 src/lib/components/ui/item/item-group.svelte create mode 100644 src/lib/components/ui/item/item-header.svelte create mode 100644 src/lib/components/ui/item/item-media.svelte create mode 100644 src/lib/components/ui/item/item-separator.svelte create mode 100644 src/lib/components/ui/item/item-title.svelte create mode 100644 src/lib/components/ui/item/item.svelte create mode 100644 src/lib/components/ui/label/index.ts create mode 100644 src/lib/components/ui/label/label.svelte create mode 100644 src/lib/components/ui/popover/index.ts create mode 100644 src/lib/components/ui/popover/popover-close.svelte create mode 100644 src/lib/components/ui/popover/popover-content.svelte create mode 100644 src/lib/components/ui/popover/popover-description.svelte create mode 100644 src/lib/components/ui/popover/popover-header.svelte create mode 100644 src/lib/components/ui/popover/popover-portal.svelte create mode 100644 src/lib/components/ui/popover/popover-title.svelte create mode 100644 src/lib/components/ui/popover/popover-trigger.svelte create mode 100644 src/lib/components/ui/popover/popover.svelte create mode 100644 src/lib/components/ui/progress/index.ts create mode 100644 src/lib/components/ui/progress/progress.svelte create mode 100644 src/lib/components/ui/scroll-area/index.ts create mode 100644 src/lib/components/ui/scroll-area/scroll-area-scrollbar.svelte create mode 100644 src/lib/components/ui/scroll-area/scroll-area.svelte create mode 100644 src/lib/components/ui/separator/index.ts create mode 100644 src/lib/components/ui/separator/separator.svelte create mode 100644 src/lib/components/ui/spinner/index.ts create mode 100644 src/lib/components/ui/spinner/spinner.svelte create mode 100644 src/lib/components/ui/switch/index.ts create mode 100644 src/lib/components/ui/switch/switch.svelte create mode 100644 src/lib/components/ui/tabs/index.ts create mode 100644 src/lib/components/ui/tabs/tabs-content.svelte create mode 100644 src/lib/components/ui/tabs/tabs-list.svelte create mode 100644 src/lib/components/ui/tabs/tabs-trigger.svelte create mode 100644 src/lib/components/ui/tabs/tabs.svelte create mode 100644 src/lib/components/ui/tooltip/index.ts create mode 100644 src/lib/components/ui/tooltip/tooltip-content.svelte create mode 100644 src/lib/components/ui/tooltip/tooltip-portal.svelte create mode 100644 src/lib/components/ui/tooltip/tooltip-provider.svelte create mode 100644 src/lib/components/ui/tooltip/tooltip-trigger.svelte create mode 100644 src/lib/components/ui/tooltip/tooltip.svelte diff --git a/components.json b/components.json new file mode 100644 index 000000000..94ebef162 --- /dev/null +++ b/components.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://shadcn-svelte.com/schema.json", + "tailwind": { + "css": "src/routes/layout.css", + "baseColor": "neutral" + }, + "aliases": { + "components": "$components", + "utils": "$utils", + "ui": "$ui", + "hooks": "$hooks", + "lib": "$lib" + }, + "typescript": true, + "registry": "https://shadcn-svelte.com/registry", + "style": "luma", + "iconLibrary": "lucide", + "menuColor": "default-translucent", + "menuAccent": "bold" +} diff --git a/package.json b/package.json index d71282edd..fe0ff4e8b 100644 --- a/package.json +++ b/package.json @@ -50,6 +50,9 @@ "@dnd-kit/helpers": "^0.4.0", "@dnd-kit/svelte": "^0.4.0", "@eslint/js": "^10.0.1", + "@fontsource-variable/montserrat": "^5.2.8", + "@fontsource/unifontex": "^5.2.6", + "@internationalized/date": "^3.12.1", "@lucide/svelte": "^1.17.0", "@oslojs/crypto": "^1.0.1", "@oslojs/encoding": "^1.1.0", @@ -95,6 +98,7 @@ "pretty-ms": "^9.3.0", "runed": "^0.37.1", "satori-html": "^0.3.2", + "shadcn-svelte": "^1.3.0", "skinview3d": "^3.4.2", "super-sitemap": "^1.0.12", "svelte": "^5.56.1", @@ -105,9 +109,11 @@ "svelte-tiny-virtual-list": "4.0.0-rc.2", "sveltekit-superforms": "^2.30.1", "tailwind-merge": "^3.6.0", + "tailwind-variants": "^3.2.2", "tailwindcss": "^4.3.0", "tailwindcss-motion": "^1.1.1", "tslib": "^2.8.1", + "tw-animate-css": "^1.4.0", "typescript": "^6.0.3", "typescript-eslint": "^8.60.1", "vaul-svelte": "1.0.0-next.7", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4b2e985fb..8710eacd2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -60,6 +60,15 @@ importers: '@eslint/js': specifier: ^10.0.1 version: 10.0.1(eslint@10.4.1(jiti@2.7.0)) + '@fontsource-variable/montserrat': + specifier: ^5.2.8 + version: 5.2.8 + '@fontsource/unifontex': + specifier: ^5.2.6 + version: 5.2.6 + '@internationalized/date': + specifier: ^3.12.1 + version: 3.12.1 '@lucide/svelte': specifier: ^1.17.0 version: 1.17.0(svelte@5.56.1(@typescript-eslint/types@8.60.1)) @@ -195,6 +204,9 @@ importers: satori-html: specifier: ^0.3.2 version: 0.3.2 + shadcn-svelte: + specifier: ^1.3.0 + version: 1.3.0(svelte@5.56.1(@typescript-eslint/types@8.60.1)) skinview3d: specifier: ^3.4.2 version: 3.4.2 @@ -225,6 +237,9 @@ importers: tailwind-merge: specifier: ^3.6.0 version: 3.6.0 + tailwind-variants: + specifier: ^3.2.2 + version: 3.2.2(tailwind-merge@3.6.0)(tailwindcss@4.3.0) tailwindcss: specifier: ^4.3.0 version: 4.3.0 @@ -234,6 +249,9 @@ importers: tslib: specifier: ^2.8.1 version: 2.8.1 + tw-animate-css: + specifier: ^1.4.0 + version: 1.4.0 typescript: specifier: ^6.0.3 version: 6.0.3 @@ -1489,6 +1507,12 @@ packages: '@floating-ui/utils@0.2.11': resolution: {integrity: sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==} + '@fontsource-variable/montserrat@5.2.8': + resolution: {integrity: sha512-d8wykq7GCKhEOlLwEuQIOK3w3qsXNxwDlH0meru4AZZzQ4/+rZyvHWKL6BBtHdmbovSHEEQDkwkD8qYUKlcFtQ==} + + '@fontsource/unifontex@5.2.6': + resolution: {integrity: sha512-y6PXONOAfsIx0v/7QevQrx+SFW6B2OBR7VZYel7ek/y8M89zfQBKOLyV8X9KmtAkS1q9JS9MFDkq78vcv1CwtQ==} + '@gerrit0/mini-shiki@3.23.0': resolution: {integrity: sha512-bEMORlG0cqdjVyCEuU0cDQbORWX+kYCeo0kV1lbxF5bt4r7SID2l9bqsxJEM0zndaxpOUT7riCyIVEuqq/Ynxg==} @@ -4671,6 +4695,9 @@ packages: sass: optional: true + node-fetch-native@1.6.7: + resolution: {integrity: sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==} + node-fetch@2.7.0: resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} engines: {node: 4.x || >=6.0.0} @@ -5296,6 +5323,12 @@ packages: set-cookie-parser@3.1.0: resolution: {integrity: sha512-kjnC1DXBHcxaOaOXBHBeRtltsDG2nUiUni+jP92M9gYdW12rsmx92UsfpH7o5tDRs7I1ZZPSQJQGv3UaRfCiuw==} + shadcn-svelte@1.3.0: + resolution: {integrity: sha512-Pd4ICWTkTks/b2YU4c9vF2XsX1x5HFPRl5bKszS1LcnWS83x+7T4WiIvbWz8Qh9knkcGZ+SCz1+Dmhdq+AYooA==} + hasBin: true + peerDependencies: + svelte: ^5.0.0 + sharp@0.34.5: resolution: {integrity: sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} @@ -5540,6 +5573,16 @@ packages: tailwind-merge@3.6.0: resolution: {integrity: sha512-uxL7qAVQriqRQPAyK3pj66VqskWqoZ37PW94jwOTwNfq/z9oyu1V+eqrZqtR2+fCiXdYOZe/Modt8GtvqNzu+w==} + tailwind-variants@3.2.2: + resolution: {integrity: sha512-Mi4kHeMTLvKlM98XPnK+7HoBPmf4gygdFmqQPaDivc3DpYS6aIY6KiG/PgThrGvii5YZJqRsPz0aPyhoFzmZgg==} + engines: {node: '>=16.x', pnpm: '>=7.x'} + peerDependencies: + tailwind-merge: '>=3.0.0' + tailwindcss: '*' + peerDependenciesMeta: + tailwind-merge: + optional: true + tailwindcss-motion@1.1.1: resolution: {integrity: sha512-CeeQAc5o31BuEPMyWdq/786X7QWNeifa+8khfu74Fs8lGkgEwjNYv6dGv+lRFS8FWXV5dp7F3AU9JjBXjiaQfw==} peerDependencies: @@ -5641,6 +5684,9 @@ packages: engines: {node: '>=18.0.0'} hasBin: true + tw-animate-css@1.4.0: + resolution: {integrity: sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ==} + type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} @@ -7158,6 +7204,10 @@ snapshots: '@floating-ui/utils@0.2.11': {} + '@fontsource-variable/montserrat@5.2.8': {} + + '@fontsource/unifontex@5.2.6': {} + '@gerrit0/mini-shiki@3.23.0': dependencies: '@shikijs/engine-oniguruma': 3.23.0 @@ -10536,6 +10586,8 @@ snapshots: - '@babel/core' - babel-plugin-macros + node-fetch-native@1.6.7: {} + node-fetch@2.7.0: dependencies: whatwg-url: 5.0.0 @@ -11177,6 +11229,14 @@ snapshots: set-cookie-parser@3.1.0: {} + shadcn-svelte@1.3.0(svelte@5.56.1(@typescript-eslint/types@8.60.1)): + dependencies: + commander: 14.0.3 + node-fetch-native: 1.6.7 + postcss: 8.5.15 + svelte: 5.56.1(@typescript-eslint/types@8.60.1) + tailwind-merge: 3.6.0 + sharp@0.34.5: dependencies: '@img/colour': 1.1.0 @@ -11466,6 +11526,12 @@ snapshots: tailwind-merge@3.6.0: {} + tailwind-variants@3.2.2(tailwind-merge@3.6.0)(tailwindcss@4.3.0): + dependencies: + tailwindcss: 4.3.0 + optionalDependencies: + tailwind-merge: 3.6.0 + tailwindcss-motion@1.1.1(tailwindcss@4.3.0): dependencies: tailwindcss: 4.3.0 @@ -11559,6 +11625,8 @@ snapshots: optionalDependencies: fsevents: 2.3.3 + tw-animate-css@1.4.0: {} + type-check@0.4.0: dependencies: prelude-ls: 1.2.1 diff --git a/src/lib/components/ui/avatar/avatar-badge.svelte b/src/lib/components/ui/avatar/avatar-badge.svelte new file mode 100644 index 000000000..a225e04c4 --- /dev/null +++ b/src/lib/components/ui/avatar/avatar-badge.svelte @@ -0,0 +1,26 @@ + + +svg]:hidden", + "group-data-[size=default]/avatar:size-2.5 group-data-[size=default]/avatar:[&>svg]:size-2", + "group-data-[size=lg]/avatar:size-3 group-data-[size=lg]/avatar:[&>svg]:size-2", + className + )} + {...restProps} +> + {@render children?.()} + diff --git a/src/lib/components/ui/avatar/avatar-fallback.svelte b/src/lib/components/ui/avatar/avatar-fallback.svelte new file mode 100644 index 000000000..838195049 --- /dev/null +++ b/src/lib/components/ui/avatar/avatar-fallback.svelte @@ -0,0 +1,20 @@ + + + diff --git a/src/lib/components/ui/avatar/avatar-group-count.svelte b/src/lib/components/ui/avatar/avatar-group-count.svelte new file mode 100644 index 000000000..c67718a70 --- /dev/null +++ b/src/lib/components/ui/avatar/avatar-group-count.svelte @@ -0,0 +1,23 @@ + + +

diff --git a/src/lib/components/ui/avatar/avatar-group.svelte b/src/lib/components/ui/avatar/avatar-group.svelte new file mode 100644 index 000000000..80ad07301 --- /dev/null +++ b/src/lib/components/ui/avatar/avatar-group.svelte @@ -0,0 +1,23 @@ + + +
+ {@render children?.()} +
diff --git a/src/lib/components/ui/avatar/avatar-image.svelte b/src/lib/components/ui/avatar/avatar-image.svelte new file mode 100644 index 000000000..8982d7ef4 --- /dev/null +++ b/src/lib/components/ui/avatar/avatar-image.svelte @@ -0,0 +1,17 @@ + + + diff --git a/src/lib/components/ui/avatar/avatar.svelte b/src/lib/components/ui/avatar/avatar.svelte new file mode 100644 index 000000000..3ae29fdd4 --- /dev/null +++ b/src/lib/components/ui/avatar/avatar.svelte @@ -0,0 +1,26 @@ + + + diff --git a/src/lib/components/ui/avatar/index.ts b/src/lib/components/ui/avatar/index.ts new file mode 100644 index 000000000..38ccef846 --- /dev/null +++ b/src/lib/components/ui/avatar/index.ts @@ -0,0 +1,22 @@ +import Root from "./avatar.svelte"; +import Image from "./avatar-image.svelte"; +import Fallback from "./avatar-fallback.svelte"; +import Badge from "./avatar-badge.svelte"; +import Group from "./avatar-group.svelte"; +import GroupCount from "./avatar-group-count.svelte"; + +export { + Root, + Image, + Fallback, + Badge, + Group, + GroupCount, + // + Root as Avatar, + Image as AvatarImage, + Fallback as AvatarFallback, + Badge as AvatarBadge, + Group as AvatarGroup, + GroupCount as AvatarGroupCount, +}; diff --git a/src/lib/components/ui/button/button.svelte b/src/lib/components/ui/button/button.svelte new file mode 100644 index 000000000..92370bc9a --- /dev/null +++ b/src/lib/components/ui/button/button.svelte @@ -0,0 +1,82 @@ + + + + +{#if href} +
+ {@render children?.()} + +{:else} + +{/if} diff --git a/src/lib/components/ui/button/index.ts b/src/lib/components/ui/button/index.ts new file mode 100644 index 000000000..fb585d768 --- /dev/null +++ b/src/lib/components/ui/button/index.ts @@ -0,0 +1,17 @@ +import Root, { + type ButtonProps, + type ButtonSize, + type ButtonVariant, + buttonVariants, +} from "./button.svelte"; + +export { + Root, + type ButtonProps as Props, + // + Root as Button, + buttonVariants, + type ButtonProps, + type ButtonSize, + type ButtonVariant, +}; diff --git a/src/lib/components/ui/collapsible/collapsible-content.svelte b/src/lib/components/ui/collapsible/collapsible-content.svelte new file mode 100644 index 000000000..bdabb559c --- /dev/null +++ b/src/lib/components/ui/collapsible/collapsible-content.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/ui/collapsible/collapsible-trigger.svelte b/src/lib/components/ui/collapsible/collapsible-trigger.svelte new file mode 100644 index 000000000..ece7ad68e --- /dev/null +++ b/src/lib/components/ui/collapsible/collapsible-trigger.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/ui/collapsible/collapsible.svelte b/src/lib/components/ui/collapsible/collapsible.svelte new file mode 100644 index 000000000..39cdd4e4e --- /dev/null +++ b/src/lib/components/ui/collapsible/collapsible.svelte @@ -0,0 +1,11 @@ + + + diff --git a/src/lib/components/ui/collapsible/index.ts b/src/lib/components/ui/collapsible/index.ts new file mode 100644 index 000000000..169b4791d --- /dev/null +++ b/src/lib/components/ui/collapsible/index.ts @@ -0,0 +1,13 @@ +import Root from "./collapsible.svelte"; +import Trigger from "./collapsible-trigger.svelte"; +import Content from "./collapsible-content.svelte"; + +export { + Root, + Content, + Trigger, + // + Root as Collapsible, + Content as CollapsibleContent, + Trigger as CollapsibleTrigger, +}; diff --git a/src/lib/components/ui/dialog/dialog-close.svelte b/src/lib/components/ui/dialog/dialog-close.svelte new file mode 100644 index 000000000..de68f2f0e --- /dev/null +++ b/src/lib/components/ui/dialog/dialog-close.svelte @@ -0,0 +1,11 @@ + + + diff --git a/src/lib/components/ui/dialog/dialog-content.svelte b/src/lib/components/ui/dialog/dialog-content.svelte new file mode 100644 index 000000000..aa0a8a1e0 --- /dev/null +++ b/src/lib/components/ui/dialog/dialog-content.svelte @@ -0,0 +1,48 @@ + + + + + + {@render children?.()} + {#if showCloseButton} + + {#snippet child({ props })} + + {/snippet} + + {/if} + + diff --git a/src/lib/components/ui/dialog/dialog-description.svelte b/src/lib/components/ui/dialog/dialog-description.svelte new file mode 100644 index 000000000..bf87f7337 --- /dev/null +++ b/src/lib/components/ui/dialog/dialog-description.svelte @@ -0,0 +1,17 @@ + + + diff --git a/src/lib/components/ui/dialog/dialog-footer.svelte b/src/lib/components/ui/dialog/dialog-footer.svelte new file mode 100644 index 000000000..a46f15336 --- /dev/null +++ b/src/lib/components/ui/dialog/dialog-footer.svelte @@ -0,0 +1,32 @@ + + +
+ {@render children?.()} + {#if showCloseButton} + + {#snippet child({ props })} + + {/snippet} + + {/if} +
diff --git a/src/lib/components/ui/dialog/dialog-header.svelte b/src/lib/components/ui/dialog/dialog-header.svelte new file mode 100644 index 000000000..418f35fac --- /dev/null +++ b/src/lib/components/ui/dialog/dialog-header.svelte @@ -0,0 +1,20 @@ + + +
+ {@render children?.()} +
diff --git a/src/lib/components/ui/dialog/dialog-overlay.svelte b/src/lib/components/ui/dialog/dialog-overlay.svelte new file mode 100644 index 000000000..a2e3dbfa9 --- /dev/null +++ b/src/lib/components/ui/dialog/dialog-overlay.svelte @@ -0,0 +1,17 @@ + + + diff --git a/src/lib/components/ui/dialog/dialog-portal.svelte b/src/lib/components/ui/dialog/dialog-portal.svelte new file mode 100644 index 000000000..ccfa79caf --- /dev/null +++ b/src/lib/components/ui/dialog/dialog-portal.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/ui/dialog/dialog-title.svelte b/src/lib/components/ui/dialog/dialog-title.svelte new file mode 100644 index 000000000..d283ddb57 --- /dev/null +++ b/src/lib/components/ui/dialog/dialog-title.svelte @@ -0,0 +1,17 @@ + + + diff --git a/src/lib/components/ui/dialog/dialog-trigger.svelte b/src/lib/components/ui/dialog/dialog-trigger.svelte new file mode 100644 index 000000000..589ee0c3d --- /dev/null +++ b/src/lib/components/ui/dialog/dialog-trigger.svelte @@ -0,0 +1,11 @@ + + + diff --git a/src/lib/components/ui/dialog/dialog.svelte b/src/lib/components/ui/dialog/dialog.svelte new file mode 100644 index 000000000..211672c6d --- /dev/null +++ b/src/lib/components/ui/dialog/dialog.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/ui/dialog/index.ts b/src/lib/components/ui/dialog/index.ts new file mode 100644 index 000000000..076cef528 --- /dev/null +++ b/src/lib/components/ui/dialog/index.ts @@ -0,0 +1,34 @@ +import Root from "./dialog.svelte"; +import Portal from "./dialog-portal.svelte"; +import Title from "./dialog-title.svelte"; +import Footer from "./dialog-footer.svelte"; +import Header from "./dialog-header.svelte"; +import Overlay from "./dialog-overlay.svelte"; +import Content from "./dialog-content.svelte"; +import Description from "./dialog-description.svelte"; +import Trigger from "./dialog-trigger.svelte"; +import Close from "./dialog-close.svelte"; + +export { + Root, + Title, + Portal, + Footer, + Header, + Trigger, + Overlay, + Content, + Description, + Close, + // + Root as Dialog, + Title as DialogTitle, + Portal as DialogPortal, + Footer as DialogFooter, + Header as DialogHeader, + Trigger as DialogTrigger, + Overlay as DialogOverlay, + Content as DialogContent, + Description as DialogDescription, + Close as DialogClose, +}; diff --git a/src/lib/components/ui/drawer/drawer-close.svelte b/src/lib/components/ui/drawer/drawer-close.svelte new file mode 100644 index 000000000..95c247963 --- /dev/null +++ b/src/lib/components/ui/drawer/drawer-close.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/ui/drawer/drawer-content.svelte b/src/lib/components/ui/drawer/drawer-content.svelte new file mode 100644 index 000000000..c01bcc91c --- /dev/null +++ b/src/lib/components/ui/drawer/drawer-content.svelte @@ -0,0 +1,33 @@ + + + + + + + {@render children?.()} + + diff --git a/src/lib/components/ui/drawer/drawer-description.svelte b/src/lib/components/ui/drawer/drawer-description.svelte new file mode 100644 index 000000000..a7847d4f3 --- /dev/null +++ b/src/lib/components/ui/drawer/drawer-description.svelte @@ -0,0 +1,17 @@ + + + diff --git a/src/lib/components/ui/drawer/drawer-footer.svelte b/src/lib/components/ui/drawer/drawer-footer.svelte new file mode 100644 index 000000000..1a9901928 --- /dev/null +++ b/src/lib/components/ui/drawer/drawer-footer.svelte @@ -0,0 +1,20 @@ + + +
+ {@render children?.()} +
diff --git a/src/lib/components/ui/drawer/drawer-header.svelte b/src/lib/components/ui/drawer/drawer-header.svelte new file mode 100644 index 000000000..2b9354e80 --- /dev/null +++ b/src/lib/components/ui/drawer/drawer-header.svelte @@ -0,0 +1,20 @@ + + +
+ {@render children?.()} +
diff --git a/src/lib/components/ui/drawer/drawer-nested.svelte b/src/lib/components/ui/drawer/drawer-nested.svelte new file mode 100644 index 000000000..834af9461 --- /dev/null +++ b/src/lib/components/ui/drawer/drawer-nested.svelte @@ -0,0 +1,12 @@ + + + diff --git a/src/lib/components/ui/drawer/drawer-overlay.svelte b/src/lib/components/ui/drawer/drawer-overlay.svelte new file mode 100644 index 000000000..9832c8e48 --- /dev/null +++ b/src/lib/components/ui/drawer/drawer-overlay.svelte @@ -0,0 +1,17 @@ + + + diff --git a/src/lib/components/ui/drawer/drawer-portal.svelte b/src/lib/components/ui/drawer/drawer-portal.svelte new file mode 100644 index 000000000..5a0dd7403 --- /dev/null +++ b/src/lib/components/ui/drawer/drawer-portal.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/ui/drawer/drawer-title.svelte b/src/lib/components/ui/drawer/drawer-title.svelte new file mode 100644 index 000000000..6925832d3 --- /dev/null +++ b/src/lib/components/ui/drawer/drawer-title.svelte @@ -0,0 +1,17 @@ + + + diff --git a/src/lib/components/ui/drawer/drawer-trigger.svelte b/src/lib/components/ui/drawer/drawer-trigger.svelte new file mode 100644 index 000000000..f1877d8e2 --- /dev/null +++ b/src/lib/components/ui/drawer/drawer-trigger.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/ui/drawer/drawer.svelte b/src/lib/components/ui/drawer/drawer.svelte new file mode 100644 index 000000000..0cb57ff99 --- /dev/null +++ b/src/lib/components/ui/drawer/drawer.svelte @@ -0,0 +1,12 @@ + + + diff --git a/src/lib/components/ui/drawer/index.ts b/src/lib/components/ui/drawer/index.ts new file mode 100644 index 000000000..1656cac54 --- /dev/null +++ b/src/lib/components/ui/drawer/index.ts @@ -0,0 +1,38 @@ +import Root from "./drawer.svelte"; +import Content from "./drawer-content.svelte"; +import Description from "./drawer-description.svelte"; +import Overlay from "./drawer-overlay.svelte"; +import Footer from "./drawer-footer.svelte"; +import Header from "./drawer-header.svelte"; +import Title from "./drawer-title.svelte"; +import NestedRoot from "./drawer-nested.svelte"; +import Close from "./drawer-close.svelte"; +import Trigger from "./drawer-trigger.svelte"; +import Portal from "./drawer-portal.svelte"; + +export { + Root, + NestedRoot, + Content, + Description, + Overlay, + Footer, + Header, + Title, + Trigger, + Portal, + Close, + + // + Root as Drawer, + NestedRoot as DrawerNestedRoot, + Content as DrawerContent, + Description as DrawerDescription, + Overlay as DrawerOverlay, + Footer as DrawerFooter, + Header as DrawerHeader, + Title as DrawerTitle, + Trigger as DrawerTrigger, + Portal as DrawerPortal, + Close as DrawerClose, +}; diff --git a/src/lib/components/ui/empty/empty-content.svelte b/src/lib/components/ui/empty/empty-content.svelte new file mode 100644 index 000000000..dd3567423 --- /dev/null +++ b/src/lib/components/ui/empty/empty-content.svelte @@ -0,0 +1,23 @@ + + +
+ {@render children?.()} +
diff --git a/src/lib/components/ui/empty/empty-description.svelte b/src/lib/components/ui/empty/empty-description.svelte new file mode 100644 index 000000000..7a5619e27 --- /dev/null +++ b/src/lib/components/ui/empty/empty-description.svelte @@ -0,0 +1,23 @@ + + +
a:hover]:text-primary text-sm/relaxed [&>a]:underline [&>a]:underline-offset-4", + className + )} + {...restProps} +> + {@render children?.()} +
diff --git a/src/lib/components/ui/empty/empty-header.svelte b/src/lib/components/ui/empty/empty-header.svelte new file mode 100644 index 000000000..0087139d7 --- /dev/null +++ b/src/lib/components/ui/empty/empty-header.svelte @@ -0,0 +1,20 @@ + + +
+ {@render children?.()} +
diff --git a/src/lib/components/ui/empty/empty-media.svelte b/src/lib/components/ui/empty/empty-media.svelte new file mode 100644 index 000000000..381b456c8 --- /dev/null +++ b/src/lib/components/ui/empty/empty-media.svelte @@ -0,0 +1,41 @@ + + + + +
+ {@render children?.()} +
diff --git a/src/lib/components/ui/empty/empty-title.svelte b/src/lib/components/ui/empty/empty-title.svelte new file mode 100644 index 000000000..8a7def26a --- /dev/null +++ b/src/lib/components/ui/empty/empty-title.svelte @@ -0,0 +1,20 @@ + + +
+ {@render children?.()} +
diff --git a/src/lib/components/ui/empty/empty.svelte b/src/lib/components/ui/empty/empty.svelte new file mode 100644 index 000000000..3abd82d3c --- /dev/null +++ b/src/lib/components/ui/empty/empty.svelte @@ -0,0 +1,23 @@ + + +
+ {@render children?.()} +
diff --git a/src/lib/components/ui/empty/index.ts b/src/lib/components/ui/empty/index.ts new file mode 100644 index 000000000..ae4c106ee --- /dev/null +++ b/src/lib/components/ui/empty/index.ts @@ -0,0 +1,22 @@ +import Root from "./empty.svelte"; +import Header from "./empty-header.svelte"; +import Media from "./empty-media.svelte"; +import Title from "./empty-title.svelte"; +import Description from "./empty-description.svelte"; +import Content from "./empty-content.svelte"; + +export { + Root, + Header, + Media, + Title, + Description, + Content, + // + Root as Empty, + Header as EmptyHeader, + Media as EmptyMedia, + Title as EmptyTitle, + Description as EmptyDescription, + Content as EmptyContent, +}; diff --git a/src/lib/components/ui/input/index.ts b/src/lib/components/ui/input/index.ts new file mode 100644 index 000000000..f47b6d3fb --- /dev/null +++ b/src/lib/components/ui/input/index.ts @@ -0,0 +1,7 @@ +import Root from "./input.svelte"; + +export { + Root, + // + Root as Input, +}; diff --git a/src/lib/components/ui/input/input.svelte b/src/lib/components/ui/input/input.svelte new file mode 100644 index 000000000..fe7f48d2c --- /dev/null +++ b/src/lib/components/ui/input/input.svelte @@ -0,0 +1,48 @@ + + +{#if type === "file"} + +{:else} + +{/if} diff --git a/src/lib/components/ui/item/index.ts b/src/lib/components/ui/item/index.ts new file mode 100644 index 000000000..168bc3eca --- /dev/null +++ b/src/lib/components/ui/item/index.ts @@ -0,0 +1,34 @@ +import Root from "./item.svelte"; +import Group from "./item-group.svelte"; +import Separator from "./item-separator.svelte"; +import Header from "./item-header.svelte"; +import Footer from "./item-footer.svelte"; +import Content from "./item-content.svelte"; +import Title from "./item-title.svelte"; +import Description from "./item-description.svelte"; +import Actions from "./item-actions.svelte"; +import Media from "./item-media.svelte"; + +export { + Root, + Group, + Separator, + Header, + Footer, + Content, + Title, + Description, + Actions, + Media, + // + Root as Item, + Group as ItemGroup, + Separator as ItemSeparator, + Header as ItemHeader, + Footer as ItemFooter, + Content as ItemContent, + Title as ItemTitle, + Description as ItemDescription, + Actions as ItemActions, + Media as ItemMedia, +}; diff --git a/src/lib/components/ui/item/item-actions.svelte b/src/lib/components/ui/item/item-actions.svelte new file mode 100644 index 000000000..b6a79b233 --- /dev/null +++ b/src/lib/components/ui/item/item-actions.svelte @@ -0,0 +1,20 @@ + + +
+ {@render children?.()} +
diff --git a/src/lib/components/ui/item/item-content.svelte b/src/lib/components/ui/item/item-content.svelte new file mode 100644 index 000000000..f56c07187 --- /dev/null +++ b/src/lib/components/ui/item/item-content.svelte @@ -0,0 +1,23 @@ + + +
+ {@render children?.()} +
diff --git a/src/lib/components/ui/item/item-description.svelte b/src/lib/components/ui/item/item-description.svelte new file mode 100644 index 000000000..e3f2d71f4 --- /dev/null +++ b/src/lib/components/ui/item/item-description.svelte @@ -0,0 +1,23 @@ + + +

a:hover]:text-primary line-clamp-2 font-normal [&>a]:underline [&>a]:underline-offset-4", + className + )} + {...restProps} +> + {@render children?.()} +

diff --git a/src/lib/components/ui/item/item-footer.svelte b/src/lib/components/ui/item/item-footer.svelte new file mode 100644 index 000000000..67b2a342c --- /dev/null +++ b/src/lib/components/ui/item/item-footer.svelte @@ -0,0 +1,20 @@ + + +
+ {@render children?.()} +
diff --git a/src/lib/components/ui/item/item-group.svelte b/src/lib/components/ui/item/item-group.svelte new file mode 100644 index 000000000..7c841ae48 --- /dev/null +++ b/src/lib/components/ui/item/item-group.svelte @@ -0,0 +1,21 @@ + + +
+ {@render children?.()} +
diff --git a/src/lib/components/ui/item/item-header.svelte b/src/lib/components/ui/item/item-header.svelte new file mode 100644 index 000000000..9174521d4 --- /dev/null +++ b/src/lib/components/ui/item/item-header.svelte @@ -0,0 +1,20 @@ + + +
+ {@render children?.()} +
diff --git a/src/lib/components/ui/item/item-media.svelte b/src/lib/components/ui/item/item-media.svelte new file mode 100644 index 000000000..b8666acfc --- /dev/null +++ b/src/lib/components/ui/item/item-media.svelte @@ -0,0 +1,42 @@ + + + + +
+ {@render children?.()} +
diff --git a/src/lib/components/ui/item/item-separator.svelte b/src/lib/components/ui/item/item-separator.svelte new file mode 100644 index 000000000..a973d45a1 --- /dev/null +++ b/src/lib/components/ui/item/item-separator.svelte @@ -0,0 +1,19 @@ + + + diff --git a/src/lib/components/ui/item/item-title.svelte b/src/lib/components/ui/item/item-title.svelte new file mode 100644 index 000000000..e5913ac9c --- /dev/null +++ b/src/lib/components/ui/item/item-title.svelte @@ -0,0 +1,20 @@ + + +
+ {@render children?.()} +
diff --git a/src/lib/components/ui/item/item.svelte b/src/lib/components/ui/item/item.svelte new file mode 100644 index 000000000..ffbc819ac --- /dev/null +++ b/src/lib/components/ui/item/item.svelte @@ -0,0 +1,61 @@ + + + + +{#if child} + {@render child({ props: mergedProps })} +{:else} +
+ {@render mergedProps.children?.()} +
+{/if} diff --git a/src/lib/components/ui/label/index.ts b/src/lib/components/ui/label/index.ts new file mode 100644 index 000000000..8bfca0b3f --- /dev/null +++ b/src/lib/components/ui/label/index.ts @@ -0,0 +1,7 @@ +import Root from "./label.svelte"; + +export { + Root, + // + Root as Label, +}; diff --git a/src/lib/components/ui/label/label.svelte b/src/lib/components/ui/label/label.svelte new file mode 100644 index 000000000..560893728 --- /dev/null +++ b/src/lib/components/ui/label/label.svelte @@ -0,0 +1,20 @@ + + + diff --git a/src/lib/components/ui/popover/index.ts b/src/lib/components/ui/popover/index.ts new file mode 100644 index 000000000..5f1803639 --- /dev/null +++ b/src/lib/components/ui/popover/index.ts @@ -0,0 +1,28 @@ +import Root from "./popover.svelte"; +import Close from "./popover-close.svelte"; +import Content from "./popover-content.svelte"; +import Description from "./popover-description.svelte"; +import Header from "./popover-header.svelte"; +import Title from "./popover-title.svelte"; +import Trigger from "./popover-trigger.svelte"; +import Portal from "./popover-portal.svelte"; + +export { + Root, + Content, + Description, + Header, + Title, + Trigger, + Close, + Portal, + // + Root as Popover, + Content as PopoverContent, + Description as PopoverDescription, + Header as PopoverHeader, + Title as PopoverTitle, + Trigger as PopoverTrigger, + Close as PopoverClose, + Portal as PopoverPortal, +}; diff --git a/src/lib/components/ui/popover/popover-close.svelte b/src/lib/components/ui/popover/popover-close.svelte new file mode 100644 index 000000000..c360925ac --- /dev/null +++ b/src/lib/components/ui/popover/popover-close.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/ui/popover/popover-content.svelte b/src/lib/components/ui/popover/popover-content.svelte new file mode 100644 index 000000000..318acc8d8 --- /dev/null +++ b/src/lib/components/ui/popover/popover-content.svelte @@ -0,0 +1,31 @@ + + + + + diff --git a/src/lib/components/ui/popover/popover-description.svelte b/src/lib/components/ui/popover/popover-description.svelte new file mode 100644 index 000000000..56de57475 --- /dev/null +++ b/src/lib/components/ui/popover/popover-description.svelte @@ -0,0 +1,20 @@ + + +
+ {@render children?.()} +
diff --git a/src/lib/components/ui/popover/popover-header.svelte b/src/lib/components/ui/popover/popover-header.svelte new file mode 100644 index 000000000..b9fcb3e9c --- /dev/null +++ b/src/lib/components/ui/popover/popover-header.svelte @@ -0,0 +1,20 @@ + + +
+ {@render children?.()} +
diff --git a/src/lib/components/ui/popover/popover-portal.svelte b/src/lib/components/ui/popover/popover-portal.svelte new file mode 100644 index 000000000..dd8265fe8 --- /dev/null +++ b/src/lib/components/ui/popover/popover-portal.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/ui/popover/popover-title.svelte b/src/lib/components/ui/popover/popover-title.svelte new file mode 100644 index 000000000..6c0b8c470 --- /dev/null +++ b/src/lib/components/ui/popover/popover-title.svelte @@ -0,0 +1,20 @@ + + +
+ {@render children?.()} +
diff --git a/src/lib/components/ui/popover/popover-trigger.svelte b/src/lib/components/ui/popover/popover-trigger.svelte new file mode 100644 index 000000000..bd6af9dcd --- /dev/null +++ b/src/lib/components/ui/popover/popover-trigger.svelte @@ -0,0 +1,17 @@ + + + diff --git a/src/lib/components/ui/popover/popover.svelte b/src/lib/components/ui/popover/popover.svelte new file mode 100644 index 000000000..6b1aa5f99 --- /dev/null +++ b/src/lib/components/ui/popover/popover.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/ui/progress/index.ts b/src/lib/components/ui/progress/index.ts new file mode 100644 index 000000000..25eee615a --- /dev/null +++ b/src/lib/components/ui/progress/index.ts @@ -0,0 +1,7 @@ +import Root from "./progress.svelte"; + +export { + Root, + // + Root as Progress, +}; diff --git a/src/lib/components/ui/progress/progress.svelte b/src/lib/components/ui/progress/progress.svelte new file mode 100644 index 000000000..48d82742e --- /dev/null +++ b/src/lib/components/ui/progress/progress.svelte @@ -0,0 +1,27 @@ + + + +
+
diff --git a/src/lib/components/ui/scroll-area/index.ts b/src/lib/components/ui/scroll-area/index.ts new file mode 100644 index 000000000..e86a25b21 --- /dev/null +++ b/src/lib/components/ui/scroll-area/index.ts @@ -0,0 +1,10 @@ +import Scrollbar from "./scroll-area-scrollbar.svelte"; +import Root from "./scroll-area.svelte"; + +export { + Root, + Scrollbar, + //, + Root as ScrollArea, + Scrollbar as ScrollAreaScrollbar, +}; diff --git a/src/lib/components/ui/scroll-area/scroll-area-scrollbar.svelte b/src/lib/components/ui/scroll-area/scroll-area-scrollbar.svelte new file mode 100644 index 000000000..340899389 --- /dev/null +++ b/src/lib/components/ui/scroll-area/scroll-area-scrollbar.svelte @@ -0,0 +1,30 @@ + + + + {@render children?.()} + + diff --git a/src/lib/components/ui/scroll-area/scroll-area.svelte b/src/lib/components/ui/scroll-area/scroll-area.svelte new file mode 100644 index 000000000..89046f96f --- /dev/null +++ b/src/lib/components/ui/scroll-area/scroll-area.svelte @@ -0,0 +1,45 @@ + + + + + {@render children?.()} + + {#if orientation === "vertical" || orientation === "both"} + + {/if} + {#if orientation === "horizontal" || orientation === "both"} + + {/if} + + diff --git a/src/lib/components/ui/separator/index.ts b/src/lib/components/ui/separator/index.ts new file mode 100644 index 000000000..82442d2cd --- /dev/null +++ b/src/lib/components/ui/separator/index.ts @@ -0,0 +1,7 @@ +import Root from "./separator.svelte"; + +export { + Root, + // + Root as Separator, +}; diff --git a/src/lib/components/ui/separator/separator.svelte b/src/lib/components/ui/separator/separator.svelte new file mode 100644 index 000000000..2d924e815 --- /dev/null +++ b/src/lib/components/ui/separator/separator.svelte @@ -0,0 +1,23 @@ + + + diff --git a/src/lib/components/ui/spinner/index.ts b/src/lib/components/ui/spinner/index.ts new file mode 100644 index 000000000..f8b1cedde --- /dev/null +++ b/src/lib/components/ui/spinner/index.ts @@ -0,0 +1 @@ +export { default as Spinner } from "./spinner.svelte"; diff --git a/src/lib/components/ui/spinner/spinner.svelte b/src/lib/components/ui/spinner/spinner.svelte new file mode 100644 index 000000000..6cee2e4cf --- /dev/null +++ b/src/lib/components/ui/spinner/spinner.svelte @@ -0,0 +1,18 @@ + + + diff --git a/src/lib/components/ui/switch/index.ts b/src/lib/components/ui/switch/index.ts new file mode 100644 index 000000000..f5533db72 --- /dev/null +++ b/src/lib/components/ui/switch/index.ts @@ -0,0 +1,7 @@ +import Root from "./switch.svelte"; + +export { + Root, + // + Root as Switch, +}; diff --git a/src/lib/components/ui/switch/switch.svelte b/src/lib/components/ui/switch/switch.svelte new file mode 100644 index 000000000..36cd04caf --- /dev/null +++ b/src/lib/components/ui/switch/switch.svelte @@ -0,0 +1,31 @@ + + + + + diff --git a/src/lib/components/ui/tabs/index.ts b/src/lib/components/ui/tabs/index.ts new file mode 100644 index 000000000..31267e58d --- /dev/null +++ b/src/lib/components/ui/tabs/index.ts @@ -0,0 +1,18 @@ +import Root from "./tabs.svelte"; +import Content from "./tabs-content.svelte"; +import List, { tabsListVariants, type TabsListVariant } from "./tabs-list.svelte"; +import Trigger from "./tabs-trigger.svelte"; + +export { + Root, + Content, + List, + Trigger, + tabsListVariants, + type TabsListVariant, + // + Root as Tabs, + Content as TabsContent, + List as TabsList, + Trigger as TabsTrigger, +}; diff --git a/src/lib/components/ui/tabs/tabs-content.svelte b/src/lib/components/ui/tabs/tabs-content.svelte new file mode 100644 index 000000000..4cd41576a --- /dev/null +++ b/src/lib/components/ui/tabs/tabs-content.svelte @@ -0,0 +1,17 @@ + + + diff --git a/src/lib/components/ui/tabs/tabs-list.svelte b/src/lib/components/ui/tabs/tabs-list.svelte new file mode 100644 index 000000000..34da93cf7 --- /dev/null +++ b/src/lib/components/ui/tabs/tabs-list.svelte @@ -0,0 +1,40 @@ + + + + + diff --git a/src/lib/components/ui/tabs/tabs-trigger.svelte b/src/lib/components/ui/tabs/tabs-trigger.svelte new file mode 100644 index 000000000..5e325d56a --- /dev/null +++ b/src/lib/components/ui/tabs/tabs-trigger.svelte @@ -0,0 +1,23 @@ + + + diff --git a/src/lib/components/ui/tabs/tabs.svelte b/src/lib/components/ui/tabs/tabs.svelte new file mode 100644 index 000000000..74e35b50c --- /dev/null +++ b/src/lib/components/ui/tabs/tabs.svelte @@ -0,0 +1,19 @@ + + + diff --git a/src/lib/components/ui/tooltip/index.ts b/src/lib/components/ui/tooltip/index.ts new file mode 100644 index 000000000..171860421 --- /dev/null +++ b/src/lib/components/ui/tooltip/index.ts @@ -0,0 +1,19 @@ +import Root from "./tooltip.svelte"; +import Trigger from "./tooltip-trigger.svelte"; +import Content from "./tooltip-content.svelte"; +import Provider from "./tooltip-provider.svelte"; +import Portal from "./tooltip-portal.svelte"; + +export { + Root, + Trigger, + Content, + Provider, + Portal, + // + Root as Tooltip, + Content as TooltipContent, + Trigger as TooltipTrigger, + Provider as TooltipProvider, + Portal as TooltipPortal, +}; diff --git a/src/lib/components/ui/tooltip/tooltip-content.svelte b/src/lib/components/ui/tooltip/tooltip-content.svelte new file mode 100644 index 000000000..e02bac2d5 --- /dev/null +++ b/src/lib/components/ui/tooltip/tooltip-content.svelte @@ -0,0 +1,52 @@ + + + + + {@render children?.()} + + {#snippet child({ props })} +
+ {/snippet} +
+
+
diff --git a/src/lib/components/ui/tooltip/tooltip-portal.svelte b/src/lib/components/ui/tooltip/tooltip-portal.svelte new file mode 100644 index 000000000..d234f7d7d --- /dev/null +++ b/src/lib/components/ui/tooltip/tooltip-portal.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/ui/tooltip/tooltip-provider.svelte b/src/lib/components/ui/tooltip/tooltip-provider.svelte new file mode 100644 index 000000000..6dba9a670 --- /dev/null +++ b/src/lib/components/ui/tooltip/tooltip-provider.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/ui/tooltip/tooltip-trigger.svelte b/src/lib/components/ui/tooltip/tooltip-trigger.svelte new file mode 100644 index 000000000..1acdaa47b --- /dev/null +++ b/src/lib/components/ui/tooltip/tooltip-trigger.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/ui/tooltip/tooltip.svelte b/src/lib/components/ui/tooltip/tooltip.svelte new file mode 100644 index 000000000..0b0f9cef2 --- /dev/null +++ b/src/lib/components/ui/tooltip/tooltip.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/shared/utils.ts b/src/lib/shared/utils.ts index fecf8b649..c69a494ec 100644 --- a/src/lib/shared/utils.ts +++ b/src/lib/shared/utils.ts @@ -7,10 +7,17 @@ import { twMerge } from "tailwind-merge"; * @param {ClassValue[]} inputs The classes to merge * @returns {string} The merged classes */ -export function cn(...inputs: ClassValue[]) { +export function cn(...inputs: ClassValue[]): string { return twMerge(clsx(inputs)); } +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export type WithoutChild = T extends { child?: any } ? Omit : T; +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export type WithoutChildren = T extends { children?: any } ? Omit : T; +export type WithoutChildrenOrChild = WithoutChildren>; +export type WithElementRef = T & { ref?: U | null }; + type FlyAndScaleParams = { y?: number; x?: number; From 87b02c7dfd10a9c7ff9abfa2375be18baf9b36c6 Mon Sep 17 00:00:00 2001 From: DarthGigi <47110839+DarthGigi@users.noreply.github.com> Date: Tue, 16 Jun 2026 16:28:28 +0200 Subject: [PATCH 08/11] feat: add performance mode and Minecraft tooltip toggles for development --- src/routes/+layout.svelte | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 74e872d55..68676f484 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -84,6 +84,14 @@ e.preventDefault(); internalState.openCommand = true; } + if (e.key.toLowerCase() === "p" && dev) { + // toggle performance mode for testing + preferences.performanceMode = !preferences.performanceMode; + } + if (e.key.toLowerCase() === "m" && dev) { + // toggle minecraft styled tooltips for testing + preferences.mctooltip = !preferences.mctooltip; + } } initDisabledPacks(); @@ -233,7 +241,7 @@ {#if showNewsroomToast} {#snippet failed()}{/snippet} - {@const latestNewsroom = await listLatestPostsForNotifications({ limit: 5 })} + {const latestNewsroom = await listLatestPostsForNotifications({ limit: 5 })} {/if} From 6f399d4e45259ea1d80b9d870ede8084bc4e8397 Mon Sep 17 00:00:00 2001 From: DarthGigi <47110839+DarthGigi@users.noreply.github.com> Date: Tue, 16 Jun 2026 16:29:01 +0200 Subject: [PATCH 09/11] feat: migrate to shadcn-svelte, modernize ui and the codebase --- src/app.html | 2 +- .../CollapsibleCustomTrigger.svelte | 28 ++ src/lib/components/EmptyStat.svelte | 26 + src/lib/components/ScrollAreaItems.svelte | 51 ++ .../components/header/settings/Order.svelte | 2 +- .../header/settings/Settings.svelte | 2 +- .../components/header/settings/Themes.svelte | 4 +- src/lib/components/item/InventoryGrid.svelte | 8 +- .../components/item/InventorySearch.svelte | 52 +- src/lib/components/item/Item.svelte | 11 +- src/lib/components/misc/Chip.svelte | 11 +- src/lib/components/misc/CommandPalette.svelte | 2 +- .../misc/CommandSettingsGroup.svelte | 4 +- .../components/misc/ContributorCard.svelte | 2 +- src/lib/components/misc/Navbar.svelte | 32 +- src/lib/components/misc/ScrollItems.svelte | 2 +- src/lib/components/misc/SearchTabs.svelte | 130 +++++ src/lib/components/misc/index.ts | 1 + src/lib/components/notices/APINotice.svelte | 2 +- src/lib/components/notices/BetaNotice.svelte | 2 +- src/lib/components/sections/Section.svelte | 32 +- .../sections/SectionBoundary.svelte | 8 +- .../sections/SectionSubtitle.svelte | 2 +- .../components/sections/SectionTitle.svelte | 2 +- src/lib/components/stats/AdditionStat.svelte | 86 ++-- src/lib/components/stats/Bonus.svelte | 4 +- src/lib/components/stats/CardBuilder.svelte | 178 ++++--- .../components/stats/DungeonCataCard.svelte | 106 ++-- .../components/stats/GardenPlotGrid.svelte | 69 ++- src/lib/components/stats/NetworthCard.svelte | 43 +- src/lib/components/stats/Skillbar.svelte | 62 +-- src/lib/components/stats/Stat.svelte | 69 ++- .../theme-editor/MCColorSection.svelte | 2 +- .../components/tooltip/TooltipSetup.svelte | 5 +- src/lib/layouts/stats/AdditionalStats.svelte | 104 ++-- src/lib/layouts/stats/Items.svelte | 10 +- src/lib/layouts/stats/Main.svelte | 5 +- src/lib/layouts/stats/PlayerProfile.svelte | 339 ++++++------- src/lib/layouts/stats/Stats.svelte | 9 +- src/lib/sections/Sections.svelte | 58 +-- src/lib/sections/stats/Accessories.svelte | 330 ++++++------- src/lib/sections/stats/Bestiary.svelte | 126 ++--- src/lib/sections/stats/Collections.svelte | 122 +++-- src/lib/sections/stats/CrimsonIsle.svelte | 132 ++--- src/lib/sections/stats/Dungeons.svelte | 49 +- src/lib/sections/stats/Gear.svelte | 159 +++--- src/lib/sections/stats/Inventory.svelte | 126 +++-- src/lib/sections/stats/Minions.svelte | 139 +++--- src/lib/sections/stats/MiscSection.svelte | 36 +- src/lib/sections/stats/Pets.svelte | 219 ++++----- src/lib/sections/stats/Rift.svelte | 249 +++++----- src/lib/sections/stats/SkillsSection.svelte | 49 +- src/lib/sections/stats/Slayer.svelte | 66 +-- src/lib/sections/stats/farming/garden.svelte | 223 +++++---- src/lib/sections/stats/misc/auctions.svelte | 85 ++-- src/lib/sections/stats/misc/chips.svelte | 22 +- src/lib/sections/stats/misc/claimed.svelte | 41 +- src/lib/sections/stats/misc/damage.svelte | 21 +- src/lib/sections/stats/misc/dragons.svelte | 74 +-- src/lib/sections/stats/misc/endstone.svelte | 21 +- src/lib/sections/stats/misc/gifts.svelte | 21 +- src/lib/sections/stats/misc/jerry.svelte | 21 +- src/lib/sections/stats/misc/kills.svelte | 23 +- .../sections/stats/misc/mythological.svelte | 113 +++-- src/lib/sections/stats/misc/pet.svelte | 72 ++- src/lib/sections/stats/misc/potions.svelte | 26 - src/lib/sections/stats/misc/races.svelte | 56 --- .../sections/stats/misc/uncategorized.svelte | 19 +- src/lib/sections/stats/misc/upgrades.svelte | 25 +- .../skills/current-tab-context.svelte.ts | 16 + .../sections/stats/skills/enchanting.svelte | 53 +- src/lib/sections/stats/skills/farming.svelte | 173 ++++--- src/lib/sections/stats/skills/fishing.svelte | 334 ++++++------- src/lib/sections/stats/skills/foraging.svelte | 190 ++++---- src/lib/sections/stats/skills/hunting.svelte | 198 +++----- src/lib/sections/stats/skills/mining.svelte | 460 ++++++++++-------- src/routes/+page.svelte | 2 +- 77 files changed, 2959 insertions(+), 2699 deletions(-) create mode 100644 src/lib/components/CollapsibleCustomTrigger.svelte create mode 100644 src/lib/components/EmptyStat.svelte create mode 100644 src/lib/components/ScrollAreaItems.svelte create mode 100644 src/lib/components/misc/SearchTabs.svelte delete mode 100644 src/lib/sections/stats/misc/potions.svelte delete mode 100644 src/lib/sections/stats/misc/races.svelte create mode 100644 src/lib/sections/stats/skills/current-tab-context.svelte.ts diff --git a/src/app.html b/src/app.html index 9c5b3e780..a9f55664c 100644 --- a/src/app.html +++ b/src/app.html @@ -1,5 +1,5 @@ - + diff --git a/src/lib/components/CollapsibleCustomTrigger.svelte b/src/lib/components/CollapsibleCustomTrigger.svelte new file mode 100644 index 000000000..c4c34e473 --- /dev/null +++ b/src/lib/components/CollapsibleCustomTrigger.svelte @@ -0,0 +1,28 @@ + + + +
+
+ +
+
+ +
+
+ + {@render children?.()} +
diff --git a/src/lib/components/EmptyStat.svelte b/src/lib/components/EmptyStat.svelte new file mode 100644 index 000000000..585a59317 --- /dev/null +++ b/src/lib/components/EmptyStat.svelte @@ -0,0 +1,26 @@ + + + + + + + + {title} + {#if description} + {description} + {/if} + + diff --git a/src/lib/components/ScrollAreaItems.svelte b/src/lib/components/ScrollAreaItems.svelte new file mode 100644 index 000000000..244f523aa --- /dev/null +++ b/src/lib/components/ScrollAreaItems.svelte @@ -0,0 +1,51 @@ + + + +
+ {@render children?.()} +
+
+
+
diff --git a/src/lib/components/header/settings/Order.svelte b/src/lib/components/header/settings/Order.svelte index 23f6503ec..825069489 100644 --- a/src/lib/components/header/settings/Order.svelte +++ b/src/lib/components/header/settings/Order.svelte @@ -41,7 +41,7 @@ {#key providerKey} {#each sectionOrder as section, index (section.id)} - {@const sortable = createSortable({ + {const sortable = createSortable({ id: section.id, get index() { return index; diff --git a/src/lib/components/header/settings/Settings.svelte b/src/lib/components/header/settings/Settings.svelte index ebad11779..9644e7b4b 100644 --- a/src/lib/components/header/settings/Settings.svelte +++ b/src/lib/components/header/settings/Settings.svelte @@ -71,7 +71,7 @@ {/snippet} - + {#snippet child({ props, open })} {#if open}
diff --git a/src/lib/components/header/settings/Themes.svelte b/src/lib/components/header/settings/Themes.svelte index 006e03637..4266326a4 100644 --- a/src/lib/components/header/settings/Themes.svelte +++ b/src/lib/components/header/settings/Themes.svelte @@ -69,7 +69,7 @@
Official Themes
{#each FIRST_PARTY_THEMES as theme (theme.metadata.id)} {#await getThemeIcons({ color: theme.colors.logo, invert: theme.light }) then iconSvg} - {@const iconDataUrl = `data:image/svg+xml;base64,${btoa(iconSvg)}`} + {const iconDataUrl = `data:image/svg+xml;base64,${btoa(iconSvg)}`}
@@ -101,7 +101,7 @@ {:else} {#each themeContext.userThemes as theme (theme.metadata.id)} {#await getThemeIcons({ color: theme.colors?.logo, invert: theme.light }) then iconSvg} - {@const iconDataUrl = `data:image/svg+xml;base64,${btoa(iconSvg)}`} + {const iconDataUrl = `data:image/svg+xml;base64,${btoa(iconSvg)}`}
diff --git a/src/lib/components/item/InventoryGrid.svelte b/src/lib/components/item/InventoryGrid.svelte index 8c4310421..28d32d41a 100644 --- a/src/lib/components/item/InventoryGrid.svelte +++ b/src/lib/components/item/InventoryGrid.svelte @@ -1,7 +1,9 @@ - { e.stopPropagation(); }} /> -{#if debouncedSearch.current === "" || !debouncedSearch.current}{:else} - searchInventorySection({ uuid, profileId, searchParam: debouncedSearch.current! })}> - {#snippet children(items: ModelsStrippedItem[])} - {#if !items || items.length === 0} -

No items found.

- {:else if debouncedSearch.current !== ""} -
- {#each items as item, index (index)} - {#if item} -
- {@render itemSnippet(item)} -
- {:else} -
- {/if} - {/each} -
- {/if} - {/snippet} -
+{#if debouncedSearch.current === "" || !debouncedSearch.current} + +{:else} + {#key debouncedSearch.current} + searchInventorySection({ uuid, profileId, searchParam: debouncedSearch.current! })}> + {#snippet children(items: ModelsStrippedItem[])} + {#if !items || items.length === 0} + + {:else if debouncedSearch.current !== ""} +
+ {#each items as item, index (index)} + {#if item} +
+ {@render itemSnippet(item)} +
+ {:else} +
+ {/if} + {/each} +
+ {/if} + {/snippet} +
+ {/key} {/if} diff --git a/src/lib/components/item/Item.svelte b/src/lib/components/item/Item.svelte index 25cab9a0f..ea278c129 100644 --- a/src/lib/components/item/Item.svelte +++ b/src/lib/components/item/Item.svelte @@ -6,6 +6,7 @@ import { cn } from "$lib/shared/utils"; import ImageOff from "@lucide/svelte/icons/image-off"; import { Avatar, Tooltip, type AvatarImageLoadingStatus } from "bits-ui"; + import { IsInViewport } from "runed"; type Props = { @@ -42,19 +43,19 @@ class={cn("overflow-clip nice-colors-dark", isInventory ? "p-0" : `relative p-2 ${bgColor}`, { shine: shine && !isInventory }, { "rounded-lg": !isInventory }, "standard:transition-all standard:duration-150 standard:ease-out standard:hover:scale-110 standard:active:scale-110")} bind:ref={targetNode} onclick={() => { - if (skyblockItem.containsItems) { + if (skyblockItem.containsItems && !skyblockItem.displayInline) { internalState.itemContentSpecial = skyblockItem; return; } internalState.itemContent = skyblockItem; - internalState.showItem = true; + internalState.showItem = !skyblockItem.displayInline; }} tether={itemTooltipTether} payload={{ skyblockItem, inViewport }}> {#snippet child({ props })}
{#if hasBeenInViewport} - + {#if loadingStatus === "loading"} {@render loadingState()} @@ -76,11 +77,11 @@ {#if showNumbers} -
+
{formatNumber(skyblockItem.Count ?? 0)}
{/if} {#snippet loadingState()} -
+
{/snippet} diff --git a/src/lib/components/misc/Chip.svelte b/src/lib/components/misc/Chip.svelte index fc8b96a90..057d86c58 100644 --- a/src/lib/components/misc/Chip.svelte +++ b/src/lib/components/misc/Chip.svelte @@ -1,8 +1,9 @@ (open = !open)} onclick={() => (internalState.content = tooltip)} tether={genericTooltipTether} payload={{ - class: "z-50 max-w-md rounded-lg bg-background-grey p-4 break-normal wrap-break-word whitespace-normal!", + class: "z-50 performance:bg-popover space-y-2 max-w-md rounded-xl bg-transparent glass border glass-bg-popover p-4 break-normal text-sm wrap-break-word whitespace-normal!", sideOffset: 6, side: "top", align: "center", @@ -70,8 +71,8 @@
{#if image} {#if hasBeenInViewport} - - + + diff --git a/src/lib/components/misc/CommandPalette.svelte b/src/lib/components/misc/CommandPalette.svelte index 9122fdee6..1d11766e7 100644 --- a/src/lib/components/misc/CommandPalette.svelte +++ b/src/lib/components/misc/CommandPalette.svelte @@ -103,7 +103,7 @@ { e.preventDefault(); commandInput?.focus(); diff --git a/src/lib/components/misc/CommandSettingsGroup.svelte b/src/lib/components/misc/CommandSettingsGroup.svelte index 09df26af9..ffe705755 100644 --- a/src/lib/components/misc/CommandSettingsGroup.svelte +++ b/src/lib/components/misc/CommandSettingsGroup.svelte @@ -104,8 +104,8 @@ }}>
{#if item.type === "toggle" && item.iconProps} - {@const Icon = item.icon} - {@const props = Object.fromEntries(Object.entries(item.iconProps).map(([key, value]) => [key, typeof value === "function" ? (value as () => unknown)() : value]))} + {const Icon = item.icon} + {const props = Object.fromEntries(Object.entries(item.iconProps).map(([key, value]) => [key, typeof value === "function" ? (value as () => unknown)() : value]))} {:else} diff --git a/src/lib/components/misc/ContributorCard.svelte b/src/lib/components/misc/ContributorCard.svelte index 1b2f33d02..f1d963703 100644 --- a/src/lib/components/misc/ContributorCard.svelte +++ b/src/lib/components/misc/ContributorCard.svelte @@ -52,7 +52,7 @@
{#if user.role} - {@const Icon = iconMapper[user.role]} + {const Icon = iconMapper[user.role]} {#snippet viewportChildren()} -
-
-
+
+
+
{#each filteredSectionOrderPreferences as section, index (index)} - handleSectionClick(section.name)}> + {/each}
{/snippet} - + @@ -157,18 +159,18 @@
{#if previousSection} - handleSectionClick(previousSection.name ?? filteredSectionOrderPreferences[0].name)}> - + {:else}
{/if} {#if nextSection} - handleSectionClick(nextSection.name ?? filteredSectionOrderPreferences[filteredSectionOrderPreferences.length - 1].name)}> + {/if}
diff --git a/src/lib/components/misc/ScrollItems.svelte b/src/lib/components/misc/ScrollItems.svelte index a821d2de6..4077d2123 100644 --- a/src/lib/components/misc/ScrollItems.svelte +++ b/src/lib/components/misc/ScrollItems.svelte @@ -9,7 +9,7 @@ let { children }: Props = $props(); - + {#snippet viewportChildren()}
{@render children?.()} diff --git a/src/lib/components/misc/SearchTabs.svelte b/src/lib/components/misc/SearchTabs.svelte new file mode 100644 index 000000000..e5cd7dd43 --- /dev/null +++ b/src/lib/components/misc/SearchTabs.svelte @@ -0,0 +1,130 @@ + + +
+ { + event.stopPropagation(); + }} /> + {#if totalResults === 0} + + {:else} + currentValue, (value) => (selected = value)} class={cn("mt-4", isVertical && "gap-4")}> + {#if isVertical} + + +
+ {@render tabsListItems()} +
+
+
+
+ {:else} + + + {@render tabsListItems()} + + + {/if} + + {#each filteredTabs as tab (tab.value)} + + {@render tabHeader?.(tab.value)} + {#if tab.items.length === 0} +

{noResultsLabel}

+ {:else} + + {#each tab.items as entry, index (itemKey(entry, index))} + {@render item(entry)} + {/each} + + {/if} +
+ {/each} +
+ {/if} +
+ +{#snippet tabsListItems()} + {#each filteredTabs as tab (tab.value)} + {const isActive = $derived(currentValue === tab.value)} + + {#if isActive} +
+ {/if} + {tab.label.replaceAll("_", " ")} +
+ {/each} +{/snippet} diff --git a/src/lib/components/misc/index.ts b/src/lib/components/misc/index.ts index 665863923..34a0fa561 100644 --- a/src/lib/components/misc/index.ts +++ b/src/lib/components/misc/index.ts @@ -9,6 +9,7 @@ export { default as JsonLd } from "./JsonLd.svelte"; export { default as Navbar } from "./Navbar.svelte"; export { default as PerformanceMode } from "./PerformanceMode.svelte"; export { default as ScrollItems } from "./ScrollItems.svelte"; +export { default as SearchTabs } from "./SearchTabs.svelte"; export { default as SEO } from "./SEO.svelte"; export { default as Wardrobe } from "./Wardrobe.svelte"; // Skin3D excluded — dynamically imported for code-splitting diff --git a/src/lib/components/notices/APINotice.svelte b/src/lib/components/notices/APINotice.svelte index 206022c5c..01f2b967c 100644 --- a/src/lib/components/notices/APINotice.svelte +++ b/src/lib/components/notices/APINotice.svelte @@ -14,7 +14,7 @@ const isHover = getHoverContext(); -
+
Notice

diff --git a/src/lib/components/notices/BetaNotice.svelte b/src/lib/components/notices/BetaNotice.svelte index f11f6a9f8..ee09e6075 100644 --- a/src/lib/components/notices/BetaNotice.svelte +++ b/src/lib/components/notices/BetaNotice.svelte @@ -37,7 +37,7 @@ {/if} {/snippet} - + {#snippet child({ props, open })} {#if open}

diff --git a/src/lib/components/sections/Section.svelte b/src/lib/components/sections/Section.svelte index d7814242d..57060537d 100644 --- a/src/lib/components/sections/Section.svelte +++ b/src/lib/components/sections/Section.svelte @@ -1,7 +1,8 @@ -
-
- {#if subtitle} - {@render subtitle()} - {:else if subtitleText} - {subtitleText} - {:else} - {id.replaceAll("_", " ")} - {/if} -
+
+ {#if subtitle || subtitleText || showSectionTitle} +
+ {#if subtitle} + {@render subtitle()} + {:else if subtitleText} + {subtitleText} + {:else if showSectionTitle} + {id.replaceAll("_", " ")} + {/if} +
+ {/if} + {#if showSectionTitle} + + {/if} + {@render children?.()}
diff --git a/src/lib/components/sections/SectionBoundary.svelte b/src/lib/components/sections/SectionBoundary.svelte index 2d69bd7b3..92d934626 100644 --- a/src/lib/components/sections/SectionBoundary.svelte +++ b/src/lib/components/sections/SectionBoundary.svelte @@ -1,6 +1,6 @@ -

+

{#if children} {@render children()} {:else if text} diff --git a/src/lib/components/sections/SectionTitle.svelte b/src/lib/components/sections/SectionTitle.svelte index 382a0b3d7..84b05f983 100644 --- a/src/lib/components/sections/SectionTitle.svelte +++ b/src/lib/components/sections/SectionTitle.svelte @@ -5,7 +5,7 @@ let { text, children, class: className }: { text?: string; children?: Snippet; class?: string } = $props(); -

+

{#if children} {@render children()} {:else if text} diff --git a/src/lib/components/stats/AdditionStat.svelte b/src/lib/components/stats/AdditionStat.svelte index a81189d5b..f6035d1b4 100644 --- a/src/lib/components/stats/AdditionStat.svelte +++ b/src/lib/components/stats/AdditionStat.svelte @@ -1,8 +1,10 @@ - (internalState.content = children)} - tether={genericTooltipTether} - payload={{ - class: "z-50 rounded-lg bg-background-grey p-4", - sideOffset: 0, - side: "top", - align: "center", - customAnchor: asteriskRef, - showTooltip: asterisk, - children - }}> - {#snippet child({ props })} - - {/snippet} - + + + {#if asterisk} + + + + {/if} +

+ +{/snippet} diff --git a/src/lib/components/stats/Bonus.svelte b/src/lib/components/stats/Bonus.svelte index 933b22080..2bc0e574f 100644 --- a/src/lib/components/stats/Bonus.svelte +++ b/src/lib/components/stats/Bonus.svelte @@ -16,10 +16,10 @@ {#if statsData.length > 0} -

+

{title} {#each statsData as [key, value], index (index)} - {@const displayKey = (STAT_ALIASES[key] !== undefined ? STAT_ALIASES[key] : key).toLowerCase()} + {const displayKey = (STAT_ALIASES[key] !== undefined ? STAT_ALIASES[key] : key).toLowerCase()} {#if STATS_DATA[displayKey]} {format(value)}{STATS_DATA[displayKey].suffix} diff --git a/src/lib/components/stats/CardBuilder.svelte b/src/lib/components/stats/CardBuilder.svelte index 51febc2af..a86ede782 100644 --- a/src/lib/components/stats/CardBuilder.svelte +++ b/src/lib/components/stats/CardBuilder.svelte @@ -4,7 +4,15 @@ import { getHoverContext } from "$ctx"; import { cardPresets, type CardPreset } from "$lib/components/cards"; import { getDefaults, settingsToParams } from "$lib/components/cards/default/schema"; - import { cn, flyAndScale } from "$lib/shared/utils"; + import * as Dialog from "$lib/components/ui/dialog"; + import { cn } from "$lib/shared/utils"; + import * as Avatar from "$ui/avatar"; + import { Button } from "$ui/button"; + import * as Collapsible from "$ui/collapsible"; + import * as Drawer from "$ui/drawer"; + import * as Item from "$ui/item"; + import { Label } from "$ui/label"; + import { Switch } from "$ui/switch"; import ChevronDown from "@lucide/svelte/icons/chevron-down"; import ClipboardIcon from "@lucide/svelte/icons/clipboard"; import CodeXmlIcon from "@lucide/svelte/icons/code-xml"; @@ -12,12 +20,9 @@ import IdCardIcon from "@lucide/svelte/icons/id-card"; import LoaderCircleIcon from "@lucide/svelte/icons/loader-circle"; import RotateCcwIcon from "@lucide/svelte/icons/rotate-ccw"; - import { Avatar, Button, Collapsible, Dialog, Label, Switch, type AvatarImageLoadingStatus } from "bits-ui"; + import type { AvatarImageLoadingStatus } from "bits-ui"; import { Debounced } from "runed"; import { toast } from "svelte-sonner"; - import { cubicOut } from "svelte/easing"; - import { fade } from "svelte/transition"; - import { Drawer } from "vaul-svelte"; type TriggerProps = Record; const isHover = getHoverContext(); @@ -88,18 +93,21 @@ {#snippet triggerButton(props: TriggerProps)} - + {/snippet} {#snippet presetCards()} -

- Preset -
+ + + + + + {#each cardPresets as preset (preset.id)} - selectPreset(preset.id)} class={cn("flex flex-col gap-1.5 rounded-lg border-2 p-2 transition-all", selectedPreset.id === preset.id ? "border-icon bg-icon/10" : "border-text/10 bg-text/5 hover:border-text/20 hover:bg-text/10")}> + {/each} -
-
+ + {/snippet} {#snippet optionGroups()} {#each selectedPreset.schema as group (group.groupName)} - + - -

{group.groupName}

+ +
{#each group.options as option (option.key)} {#if option.type === "checkbox"} - - {option.label} - updateSetting(option.key, checked)}> - - - + {:else if option.type === "color"} - - {option.label} - updateSetting(option.key, e.currentTarget.value)} class="size-8 cursor-pointer rounded-md border border-text/10 bg-transparent p-0.5" /> - + {:else if option.type === "text"} - - {option.label} - updateSetting(option.key, e.currentTarget.value)} class="w-full max-w-40 rounded-md border border-text/10 bg-text/5 px-2 py-1 text-sm text-text focus:border-icon focus:outline-none" /> - + {:else if option.type === "number"} - - {option.label} - updateSetting(option.key, Number(e.currentTarget.value))} class="w-full max-w-24 rounded-md border border-text/10 bg-text/5 px-2 py-1 text-sm text-text focus:border-icon focus:outline-none" /> - + {/if} {/each} @@ -177,39 +207,39 @@ {/snippet} {#snippet resetButton()} - + {/snippet} {#snippet imagePreview()} -
+
-

Preview

+
- + + +
- + {#if isImagePending}
{/if} - - Card Preview + + Card Preview
{/snippet} @@ -222,26 +252,17 @@ {/snippet} - - {#snippet child({ props, open })} - {#if open} -
- {/if} - {/snippet} -
- - {#snippet child({ props, open })} - {#if open} -
-
- {@render presetCards()} - {@render optionGroups()} - {@render resetButton()} - {@render imagePreview()} -
-
- {/if} - {/snippet} + + + Generate your SkyCrypt card + Choose from various presets and options to create the perfect card for sharing on social media, forums, or with friends! + +
+ {@render presetCards()} + {@render optionGroups()} + {@render imagePreview()} + {@render resetButton()} +
@@ -252,18 +273,13 @@ {@render triggerButton(props)} {/snippet} - - - -
-
- {@render presetCards()} - {@render optionGroups()} - {@render resetButton()} - {@render imagePreview()} -
-
-
-
+ +
+ {@render presetCards()} + {@render optionGroups()} + {@render imagePreview()} + {@render resetButton()} +
+
{/if} diff --git a/src/lib/components/stats/DungeonCataCard.svelte b/src/lib/components/stats/DungeonCataCard.svelte index e81fceb3e..b5ace396f 100644 --- a/src/lib/components/stats/DungeonCataCard.svelte +++ b/src/lib/components/stats/DungeonCataCard.svelte @@ -1,13 +1,17 @@ {#if catacombs} - + {#each catacombs as catacomb, index (index)} {#if catacomb.stats} {#if catacomb.stats.tier_completions != null && catacomb.stats.tier_completions > 0} -
-
- - - +
+
+ + + {catacomb.name}
+ - - - - Floor Stats - - - {#each Object.entries(catacomb.stats) as [key, value], index (index)} - {#if typeof value === "object"} - - {:else if key.includes("time") && key !== "times_played"} - - {:else} - - {/if} - {/each} - - - - {#if catacomb.best_run} - - - - Best run - - - {#each Object.entries(catacomb.best_run) as [key, value], index (index)} - {#if typeof value === "number"} - {#if key === "timestamp"} - - {formatDate(value, "dd MMMM yyyy 'at' HH:mm", { in: tz(Intl.DateTimeFormat().resolvedOptions().timeZone) })} - - {:else if key.includes("time")} - - {:else} - - {/if} +
+ + Floor Stats + + {#each Object.entries(catacomb.stats) as [key, value], index (index)} + {#if typeof value === "object"} + + {:else if key.includes("time") && key !== "times_played"} + {:else} - + {/if} {/each} - {:else} -
This player has not completed this floor.
- {/if} + + {#if catacomb.best_run} + + Best Run + + + {#each Object.entries(catacomb.best_run) as [key, value], index (index)} + {#if typeof value === "number"} + {#if key === "timestamp"} + + {formatDate(value, "dd MMMM yyyy 'at' HH:mm", { in: tz(Intl.DateTimeFormat().resolvedOptions().timeZone) })} + + {:else if key.includes("time")} + + {:else} + + {/if} + {:else} + + {/if} + {/each} + + + {:else} + + {/if} +
{/if} {/if} {/each} - + {:else} - This player has not played any {master ? "Master Catacombs" : "Catacombs"}. + {/if} diff --git a/src/lib/components/stats/GardenPlotGrid.svelte b/src/lib/components/stats/GardenPlotGrid.svelte index ec453e1c2..dccaf24b0 100644 --- a/src/lib/components/stats/GardenPlotGrid.svelte +++ b/src/lib/components/stats/GardenPlotGrid.svelte @@ -4,9 +4,11 @@ import { type ModelsPlotLayout } from "$lib/shared/api/orval-generated"; import { renderLore } from "$lib/shared/helper"; import { animateObfuscatedText } from "$lib/shared/mc-text/obfuscated"; - import { flyAndScale } from "$lib/shared/utils"; + import ScrollAreaItems from "$src/lib/components/ScrollAreaItems.svelte"; + import SectionSubtitle from "$src/lib/components/sections/SectionSubtitle.svelte"; + import * as Avatar from "$ui/avatar"; + import * as Tooltip from "$ui/tooltip"; import Image from "@lucide/svelte/icons/image"; - import { Avatar, Tooltip } from "bits-ui"; let { plot }: { plot: ModelsPlotLayout | undefined } = $props(); @@ -16,8 +18,8 @@ const allMaxed = $derived(plot?.unlocked === plot?.total); -
-

Plots

+
+ Plots {#if allMaxed} Max! {:else} @@ -34,41 +36,34 @@ {/if}
{#if plot} -
-
- {#each plot.layout as plotItem, index (index)} - {#snippet tooltipContent()} - {#if plotItem.display_name} -

{@html renderLore(plotItem.display_name)}

- {/if} - {/snippet} - - (internalState.content = tooltipContent)}> - - - - - - - - + +
+
+ {#each plot.layout as plotItem, index (index)} + {#snippet tooltipContent()} + {#if plotItem.display_name} +

{@html renderLore(plotItem.display_name)}

+ {/if} + {/snippet} + + + (internalState.content = tooltipContent)}> + + + + + + + + {#if isHover.current} - - {#snippet child({ wrapperProps, props, open })} - {#if open} -
-
- - {@render tooltipContent()} -
-
- {/if} - {/snippet} + + {@render tooltipContent()} {/if} - -
- {/each} + + {/each} +
-
+ {/if} diff --git a/src/lib/components/stats/NetworthCard.svelte b/src/lib/components/stats/NetworthCard.svelte index 9874a6a6d..2dfdd294a 100644 --- a/src/lib/components/stats/NetworthCard.svelte +++ b/src/lib/components/stats/NetworthCard.svelte @@ -2,6 +2,8 @@ import { AdditionStat } from "$lib/components/stats"; import { type SkycryptSrcModelsNetworthResult } from "$lib/shared/api/orval-generated"; import { formatNumber } from "$lib/shared/helper"; + import { Label } from "$ui/label"; + import { Separator } from "$ui/separator"; import { format as numberFormat } from "numerable"; const defaultPattern: string = "0,0"; @@ -15,31 +17,34 @@ -
+
-

{title}

-

{title} calculations by SkyHelper.

+ +

{title} calculations by SkyHelper.

-
-
    - {#each Object.entries(networth.types ?? {}) as [key, value], index (index)} -
  • - {key.replace(/_/g, " ")}: - - {formatNumber(value.total ?? 0)} - -
  • - {/each} -
-
-

+ +

    + {#each Object.entries(networth.types ?? {}) as [key, value], index (index)} +
  • + {key.replace(/_/g, " ")}: + + {formatNumber(value.total ?? 0)} + +
  • + {/each} +
+ + + +

Unsoulbound {title}: - + {formatNumber(networth.unsoulboundNetworth ?? 0)} -
+

+

Total {title}: - + {numberFormat(networth.networth, defaultPattern)} ({formatNumber(networth.networth ?? 0)})

diff --git a/src/lib/components/stats/Skillbar.svelte b/src/lib/components/stats/Skillbar.svelte index 0b88ba1b7..06fc27fac 100644 --- a/src/lib/components/stats/Skillbar.svelte +++ b/src/lib/components/stats/Skillbar.svelte @@ -2,9 +2,10 @@ import { getPreferences } from "$ctx"; import type { ModelsSkill } from "$lib/shared/api/orval-generated"; import { calculatePercentage, formatNumber } from "$lib/shared/helper"; - import { cn } from "$lib/shared/utils"; + import * as Avatar from "$ui/avatar"; + import { Progress } from "$ui/progress"; + import { cn } from "$utils"; import BarChartHorizontal from "@lucide/svelte/icons/bar-chart-horizontal"; - import { Avatar, Progress } from "bits-ui"; import { format } from "numerable"; import { cubicInOut } from "svelte/easing"; import { Tween } from "svelte/motion"; @@ -31,40 +32,41 @@
(isHovered = true)} onpointerleave={() => (isHovered = false)} role="none"> -
- - - - +
+ + + +
-
- {skill} - - {skillData.level} - -
- +
+
+ {skill} + {#if apiEnabled} + + {skillData.level} + + {/if} +
{#if apiEnabled} -
-
- {#if isHovered && !isMaxed} - {format(skillData.xpCurrent, "0,0")} / {format(skillData.xpForNext)} - {:else if !isMaxed} - {formatNumber(skillData.xpCurrent ?? 0)} / {formatNumber(skillData.xpForNext ?? 0)} - {/if} +
+ {#if isHovered && !isMaxed} + {format(skillData.xpCurrent, "0,0")} / {format(skillData.xpForNext)} + {:else if !isMaxed} + {formatNumber(skillData.xpCurrent ?? 0)} / {formatNumber(skillData.xpForNext ?? 0)} + {/if} - {#if isHovered && isMaxed} - {format(skillData.xpCurrent, "0,0")} - {:else if isMaxed} - {formatNumber(skillData.xpCurrent ?? 0)} - {/if} - XP -
+ {#if isHovered && isMaxed} + {format(skillData.xpCurrent, "0,0")} + {:else if isMaxed} + {formatNumber(skillData.xpCurrent ?? 0)} + {/if} + XP
-
{/if} - +
+ +
diff --git a/src/lib/components/stats/Stat.svelte b/src/lib/components/stats/Stat.svelte index 29e2a199d..8b7456bc8 100644 --- a/src/lib/components/stats/Stat.svelte +++ b/src/lib/components/stats/Stat.svelte @@ -3,7 +3,10 @@ import type { ModelsStatsInfo } from "$lib/shared/api/orval-generated"; import { STATS_DATA } from "$lib/shared/constants/stats"; import { cn } from "$lib/shared/utils"; - import { Tooltip } from "bits-ui"; + import * as Item from "$ui/item"; + import { Label } from "$ui/label"; + import { Separator } from "$ui/separator"; + import * as Tooltip from "$ui/tooltip"; import { format } from "numerable"; type Props = { @@ -18,45 +21,65 @@ let iconRef = $state(null); const internalState = getInternalState(); + const statIconClass = "grid size-4 shrink-0 place-items-center font-unifontex text-base leading-none"; (open = !open)} onclick={() => (internalState.content = tooltipContent)} tether={genericTooltipTether} payload={{ - class: "z-50 space-y-4 rounded-lg bg-background-grey p-4 text-sm", + class: "z-50 [&>div]:leading-7 performance:bg-popover space-y-2 rounded-lg [&>span]:invisible bg-transparent glass border glass-bg-popover p-4 text-sm", side: "top", + sideOffset: 4, align: "center", customAnchor: iconRef, children: tooltipContent }}> -
{STATS_DATA[stat].symbol}
- {stat.replace(/_/g, " ")} - - {format(statData.total)}{#if STATS_DATA[stat]?.percent}%{/if} - + {#snippet child({ props })} + + + {STATS_DATA[stat].symbol} + + + + {stat.replace(/_/g, " ")} + + {format(statData.total)}{#if STATS_DATA[stat]?.percent}%{/if} + + + + + {/snippet}
{#snippet tooltipContent()} -
-

Base {stat.replaceAll("_", " ")}: {format(statData.base)}

-

Base value every player has at the beginning of their SkyBlock adventure!

+
+ {STATS_DATA[stat].symbol} + {stat.replace(/_/g, " ")}
+ +

Base value every player has at the beginning of their SkyBlock adventure!

+ {#if statData.total} -
-

Bonus {stat.replaceAll("_", " ")}: {format(statData.total)}

-

Bonus value obtained from:

- -
- {#each Object.entries(statData) as [key, value], index (index)} - {#if !["total", "base"].includes(key)} -
- {key.replaceAll("_", " ")} +{format(value)}
- {/if} - {/each} -
-
+ + + +

Bonus value obtained from:

+ +
    + {#each Object.entries(statData) as [key, value], index (index)} + {#if !["total", "base"].includes(key)} +
  • + + {key.replaceAll("_", " ")} + +{format(value)} + +
  • + {/if} + {/each} +
{/if} {/snippet} diff --git a/src/lib/components/theme-editor/MCColorSection.svelte b/src/lib/components/theme-editor/MCColorSection.svelte index 917eecef3..c08f7b2fe 100644 --- a/src/lib/components/theme-editor/MCColorSection.svelte +++ b/src/lib/components/theme-editor/MCColorSection.svelte @@ -83,7 +83,7 @@
{#each mcCodes as code, index (index)} - {@const effectiveColor = getEffectiveColor(code)} + {const effectiveColor = getEffectiveColor(code)}
§{code} diff --git a/src/lib/components/tooltip/TooltipSetup.svelte b/src/lib/components/tooltip/TooltipSetup.svelte index 2293a2ba4..6b3e89931 100644 --- a/src/lib/components/tooltip/TooltipSetup.svelte +++ b/src/lib/components/tooltip/TooltipSetup.svelte @@ -24,9 +24,6 @@ {:else if payload?.tooltipContent} {payload.tooltipContent} {/if} - {#if payload?.showArrow !== false} - - {/if} {/key}
@@ -43,7 +40,7 @@ {#snippet children({ payload })} {#if payload?.inViewport?.current} - + {#snippet child({ wrapperProps, props, open })} {#if open}
diff --git a/src/lib/layouts/stats/AdditionalStats.svelte b/src/lib/layouts/stats/AdditionalStats.svelte index 0422647e4..74916e1d3 100644 --- a/src/lib/layouts/stats/AdditionalStats.svelte +++ b/src/lib/layouts/stats/AdditionalStats.svelte @@ -3,19 +3,20 @@ import { AdditionStat, NetworthCard } from "$lib/components/stats"; import { getNetworth } from "$lib/shared/api/skycrypt-api.remote"; import { calculatePercentage, formatNumber } from "$lib/shared/helper"; - import { flyAndScale } from "$lib/shared/utils"; + import { Button } from "$ui/button"; + import { Label } from "$ui/label"; + import * as Popover from "$ui/popover"; + import { Separator } from "$ui/separator"; + import { Spinner } from "$ui/spinner"; import { tz } from "@date-fns/tz"; import CircleX from "@lucide/svelte/icons/circle-x"; - import LoaderCircle from "@lucide/svelte/icons/loader-circle"; import { isHttpError } from "@sveltejs/kit"; - import { Button, Popover } from "bits-ui"; import { format as dateFormat, formatDistanceToNowStrict } from "date-fns"; import { format as numberFormat } from "numerable"; const profile = $derived(getProfileContext().current); const profileUUID = $derived(profile?.uuid); const profileId = $derived(profile?.profile_id); - const networth = $derived(profileUUID != null && profileId != null ? await getNetworth({ uuid: profileUUID, profileId }) : null); const defaultPatternDecimal: string = "0,0.##"; const defaultPattern: string = "0,0"; @@ -38,20 +39,20 @@ {/if} {#if profile.bank != null && profile.personalBank != null} -
-

+
+

+ {#if profile.personalBank} -

+

+ {/if}
@@ -59,36 +60,34 @@ {#if profile.skills?.averageSkillLevel}
-
-

- Total Skill XP: - - {numberFormat(profile.skills.totalSkillXp, defaultPattern)} - -

-

Total XP gained in all skills except Social and Runecrafting.

-
- {#if profile.skills.averageSkillLevelWithProgress != null} -
-

- Average Level: - - {profile.skills.averageSkillLevelWithProgress.toFixed(2)} - -

-

Average skill level over all skills except Social and Runecrafting, includes progress to next level.

-
- {/if} -
-

- Average Level without progress: - - {numberFormat(profile.skills.averageSkillLevel, defaultPatternDecimal)} - -

-

Average skill level without including partial level progress.

-
+ +

Total XP gained in all skills except Social and Runecrafting.

+ {#if profile.skills.averageSkillLevelWithProgress != null} + + + +

Average skill level over all skills except Social and Runecrafting, includes progress to next level.

+ {/if} + + + +

Average skill level without including partial level progress.

{/if} {#if profile.fairySouls} @@ -98,39 +97,32 @@ {/if} {/if} + {const networth = $derived(profileUUID != null && profileId != null ? await getNetworth({ uuid: profileUUID, profileId }) : null)} {#snippet pending()} -
+
Networth: - +
{/snippet} {#snippet failed(err, retry)} -
+
{ if (!isHover.current) return; networthOpen = true; }}> - Networth: + Networth: {#if isHttpError(err)} - - {#snippet child({ wrapperProps, props, open })} - {#if open} -
-
- {err.body.message} -
-
- {/if} - {/snippet} + + {err.body.message} {/if}
- Retry + +
{/snippet} {#if networth} diff --git a/src/lib/layouts/stats/Items.svelte b/src/lib/layouts/stats/Items.svelte index 1db8817e7..11627fb9f 100644 --- a/src/lib/layouts/stats/Items.svelte +++ b/src/lib/layouts/stats/Items.svelte @@ -6,23 +6,23 @@ type Props = { subtitle?: string; class?: string; + parentClass?: string; text?: Snippet; children?: Snippet; info?: Snippet; }; - let { subtitle, class: className, text, children, info }: Props = $props(); + let { subtitle, class: className, parentClass, text, children, info }: Props = $props(); -
+
{#if subtitle} {subtitle} {/if} {@render text?.()} -
+ {@render info?.()} +
{@render children?.()}
- - {@render info?.()}
diff --git a/src/lib/layouts/stats/Main.svelte b/src/lib/layouts/stats/Main.svelte index 2a8e0fd55..64eebee99 100644 --- a/src/lib/layouts/stats/Main.svelte +++ b/src/lib/layouts/stats/Main.svelte @@ -219,6 +219,7 @@
+
{#if getProfileContext().current}
@@ -245,7 +246,7 @@ {/if} {/snippet} - + {#snippet child({ props, open })} {#if open}
@@ -271,7 +272,7 @@ {/if} {/snippet} - + {#snippet child({ props, open })} {#if open}
diff --git a/src/lib/layouts/stats/PlayerProfile.svelte b/src/lib/layouts/stats/PlayerProfile.svelte index 92cb77815..42640c02c 100644 --- a/src/lib/layouts/stats/PlayerProfile.svelte +++ b/src/lib/layouts/stats/PlayerProfile.svelte @@ -2,20 +2,24 @@ import { resolve } from "$app/paths"; import { getFavorites, getHoverContext, getProfileContext } from "$ctx"; import { APINotice } from "$lib/components/notices"; - import { cn, flyAndScale } from "$lib/shared/utils"; + import { cn } from "$lib/shared/utils"; import CardBuilder from "$src/lib/components/stats/CardBuilder.svelte"; + import * as Avatar from "$ui/avatar"; + import { Button } from "$ui/button"; + import * as Item from "$ui/item"; + import * as Popover from "$ui/popover"; import Ban from "@lucide/svelte/icons/ban"; - import ChevronLeft from "@lucide/svelte/icons/chevron-left"; + import ChevronRight from "@lucide/svelte/icons/chevron-right"; import ExternalLink from "@lucide/svelte/icons/external-link"; + import Heart from "@lucide/svelte/icons/heart"; + import HeartMinus from "@lucide/svelte/icons/heart-minus"; + import HeartPlus from "@lucide/svelte/icons/heart-plus"; import Link from "@lucide/svelte/icons/link"; - import Star from "@lucide/svelte/icons/star"; import TriangleAlert from "@lucide/svelte/icons/triangle-alert"; - import { Avatar, Button, Popover, Tooltip } from "bits-ui"; import { toast } from "svelte-sonner"; let toastId: string | number = $state(0); let showMore = $state(false); - let favoriteTooltipOpen = $state(false); let noticeOpen = $state(false); let ignOpen = $state(false); let profileOpen = $state(false); @@ -39,6 +43,12 @@ HYPIXEL: "hypixel.avif" }; + const emojiMapper: Record = { + bingo: "🎲", + ironman: "♻️", + island: "🌴" + }; + function copyToClipboard(value: string) { navigator.clipboard.writeText(value); toast.dismiss(toastId); @@ -49,17 +59,7 @@
Stats for - { - if (profile == null) return; - if (profile.members?.length) return; - if (!isHover.current) return; - profileOpen = false; - ignOpen = true; - }}> + {#if profile != null && profile.rank?.rankColor}
@@ -74,53 +74,46 @@ {profile?.displayName} - - - {#snippet child({ wrapperProps, props, open })} - {#if open} -
-
- {#each profile?.members as member (member.uuid)} - {#if member.username !== profile?.username} - -
-
- - - - Steve - - - - {member.username} - -
- {#if member.removed} - - {/if} -
-
- {/if} - {/each} -
-
- {/if} - {/snippet} -
-
+ + {#each profile?.members?.toSorted() as member (member.uuid)} + {#if member.username !== profile?.username} + + {#snippet child({ props })} + + + + + + Steve + + + + + {member.username} + + {#if member.removed} + + + + {/if} + + {/snippet} + + {/if} + {/each} + on -
0} bind:this={noticeRef}> +
0} bind:this={noticeRef} data-disabled={(profile?.profiles?.length || 1) <= 1}> { if (profile == null) return; if (profile.profiles?.length) return; @@ -130,38 +123,40 @@ }} class="rounded-full px-2 py-1"> {profile?.profile_cute_name} - {@render profileIcon(profile?.game_mode ?? "")} + {#if profile?.game_mode} + {emojiMapper[profile.game_mode]} + {/if} - - - {#snippet child({ wrapperProps, props, open })} - {#if open} -
-
- {#each profile?.profiles ?? [] as otherProfile (otherProfile.profile_id)} - {#if otherProfile.profile_id !== profile?.profile_id} - -
- - {otherProfile.cute_name} - - {@render profileIcon(otherProfile.game_mode ?? "")} -
-
- {/if} - {/each} -
-
- {/if} - {/snippet} -
-
+ + + {#each profile?.profiles ?? [] as otherProfile (otherProfile.profile_id)} + {#if otherProfile.profile_id !== profile?.profile_id} + + {#snippet child({ props })} + + + + {otherProfile.cute_name} + + + + {#if otherProfile.game_mode} + + {emojiMapper[otherProfile.game_mode]} + + {/if} + + {/snippet} + + {/if} + {/each} +
{#if apiSettings.length} @@ -169,146 +164,96 @@ (noticeOpen = true)}> - - - {#snippet child({ wrapperProps, props, open })} - {#if open} -
-
- - -
-
- {/if} - {/snippet} -
-
+ + + + {/if}
-
- - { - if (profile == null) return; - if (!favorites.current.some((fav) => fav.uuid === profile.uuid)) { - favorites.current = [...favorites.current, { uuid: profile.uuid ?? "", ign: profile.username ?? "", displayName: profile.displayName ?? undefined }]; - toast.dismiss(toastId); - toastId = toast.success(`Added ${profile.username} to your favorites!`); - } else { - favorites.current = favorites.current.filter((fav) => fav.uuid !== profile.uuid); - toast.dismiss(toastId); - toastId = toast.success(`Removed ${profile.username} from your favorites!`); - } - }} - onpointerdown={() => (favoriteTooltipOpen = !favoriteTooltipOpen)}> - {#snippet child({ props })} - - {/snippet} - - - - {#snippet child({ wrapperProps, props, open })} - {#if open} -
-
- - {#if favorites.current.some((fav) => fav.uuid === profile?.uuid)} -

Remove from favorites

- {:else} -

Add to favorites

- {/if} -
-
- {/if} - {/snippet} -
-
-
+
+ - { copyToClipboard(window.location.href); }}> - + - + - + + + - (showMore = !showMore)}> - - {#if showMore} - { copyToClipboard(profile?.uuid ?? ""); }}> Copy UUID - + - { copyToClipboard(profile?.profile_id ?? ""); }}> Copy Profile UUID - + {#if profile?.social} {#each Object.entries(profile.social) as [key, value], index (index)} - {#if key === "DISCORD"} - copyToClipboard(value)}> - - - - {profile.username?.slice(0, 2)} - - + {/each} {/if} {/if}
- -{#snippet profileIcon(gameMode: string)} - {#if gameMode === "bingo"} - 🎲 - {/if} - {#if gameMode === "ironman"} - ♻️ - {/if} - {#if gameMode === "island"} - 🌴 - {/if} -{/snippet} diff --git a/src/lib/layouts/stats/Stats.svelte b/src/lib/layouts/stats/Stats.svelte index 735fdcb18..81ef648a2 100644 --- a/src/lib/layouts/stats/Stats.svelte +++ b/src/lib/layouts/stats/Stats.svelte @@ -3,8 +3,9 @@ import { Notice } from "$lib/components/notices"; import { Stat } from "$lib/components/stats"; import { getAdditionalStats } from "$lib/shared/api/skycrypt-api.remote"; - import LoaderCircle from "@lucide/svelte/icons/loader-circle"; - import { Collapsible } from "bits-ui"; + import { buttonVariants } from "$ui/button"; + import * as Collapsible from "$ui/collapsible"; + import { Spinner } from "$ui/spinner"; import { cubicOut } from "svelte/easing"; import { slide } from "svelte/transition"; @@ -37,9 +38,9 @@ {/snippet} {/key} - + {#if statsQuery?.loading} - + {:else} {openState ? "Hide Stats" : "Show Stats"} {/if} diff --git a/src/lib/sections/Sections.svelte b/src/lib/sections/Sections.svelte index 0e9242c7a..5f310e39a 100644 --- a/src/lib/sections/Sections.svelte +++ b/src/lib/sections/Sections.svelte @@ -3,7 +3,7 @@ import { Notice } from "$lib/components/notices"; import type { SectionName } from "$lib/sections/types"; import { titleCase } from "$lib/shared/helper"; - import LoaderCircle from "@lucide/svelte/icons/loader-circle"; + import { Spinner } from "$ui/spinner"; import { Tabs } from "bits-ui"; const preferences = getPreferences(); @@ -35,43 +35,39 @@ {#key internalState.tabValue} {#if internalState.tabValue in COMPONENTS} - + {#if shouldWaitForCombined && !combinedCtx.current} -
-
- - Loading {titleCase(internalState.tabValue)}... -
-
+ {@render loadingState()} + Not boundary {:else} - {#await COMPONENTS[internalState.tabValue]()} -
-
- - Loading {titleCase(internalState.tabValue)}... -
-
- {:then { default: Component }} - - {#snippet pending()} - - {/snippet} - {#snippet failed(err, reset)} - - {/snippet} - - - {:catch} - -

This section may not be available or there was an error loading it.

-
- {/await} + + {const { default: Component } = await COMPONENTS[internalState.tabValue]()} + {#snippet pending()} + {@render loadingState()} + {/snippet} + {#snippet failed(err, reset)} + +

This section may not be available or there was an error loading it.

+
+ {/snippet} + + +
{/if}
{:else} -

This section does not exist or is not implemented.

+

This section does not exist or is not implemented.

{/if} {/key} + +{#snippet loadingState()} +
+
+ + Loading {titleCase(internalState.tabValue)} +
+
+{/snippet} diff --git a/src/lib/sections/stats/Accessories.svelte b/src/lib/sections/stats/Accessories.svelte index a079538dd..4d811c07b 100644 --- a/src/lib/sections/stats/Accessories.svelte +++ b/src/lib/sections/stats/Accessories.svelte @@ -1,227 +1,205 @@
{#if accessories} {#if accessories.magicalPower?.total} - - {#snippet text()} -
- {#if accessories.unique != null && accessories.total != null} - - {/if} - {#if accessories.recombobulated != null && accessories.totalRecombobulated != null} - - {/if} - {#if accessories.selectedPower} - - {/if} - {#if accessories.magicalPower} - -
+
+
+ {#if accessories.unique != null && accessories.total != null} + + {/if} + {#if accessories.recombobulated != null && accessories.totalRecombobulated != null} + + {/if} + {#if accessories.selectedPower} + + {/if} + {#if accessories.magicalPower} + +
+
+ +

From your accessory bag.

+
+ {#if accessories.magicalPower.rarities} + {const rarities = accessories.magicalPower.rarities}
-

Accessories Breakdown

-

From your accessory bag.

-
- {#if accessories.magicalPower.rarities} -
-
    -
  • - 22 MP - × - {accessories.magicalPower.rarities.mythic.amount} Accs. - = - {accessories.magicalPower.rarities.mythic.magicalPower} MP -
  • -
  • - 16 MP - × - {accessories.magicalPower.rarities.legendary.amount} Accs. - = - {accessories.magicalPower.rarities.legendary.magicalPower} MP -
  • -
  • - 12 MP - × - {accessories.magicalPower.rarities.epic.amount} Accs. - = - {accessories.magicalPower.rarities.epic.magicalPower} MP -
  • -
  • - 8 MP - × - {accessories.magicalPower.rarities.rare.amount} Accs. - = - {accessories.magicalPower.rarities.rare.magicalPower} MP -
  • -
  • - 5 MP - × - {accessories.magicalPower.rarities.uncommon.amount} Accs. - = - {accessories.magicalPower.rarities.uncommon.magicalPower} MP -
  • -
  • - 3 MP - × - {accessories.magicalPower.rarities.common.amount} Accs. - = - {accessories.magicalPower.rarities.common.magicalPower} MP -
  • +
      + {#each MP_PER_RARITY as { rarity, mp } (rarity)}
    • - 3 MP + {mp} MP × - {accessories.magicalPower.rarities.special.amount} Accs. + {rarities[rarity]?.amount ?? 0} {rarity.replaceAll("_", " ")}. = - {accessories.magicalPower.rarities.special.magicalPower} MP + {rarities[rarity]?.magicalPower ?? 0} MP
    • -
    • - 5 MP - × - {accessories.magicalPower.rarities.very_special.amount} Accs. - = - {accessories.magicalPower.rarities.very_special.magicalPower} MP -
    • -
    -
- {/if} + {/each} + +
+ {/if} -
-
    - {#if accessories.magicalPower.abiphone != null && accessories.magicalPower.abiphone > 0} -
  • - Abicase: - = - +{accessories.magicalPower.abiphone} MP -
  • - {/if} - {#if accessories.magicalPower.riftPrism != null && accessories.magicalPower.riftPrism > 0} +
    +
      + {#if accessories.magicalPower.abiphone != null && accessories.magicalPower.abiphone > 0} +
    • + Abicase: + = + +{accessories.magicalPower.abiphone} MP +
    • + {/if} + {#if accessories.magicalPower.riftPrism != null && accessories.magicalPower.riftPrism > 0} +
    • + Rift Prism: + = + +{accessories.magicalPower.riftPrism} MP +
    • + {/if} + {#if accessories.magicalPower.hegemony} + {#if accessories.magicalPower.hegemony.amount != null && accessories.magicalPower.hegemony.amount > 0 && accessories.magicalPower.hegemony.rarity}
    • - Rift Prism: + Hegemony Artifact: = - +{accessories.magicalPower.riftPrism} MP + +{accessories.magicalPower.hegemony.amount.toString()} MP
    • {/if} - {#if accessories.magicalPower.hegemony} - {#if accessories.magicalPower.hegemony.amount != null && accessories.magicalPower.hegemony.amount > 0 && accessories.magicalPower.hegemony.rarity} -
    • - Hegemony Artifact: - = - +{accessories.magicalPower.hegemony.amount} MP -
    • - {/if} - {/if} -
    -
    -

    - Total: - - {accessories.magicalPower.total} Magical Power - -

    + {/if} +
-
+

+ Total: + + {accessories.magicalPower.total} Magical Power + +

+
+ + {/if} +
+ + {#if accessories.accessories && accessories.accessories.length > 0} +
+ Active Accessories + + {#if accessories.enrichments != null} +

+ Enrichments: + {#each Object.entries(accessories.enrichments) as [key, value], index (index)} + {#if key !== "missing" && STATS_DATA[key.toLowerCase()]} + + {value}× + {STATS_DATA[key.toLowerCase()].name} + + {#if Object.entries(accessories.enrichments).length - 1 !== index || (Object.entries(accessories.enrichments).length - 1 === index && accessories.enrichments.missing > 0)} + // + {/if} + {/if} + {/each} + {#if accessories.enrichments.missing > 0} + {accessories.enrichments.missing}× Missing Enrichment! + {/if} +

{/if} + + {#if accessories.stats} + + {/if} + + + + + {#each accessories.accessories as accessory, index (index)} + {#if accessory.isInactive === false} + + {/if} + {/each} +
- {/snippet} -
- {#if accessories.accessories && accessories.accessories.length > 0} -
- Active Accessories - + {#if accessories.accessories.length > 0 && accessories.accessories.find((accessory) => accessory.isInactive)} +
+ Inactive Accessories + {#each accessories.accessories as accessory, index (index)} - {#if accessory.isInactive === false} + {#if accessory.isInactive === true} {/if} {/each} - - {#if accessories.enrichments != null} -

- Enrichments: - {#each Object.entries(accessories.enrichments) as [key, value], index (index)} - {#if key !== "missing" && STATS_DATA[key.toLowerCase()]} - - {value}× - {STATS_DATA[key.toLowerCase()].name} - - {#if Object.entries(accessories.enrichments).length - 1 !== index || (Object.entries(accessories.enrichments).length - 1 === index && accessories.enrichments.missing > 0)} - // - {/if} - {/if} - {/each} - {#if accessories.enrichments.missing > 0} - {accessories.enrichments.missing}× Missing Enrichment! - {/if} -

- {/if} - {#if accessories.stats} - - {/if} - - {#if accessories.accessories.length > 0 && accessories.accessories.find((accessory) => accessory.isInactive)} - - {#each accessories.accessories as accessory, index (index)} - {#if accessory.isInactive === true} - - {/if} - {/each} - - {/if} +
- {:else} -

{profile?.username} doesn't have any accessories.

{/if} - {#if (accessories.missing && accessories.missing.length > 0) || (accessories.upgrades && accessories.upgrades.length > 0)} - - - - Missing Accessories - - - {#if accessories.missing && accessories.missing.length > 0} - + {:else} + + {/if} + + {#if (accessories.missing && accessories.missing.length > 0) || (accessories.upgrades && accessories.upgrades.length > 0)} + + Missing Accessories + + + {#if accessories.missing && accessories.missing.length > 0} +
+ {#each accessories.missing as accessory, index (index)}
{/each} - - {/if} - {#if accessories.upgrades && accessories.upgrades.length > 0} - +
+
+ {/if} + + {#if accessories.upgrades && accessories.upgrades.length > 0} +
+ Missing Accessory Upgrades + {#each accessories.upgrades as accessory, index (index)}
{/each} - - {/if} - - - {/if} -
-
+ +
+ {/if} + + + {/if} +
{:else} - -

{profile?.username} doesn't have any accessories

-
+ {/if} + {:else} + {/if}
diff --git a/src/lib/sections/stats/Bestiary.svelte b/src/lib/sections/stats/Bestiary.svelte index 39bb2f358..1e476dc3c 100644 --- a/src/lib/sections/stats/Bestiary.svelte +++ b/src/lib/sections/stats/Bestiary.svelte @@ -1,80 +1,94 @@
{#if bestiary} - - {#snippet text()} -
+
+
+
- {/snippet} - {#if bestiary.categories} - {#each Object.entries(bestiary.categories) as [_, data], index (index)} -
-

{data.name}

- {#if data.mobsMaxed === data.mobs?.length} - Max! - {:else} - ({data.mobsMaxed} / {data.mobs?.length} max) - {/if} -
+
- - {#each data.mobs as mob, index (index)} - {@const hasKilled = mob.kills} - {@const hasMaxed = mob.tier === mob.maxTier} - -
-
- {mob.name} - {mob.tier} -
- Kills: - {format(mob.kills)} -
-
+ [mob.name]} itemKey={(mob, index) => mob.name ?? index} noResultsLabel="No mobs match your search."> + {#snippet tabHeader(value)} + {const data = bestiary.categories?.[value]} + {#if data} +
+ {#if data.mobsMaxed === data.mobs?.length} + Max! + {:else} + {data.mobsMaxed} / {data.mobs?.length} maxed + {/if} +
+ {/if} + {/snippet} + {#snippet item(mob)} + {const hasKilled = mob.kills} + {const hasMaxed = mob.tier === mob.maxTier} + +
+
+ {mob.name} + {mob.tier} +
+ Kills: + {format(mob.kills)}
- {#snippet tooltip()} -
- {#if hasMaxed} - Progress: - max! - {:else} -
-
- - Progress to Tier {(mob.tier ?? 0) + 1}: - - {format(mob.kills)} / {format(mob.nextTierKills)} -
-
- Overall progress: - {format(mob.kills)} / {format(mob.maxKills)} -
-
- {/if} +
+
+ {#snippet tooltip()} +
+ {#if hasMaxed} + Progress: + max! + {:else} +
+
+ + Progress to Tier {(mob.tier ?? 0) + 1}: + + {format(mob.kills)} / {format(mob.nextTierKills)} +
+
+ Overall progress: + {format(mob.kills)} / {format(mob.maxKills)} +
- {/snippet} - - {/each} - - {/each} - {/if} - + {/if} +
+ {/snippet} + + {/snippet} + +
+ {:else} + {/if}
diff --git a/src/lib/sections/stats/Collections.svelte b/src/lib/sections/stats/Collections.svelte index b3f043a2b..b0d58fdf9 100644 --- a/src/lib/sections/stats/Collections.svelte +++ b/src/lib/sections/stats/Collections.svelte @@ -1,76 +1,90 @@
{#if collections} - - {#snippet text()} -
+
+
+
- {/snippet} - {#if collections.categories} - {#each Object.entries(collections.categories) as [_, data], index (index)} -
-

{data.name}

- {#if data.maxTiers === data.totalTiers} - Max! - {:else} - ({data.maxTiers} / {data.totalTiers} max) - {/if} -
+
- - {#each data.items as item, index (index)} - {@const hasUnlocked = item.totalAmount} - {@const hasMaxed = item.tier === item.maxTier} - -
-
- {item.name} - {item.tier} -
- Amount: - {format(item.totalAmount)} -
-
+ [item.name]} itemKey={(item, index) => item.id ?? item.name ?? index} noResultsLabel="No collections match your search."> + {#snippet tabHeader(value)} + {const data = collections.categories?.[value]} + {#if data} +
+ {#if data.maxTiers === data.totalTiers} + Max! + {:else} + {data.maxTiers} / {data.totalTiers} maxed + {/if} +
+ {/if} + {/snippet} + {#snippet item(item)} + {const hasUnlocked = item.totalAmount} + {const hasMaxed = item.tier === item.maxTier} + +
+
+ {item.name} + {item.tier} +
+ Amount: + {format(item.totalAmount)}
- {#snippet tooltip()} -
- {#if item.amounts && item.amounts.length > 0} -
- {#each item.amounts as user, index (index)} -
- - {user.username}: - - {format(user.amount)} -
- {/each} +
+
+ {#snippet tooltip()} +
+ {#if item.amounts && item.amounts.length > 0} +
+ {#each item.amounts as user, index (index)} +
+ + {user.username}: + + {format(user.amount)}
- {/if} -
- Total: - {format(item.totalAmount)} -
+ {/each}
- {/snippet} - - {/each} - - {/each} - {/if} - + {/if} +
+ Total: + {format(item.totalAmount)} +
+
+ {/snippet} + + {/snippet} + +
+ {:else} + {/if}
diff --git a/src/lib/sections/stats/CrimsonIsle.svelte b/src/lib/sections/stats/CrimsonIsle.svelte index 314170d22..e9510edde 100644 --- a/src/lib/sections/stats/CrimsonIsle.svelte +++ b/src/lib/sections/stats/CrimsonIsle.svelte @@ -1,11 +1,13 @@
{#if dungeons} -
+
{#if dungeons.level && dungeons.level.xp === 0} -

{profile?.username} hasn't unlocked Dungeons yet.

+ {:else if dungeons} -
+
{#if dungeons.level} - + {/if} {#if dungeons.classes && dungeons.classes.classes} {#each Object.entries(dungeons.classes.classes) as [className, classData], index (index)} @@ -26,29 +31,35 @@ {/each} {/if}
-
+
{#if dungeons.classes} {#if dungeons.classes.selectedClass} {/if} {#if dungeons.classes.classAverage != null} = 50}> -
+
{#if dungeons.classes.totalClassExp != null}
-

Total Class XP: {format(dungeons.classes.totalClassExp.toFixed(2))}

-

Total Class XP gained in Catacombs.

+ +

Total Class XP gained in Catacombs.

{/if} + + {#if dungeons.classes.totalClassExp != null && dungeons.classes.classAverageWithProgress != null} + + {/if} + {#if dungeons.classes.classAverageWithProgress != null}
-

Average Level: {format(dungeons.classes.classAverageWithProgress.toFixed(2))}

-

Average class level, includes progress to next level.

+ +

Average class level, includes progress to next level.

{/if} +
-

Average Level without progress: {format(dungeons.classes.classAverage.toFixed(2))}

-

Average class level without including partial level progress.

+ +

Average class level without including partial level progress.

@@ -64,20 +75,22 @@ {/if}
-
+
{#snippet subtitle()} -

Catacombs

+ Catacombs {/snippet}
-
+
{#snippet subtitle()} -

Master Catacombs

+ Master Catacombs {/snippet}
{/if}
+ {:else} + {/if}
diff --git a/src/lib/sections/stats/Gear.svelte b/src/lib/sections/stats/Gear.svelte index 8d33246ab..cb509e30d 100644 --- a/src/lib/sections/stats/Gear.svelte +++ b/src/lib/sections/stats/Gear.svelte @@ -1,19 +1,21 @@ -
+
{#if armor && armor.armor} - - {#snippet text()} - {#if armor && armor.armor} - {#if armor.armor.length > 0 && !armor.armor.every((piece) => !piece.display_name)} - {#if armor.set_name} -

- Set: - {armor.set_name} -

- {/if} +
+ Armor + {#if armor && armor.armor} + {#if armor.armor.length > 0 && !armor.armor.every((piece) => !piece.display_name)} + {#if armor.set_name} +

+ Set: + {armor.set_name} +

{/if} {/if} - {/snippet} + {/if} + + {#if armor.stats} + + {/if} {#if armor.armor.length > 0 && !armor.armor.every((piece) => !piece.display_name)} - {#each armor.armor as piece, index (index)} - {#if piece && piece.display_name} - - {:else} - - {/if} - {/each} + + {#each armor.armor as piece, index (index)} + {#if piece && piece.display_name} + + {:else} + + {/if} + {/each} + {:else} -

{profile?.username} has no armor equipped

+ {/if} - {#snippet info()} - {#if armor.stats} - - {/if} - {/snippet} - +
{/if} {#if equipment} - +
+ Equipment + {#if equipment.stats} + + {/if} {#if equipment.equipment && equipment.equipment.length > 0} - {#each equipment.equipment as piece, index (index)} - - {/each} + + {#each equipment.equipment as piece, index (index)} + + {/each} + {:else} -

{profile?.username} has no equipment equipped

+ {/if} - {#snippet info()} - {#if equipment.stats} - - {/if} - {/snippet} - +
{/if} {#if wardrobe && wardrobe.length > 0} - +
+ Wardrobe
- - - {#snippet viewportChildren()} -
- {#each firstWardrobeItems as _, i (i)} -
- -
- {/each} -
- {/snippet} - - - - - -
+ +
+ {#each firstWardrobeItems as _, i (i)} +
+ +
+ {/each} +
+
+
- +
{/if} {#if weapons} - - {#snippet text()} - {#if weapons.weapons && weapons.weapons.length} -
- {#if weapons.highest_priority_weapon?.display_name} -

- Active Weapon: - {@html renderLore(weapons.highest_priority_weapon.display_name)} -

- {/if} -
- {:else} -

{profile?.username} has no weapons

- {/if} - {/snippet} +
+ Weapons + + {#if weapons.weapons && weapons.weapons.length} +
+ {#if weapons.highest_priority_weapon?.display_name} +

+ Active Weapon: + {@html renderLore(weapons.highest_priority_weapon.display_name)} +

+ {/if} +
+ {:else} + + {/if} {#if weapons.weapons && weapons.weapons.length} - {#each weapons.weapons as weapon, index (index)} - - {/each} + + {#each weapons.weapons as weapon, index (index)} + + {/each} + {/if} - +
{/if}
diff --git a/src/lib/sections/stats/Inventory.svelte b/src/lib/sections/stats/Inventory.svelte index 8fce7b40e..9ab70d077 100644 --- a/src/lib/sections/stats/Inventory.svelte +++ b/src/lib/sections/stats/Inventory.svelte @@ -1,20 +1,26 @@
+ {const inventories = $derived(uuid && profileId ? await getInventories({ uuid, profileId }) : [])} + {const selectedInventory = $derived(openTab ? inventories.find((inventory) => inventory.name === openTab) : undefined)} + {const selectedTabName = $derived(selectedInventory?.name ?? inventories[0]?.name ?? "")} + {const currentInventory = $derived(selectedInventory ?? inventories[0])} + {const usesNestedInventoryView = $derived(selectedTabName === "Backpack" || selectedTabName === "Museum" || selectedTabName === "Sacks")} {#snippet pending()} - +
+ + Loading Inventory Data +
{/snippet} - {#snippet failed()} -

Failed to load inventories.

+ {#snippet failed(err, reset)} + {/snippet} {#if inventories.length && currentInventory} - selectedTabName, handleTabChange} class="@container relative mb-0 rounded-lg bg-background/30 p-5 pt-4"> - - - {#snippet viewportChildren()} -
- {#each inventories as tabItem (tabItem.name)} - - - - - - - - {tabItem.name} - {#if selectedTabName === tabItem.name} -
- {:else} -
- {/if} -
- {/each} -
- {/snippet} - - - -
-
+ selectedTabName, handleTabChange} class="group/tabs relative mb-0 flex flex-col rounded-xl border md:flex-row" orientation={tabsOrientation}> + {#if isMobile.current} + + + {@render inventoryTabItems(inventories, selectedTabName)} + + + + {:else} +
+ + +
+ {@render inventoryTabItems(inventories, selectedTabName)} +
+
+
+
+ +
+ {/if} - + {#if selectedTabName === "Search"} {#if uuid && profileId} {/if} {:else if usesNestedInventoryView} - {@render multipleInventorySection(currentInventory?.items ?? [])} + {@render multipleInventorySection(currentInventory?.items ?? [], currentInventory)} {:else} {/if} @@ -98,6 +101,23 @@
+{#snippet inventoryTabItems(inventories: ModelsInventory[], selectedTabName: string)} + {#each inventories as tabItem (tabItem.name)} + + {#if selectedTabName === tabItem.name} +
+ {/if} + + + + + + + {tabItem.name} +
+ {/each} +{/snippet} + {#snippet itemSnippet(item: ModelsStrippedItem)} {/snippet} @@ -110,9 +130,9 @@
{/snippet} -{#snippet multipleInventorySection(items: ModelsStrippedItem[])} +{#snippet multipleInventorySection(items: ModelsStrippedItem[], currentInventory: ModelsInventory)} - + {#if items?.length} {#each items as item, index (index)} @@ -134,7 +154,7 @@ {#if items?.length} {#each items as item, index (index)} -
+
{#if item?.containsItems} {#each item.containsItems as containedItem, index2 (index2)} {#if index2 > 0} @@ -154,8 +174,8 @@ {/each} {/if}
-
-
+
+
{#if item?.lore} {#each item?.lore as lore, index (index)} {@html renderLore(lore)} diff --git a/src/lib/sections/stats/Minions.svelte b/src/lib/sections/stats/Minions.svelte index 1edd0400d..66fd3c982 100644 --- a/src/lib/sections/stats/Minions.svelte +++ b/src/lib/sections/stats/Minions.svelte @@ -1,13 +1,15 @@
- {#if minions} - - {#snippet text()} -
+
+ + {#snippet child({ props })} + + + + + MI + + + + Looking for a place to trade minions? Check out MinionAH + + + + {/snippet} + + {#if minions} +
+
{#if minions.maxedTiers != null && minions.totalTiers != null} {/if} @@ -33,61 +62,45 @@ {/if}
- {/snippet} - - - - - MA - -
-
Looking for a place to trade minions?
- - Check out - - -
-
+
- {#if minions.minions} - {#each Object.entries(minions.minions) as [category, data], index (index)} -
-

{category}

- {#if data.maxedMinions === data.totalMinions} - Max! - {:else} - ({data.maxedMinions} / {data.totalMinions} max) - {/if} -
- - - {#each data.minions as minion, index (index)} - {#if minion.tiers} - {@const hasTier = minion.tiers[minion.tiers.length - 1]} - {@const hasMaxed = hasTier === minion.maxTier} - -
-
- {minion.name} - {hasTier ? minion.tiers[minion.tiers.length - 1] : 0} -
-
- {#snippet tooltip()} -
- {#each arabicTiers.slice(0, minion.maxTier) as tier, index (index)} - {#if minion.tiers} - {@const hasTier = minion.tiers.includes(tier)} - {romanTiers[tier - 1]} - {/if} - {/each} -
- {/snippet} -
+ [minion.name]} itemKey={(minion, index) => minion.name ?? index} noResultsLabel="No minions match your search."> + {#snippet tabHeader(value)} + {const data = minions.minions?.[value]} + {#if data} +
+ {#if data.maxedMinions === data.totalMinions} + Max! + {:else} + {data.maxedMinions} / {data.totalMinions} maxed {/if} - {/each} - - {/each} - {/if} - - {/if} +
+ {/if} + {/snippet} + {#snippet item(minion)} + {const tiers = minion.tiers ?? []} + {const hasTier = tiers[tiers.length - 1]} + {const hasMaxed = hasTier === minion.maxTier} + +
+
+ {minion.name} + {hasTier ? tiers[tiers.length - 1] : 0} +
+
+ {#snippet tooltip()} +
+ {#each arabicTiers.slice(0, minion.maxTier) as tier (tier)} + {const unlocked = tiers.includes(tier)} + {romanTiers[tier - 1]} + {/each} +
+ {/snippet} +
+ {/snippet} +
+ {:else} + + {/if} +
diff --git a/src/lib/sections/stats/MiscSection.svelte b/src/lib/sections/stats/MiscSection.svelte index ec47bd301..13386c41c 100644 --- a/src/lib/sections/stats/MiscSection.svelte +++ b/src/lib/sections/stats/MiscSection.svelte @@ -1,6 +1,8 @@ +{#snippet petCard(pet: ModelsStrippedPet)} +
+ +

LVL {pet.level}

+
+{/snippet} +
{#if pets} {#if pets.pets?.length} - - {#snippet text()} -
- - {#if pets.amountSkins} - - {/if} - {#if pets.petScore != null} - -
-

Pet score is calculated based on how many unique pets you have and the rarity of these pets.

-

You gain an additional score for each max level pet you have!

-
- {#each pets.petScore.reward as { score, bonus, unlocked }, index (index)} -
- {score} Score: +{bonus} Magic Find - {#if unlocked} - « - {/if} -
- {/each} -
-
-
- {/if} - {#if pets.totalCandyUsed != null} - - {/if} - {#if pets.totalPetExp != null} - - {/if} -
- {/snippet} -
- {#if activePet != null} - Active Pet - -
-
- -
-

{(activePet.rarity ?? "common").toLowerCase()} {@html renderLore((activePet.display_name ?? "").toLowerCase())}

-

Level {activePet.level}

-
+
+
+ + {#if pets.amountSkins} + + {/if} + {#if pets.petScore != null} + +
+ +

Pet score is calculated based on how many unique pets you have and the rarity of these pets.

+

You gain an additional score for each max level pet you have!

+
+ {#each pets.petScore.reward?.toReversed() as { score, bonus, unlocked }, index (index)} +
+ {score} Score: +{bonus} Magic Find + {#if unlocked} + « + {/if} +
+ {/each}
- {#if activePet.stats} - - {/if}
- +
+ {/if} + {#if pets.totalCandyUsed != null} + + {/if} + {#if pets.totalPetExp != null} + + {/if} +
- {#if uniquePets.length > 0 && uniquePets.find((pet) => !pet.active)} - Other Pets - - {#each uniquePets as pet, index (index)} - {#if !pet.active} -
- -

LVL {pet.level}

-
- {/if} - {/each} -
+ {#if activePet != null} +
+ Active Pet + {#if activePet.stats} + {/if} - {:else} - +
+ +
+

{(activePet.rarity ?? "common").toLowerCase()} {@html renderLore((activePet.display_name ?? "").toLowerCase())}

+

Level {activePet.level}

+
+
+
+ {/if} + + {#if hasInactiveUniquePets} +
+ Other Pets + + {#each uniquePets as pet, index (index)} {#if !pet.active} -
- -

LVL {pet.level}

-
+ {@render petCard(pet)} {/if} {/each} - - {/if} +
+
+ {/if} - {#if otherPets && otherPets.length > 0} - - - - Show More Pets - - - - {#each otherPets as pet, index (index)} -
- -

LVL {pet.level}

-
- {/each} -
-
-
- {/if} + {#if otherPets && otherPets.length > 0} + + Show More Pets + + + {#each otherPets as pet, index (index)} + {@render petCard(pet)} + {/each} + + + + {/if} - {#if pets.missing && pets.missing.length > 0} - - - - Missing Pets - - - - {#each pets.missing as pet, index (index)} -
- -
- {/each} -
-
-
- {/if} -
- + {#if pets.missing && pets.missing.length > 0} + + Missing Pets + + + {#each pets.missing as pet, index (index)} +
+ +
+ {/each} +
+
+
+ {/if} +
{:else} - -

{profile?.username} doesn't have any pets

-
+ {/if} + {:else} + {/if}
diff --git a/src/lib/sections/stats/Rift.svelte b/src/lib/sections/stats/Rift.svelte index d0ef4abd4..3af98883a 100644 --- a/src/lib/sections/stats/Rift.svelte +++ b/src/lib/sections/stats/Rift.svelte @@ -1,19 +1,23 @@ -
{#if slayer} -
- {#if slayer.totalSlayerExp === 0} -

{profile?.username} hasn't unlocked Slayers yet.

- {:else} -
+ {#if slayer.totalSlayerExp === 0} + + {:else} +
+
+ {#if slayer.stats} + + {/if}
+ {#if slayer.data} - + {#each Object.entries(slayer.data) as [key, value], index (index)} {#if value.level && value.level.xp != null && value.level.xp > 0} -
+
- - - + + + @@ -61,29 +66,28 @@ {key} Level {value.level.level}

- -
-
+
+ +
+ {#if value.level.maxed} - {format(value.level.xp)} + {formatNumber(value.level.xp)} {:else} - {format(value.level.xp)} / {format(value.level.xpForNext)} + {formatNumber(value.level.xp)} / {formatNumber(value.level.xpForNext ?? 0)} {/if} - XP -
+ + XP
-
- +
{/if} {/each} - - {/if} - {#if slayer.stats} - + {/if} - {/if} -
+
+ {/if} + {:else} + {/if}
diff --git a/src/lib/sections/stats/farming/garden.svelte b/src/lib/sections/stats/farming/garden.svelte index 5e9315f2d..7fddea195 100644 --- a/src/lib/sections/stats/farming/garden.svelte +++ b/src/lib/sections/stats/farming/garden.svelte @@ -1,97 +1,99 @@ - - - - Garden - + + Garden + {#if gardenLocked} -

This player does not have the Garden unlocked.

+ {:else if sectionOpen} getGarden({ uuid: profile?.uuid ?? "", profileId: profileId! })}> {#snippet children(garden)} {#if garden} - {@const hasMaxed = garden.level?.maxed ?? false} -
- -

- XP: - - {format(garden.level?.xp)} - -

-

Progress to next level:

- -
-
- {formatNumber(garden.level?.xpCurrent ?? 0)} / {formatNumber(garden.level?.xpForNext ?? 0)} - XP -
-
-
-
-
- value === 25)}> - {#each Object.entries(garden.composter ?? {}) as [key, value], index (index)} -

- {key.replaceAll("_", " ")}: - - {value} - -

- {/each} -
- - {#each Object.entries(garden.visitors?.visitors ?? {}) as [key, value], index (index)} -

- {key}: - - {format(value.completed)} - -

- {/each} -
- - {#each Object.entries(garden.visitors?.visitors ?? {}) as [key, value], index (index)} -

- {key}: - - {format(value.unique)} - -

- {/each} -
- -
- {#if garden.gardenUpgrades} -
-
-

Garden Upgrades

+ {const hasMaxed = $derived(garden.level?.maxed ?? false)} + + + + +
+ +
+ {formatNumber(garden.level?.xpCurrent ?? 0)} / {formatNumber(garden.level?.xpForNext ?? 0)} + XP
+ +
+
+ value === 25)}> + {#each Object.entries(garden.composter ?? {}) as [key, value], index (index)} + + {/each} + + + {#each Object.entries(garden.visitors?.visitors ?? {}) as [key, value], index (index)} + + {/each} + + + {#each Object.entries(garden.visitors?.visitors ?? {}) as [key, value], index (index)} + + {/each} + + - + {#if garden.gardenUpgrades} + +
+ Garden Upgrades + {#each garden.gardenUpgrades as gardenUpgrade, index (index)} - {@const hasUnlocked = gardenUpgrade.level} + {const hasUnlocked = gardenUpgrade.level}
@@ -104,17 +106,18 @@
{/each} - +
{/if} {#if garden.gardenChips != null} -
- Garden Chips - + +
+ Garden Chips + {#each garden.gardenChips as gardenChip, index (index)} - {@const hasUnlocked = gardenChip.amount} - {@const hasMaxed = (gardenChip.amount ?? 0) >= (gardenChip.maxLevel ?? 0)} + {const hasUnlocked = gardenChip.amount} + {const hasMaxed = (gardenChip.amount ?? 0) >= (gardenChip.maxLevel ?? 0)}
@@ -127,17 +130,19 @@
{/each} - +
{/if} {#if garden.mutations != null} -
- Mutations - + + +
+ Mutations + {#each garden.mutations as mutation, index (index)} - {@const hasUnlocked = mutation.unlocked} - {@const hasMaxed = mutation.max} + {const hasUnlocked = mutation.unlocked} + {const hasMaxed = mutation.max}
@@ -146,16 +151,22 @@
{/each} - +
{/if} -
+ + +
{@render milestones(garden)}
-
+ + +
{@render upgrades(garden)}
-
+ + +
{/if} @@ -167,18 +178,19 @@ {#snippet upgrades(garden: ModelsGarden)} {#if garden.cropUpgrades} - {@const allMaxed = Object.values(garden.cropUpgrades).every((upgrade) => upgrade.level?.maxed)} -
-

Crop Upgrades

+ {const allMaxed = Object.values(garden.cropUpgrades).every((upgrade) => upgrade.level?.maxed)} +
+ Crop Upgrades + {#if allMaxed} Max! {:else} ({Object.values(garden.cropUpgrades).filter((upgrade) => upgrade.level?.maxed).length} / {Object.values(garden.cropUpgrades).length} max) {/if}
- + {#each garden.cropUpgrades as upgrade, index (index)} - {@const hasMaxed = upgrade.level?.maxed} + {const hasMaxed = upgrade.level?.maxed}
@@ -188,24 +200,25 @@
{/each} - + {/if} {/snippet} {#snippet milestones(garden: ModelsGarden)} {#if garden.cropMilestones} - {@const allMaxed = Object.values(garden.cropMilestones).every((upgrade) => upgrade.level?.maxed)} -
-

Milestones

+ {const allMaxed = Object.values(garden.cropMilestones).every((upgrade) => upgrade.level?.maxed)} +
+ Milestones + {#if allMaxed} Max! {:else if garden.cropUpgrades} ({Object.values(garden.cropMilestones).filter((upgrade) => upgrade.level?.maxed).length} / {Object.values(garden.cropUpgrades).length} max) {/if}
- + {#each garden.cropMilestones as milestone, index (index)} - {@const hasMaxed = milestone.level?.maxed} + {const hasMaxed = milestone.level?.maxed}
@@ -215,19 +228,15 @@
{#snippet progress()} - -
-
- {formatNumber(milestone.level?.xpCurrent ?? 0)} / {formatNumber(milestone.level?.xpForNext ?? 0)} - XP -
+
+ +
+ {formatNumber(milestone.level?.xpCurrent ?? 0)} / {formatNumber(milestone.level?.xpForNext ?? 0)} XP
- -
- +
{/snippet} {/each} - + {/if} {/snippet} diff --git a/src/lib/sections/stats/misc/auctions.svelte b/src/lib/sections/stats/misc/auctions.svelte index d5c217169..43ac949e5 100644 --- a/src/lib/sections/stats/misc/auctions.svelte +++ b/src/lib/sections/stats/misc/auctions.svelte @@ -2,54 +2,57 @@ import { getMiscContext } from "$ctx"; import { SectionSubtitle } from "$lib/components/sections"; import { AdditionStat } from "$lib/components/stats"; - import Items from "$lib/layouts/stats/Items.svelte"; + import { RARITY_COLORS } from "$lib/shared/constants/rarities"; + import { Label } from "$ui/label"; import { format } from "numerable"; const misc = $derived(getMiscContext().misc); {#if misc && misc.auctions != null} - Auctions Sold - - {#snippet text()} - {#if misc.auctions} -
- - - {#if misc.auctions.total_sold && misc.auctions.total_sold.total !== 0} - - {#each Object.entries(misc.auctions.total_sold) as [rarity, amount], index (index)} - {#if rarity !== "total"} - - {/if} - {/each} - - {/if} -
+
+ Auctions Sold +
+ + + {#if misc.auctions.total_sold && misc.auctions.total_sold.total !== 0} + +
+ {#each Object.entries(misc.auctions.total_sold) as [rarity, amount], index (index)} + {#if rarity !== "total"} + + {/if} + {/each} +
+
{/if} - {/snippet} - +
+
- Auctions Bought - - {#snippet text()} - {#if misc.auctions} -
- - - - - {#if misc.auctions.total_bought && misc.auctions.total_bought.total !== 0} - - {#each Object.entries(misc.auctions.total_bought) as [rarity, amount], index (index)} - {#if rarity !== "total"} - - {/if} - {/each} - - {/if} -
+
+ Auctions Bought +
+ + + + + {#if misc.auctions.total_bought && misc.auctions.total_bought.total !== 0} + +
+ {#each Object.entries(misc.auctions.total_bought) as [rarity, amount], index (index)} + {#if rarity !== "total"} + + {/if} + {/each} +
+
{/if} - {/snippet} - +
+
{/if} diff --git a/src/lib/sections/stats/misc/chips.svelte b/src/lib/sections/stats/misc/chips.svelte index eefca6a52..0b90b7b23 100644 --- a/src/lib/sections/stats/misc/chips.svelte +++ b/src/lib/sections/stats/misc/chips.svelte @@ -1,18 +1,22 @@ {#if misc && misc.essence != null} @@ -24,12 +28,12 @@ {/if} {#snippet chips(title: string, data: ChipData[])} -
- {title} - +
+ {title} + {#each data as item, index (index)} - {@const hasUnlocked = item.amount} - {@const hasMaxed = item.maxAmount != null && item.amount === item.maxAmount} + {const hasUnlocked = item.amount} + {const hasMaxed = item.maxAmount != null && item.amount === item.maxAmount}
@@ -44,6 +48,6 @@
{/each} - +
{/snippet} diff --git a/src/lib/sections/stats/misc/claimed.svelte b/src/lib/sections/stats/misc/claimed.svelte index 4aa661371..5e92eb1e8 100644 --- a/src/lib/sections/stats/misc/claimed.svelte +++ b/src/lib/sections/stats/misc/claimed.svelte @@ -2,7 +2,6 @@ import { getMiscContext } from "$ctx"; import { SectionSubtitle } from "$lib/components/sections"; import { AdditionStat } from "$lib/components/stats"; - import Items from "$lib/layouts/stats/Items.svelte"; import { tz } from "@date-fns/tz"; import { formatDate, formatDistanceToNowStrict } from "date-fns"; @@ -10,26 +9,22 @@ {#if misc && misc.claimed_items != null} - Claimed Items - - {#snippet text()} - {#if misc.claimed_items} -
- {#each Object.entries(misc.claimed_items) as [item, time], index (index)} - {#if time} - - {formatDate(time, "'Claimed on' dd MMMM yyyy 'at' HH:mm", { in: tz(Intl.DateTimeFormat().resolvedOptions().timeZone) })} - - {/if} - {/each} -
- {/if} - {/snippet} -
+
+ Claimed Items +
+ {#each Object.entries(misc.claimed_items) as [item, time], index (index)} + {#if time} + + {formatDate(time, "'Claimed on' dd MMMM yyyy 'at' HH:mm", { in: tz(Intl.DateTimeFormat().resolvedOptions().timeZone) })} + + {/if} + {/each} +
+
{/if} diff --git a/src/lib/sections/stats/misc/damage.svelte b/src/lib/sections/stats/misc/damage.svelte index d972b1701..865db3502 100644 --- a/src/lib/sections/stats/misc/damage.svelte +++ b/src/lib/sections/stats/misc/damage.svelte @@ -2,23 +2,18 @@ import { getMiscContext } from "$ctx"; import { SectionSubtitle } from "$lib/components/sections"; import { AdditionStat } from "$lib/components/stats"; - import Items from "$lib/layouts/stats/Items.svelte"; import { format } from "numerable"; const misc = $derived(getMiscContext().misc); {#if misc && misc.damage != null} - Damage - - {#snippet text()} - {#if misc.damage} -
- {#each Object.entries(misc.damage) as [text, data], index (index)} - - {/each} -
- {/if} - {/snippet} -
+
+ Damage +
+ {#each Object.entries(misc.damage) as [text, data], index (index)} + + {/each} +
+
{/if} diff --git a/src/lib/sections/stats/misc/dragons.svelte b/src/lib/sections/stats/misc/dragons.svelte index 61e6d8f3d..da2b78040 100644 --- a/src/lib/sections/stats/misc/dragons.svelte +++ b/src/lib/sections/stats/misc/dragons.svelte @@ -2,8 +2,8 @@ import { getMiscContext } from "$ctx"; import { SectionSubtitle } from "$lib/components/sections"; import { AdditionStat } from "$lib/components/stats"; - import Items from "$lib/layouts/stats/Items.svelte"; import { formatTime } from "$lib/shared/helper"; + import { Label } from "$ui/label"; import { format } from "numerable"; const misc = $derived(getMiscContext().misc); @@ -11,47 +11,65 @@ {#if misc && dragons} - Dragons - - {#snippet text()} -
- {#if dragons.most_damage?.best} - +
+ Dragons +
+ {#if dragons.most_damage?.best} + +
{#each Object.entries(dragons.most_damage) as [text, data], index (index)} {#if text !== "best"} - + {/if} {/each} - - {/if} - {#if dragons.fastest_kill?.best} - +
+
+ {/if} + {#if dragons.fastest_kill?.best} + +
{#each Object.entries(dragons.fastest_kill) as [text, data], index (index)} {#if text !== "best"} - + {/if} {/each} - - {/if} - {#if dragons.last_hits != null} - +
+
+ {/if} + {#if dragons.last_hits != null} + +
{#each Object.entries(dragons.last_hits) as [text, data], index (index)} {#if text !== "total"} - + {/if} {/each} - - {/if} - {#if dragons.deaths != null} - +
+
+ {/if} + {#if dragons.deaths != null} + +
{#each Object.entries(dragons.deaths) as [text, data], index (index)} {#if text !== "total"} - + {/if} {/each} - - {/if} -
- {/snippet} - +
+ + {/if} +
+
{/if} diff --git a/src/lib/sections/stats/misc/endstone.svelte b/src/lib/sections/stats/misc/endstone.svelte index 6715220e3..cb4a2750c 100644 --- a/src/lib/sections/stats/misc/endstone.svelte +++ b/src/lib/sections/stats/misc/endstone.svelte @@ -2,23 +2,18 @@ import { getMiscContext } from "$ctx"; import { SectionSubtitle } from "$lib/components/sections"; import { AdditionStat } from "$lib/components/stats"; - import Items from "$lib/layouts/stats/Items.svelte"; import { format } from "numerable"; const misc = $derived(getMiscContext().misc); {#if misc && misc.endstone_protector != null} - Endstone Protector - - {#snippet text()} - {#if misc.endstone_protector} -
- {#each Object.entries(misc.endstone_protector) as [text, data], index (index)} - - {/each} -
- {/if} - {/snippet} -
+
+ Endstone Protector +
+ {#each Object.entries(misc.endstone_protector) as [text, data], index (index)} + + {/each} +
+
{/if} diff --git a/src/lib/sections/stats/misc/gifts.svelte b/src/lib/sections/stats/misc/gifts.svelte index 22d54ef76..5aba33be6 100644 --- a/src/lib/sections/stats/misc/gifts.svelte +++ b/src/lib/sections/stats/misc/gifts.svelte @@ -2,23 +2,18 @@ import { getMiscContext } from "$ctx"; import { SectionSubtitle } from "$lib/components/sections"; import { AdditionStat } from "$lib/components/stats"; - import Items from "$lib/layouts/stats/Items.svelte"; import { format } from "numerable"; const misc = $derived(getMiscContext().misc); {#if misc && misc.gifts != null} - Gifts - - {#snippet text()} - {#if misc.gifts} -
- {#each Object.entries(misc.gifts) as [text, data], index (index)} - - {/each} -
- {/if} - {/snippet} -
+
+ Gifts +
+ {#each Object.entries(misc.gifts) as [text, data], index (index)} + + {/each} +
+
{/if} diff --git a/src/lib/sections/stats/misc/jerry.svelte b/src/lib/sections/stats/misc/jerry.svelte index d93df6031..28798dc5e 100644 --- a/src/lib/sections/stats/misc/jerry.svelte +++ b/src/lib/sections/stats/misc/jerry.svelte @@ -2,23 +2,18 @@ import { getMiscContext } from "$ctx"; import { SectionSubtitle } from "$lib/components/sections"; import { AdditionStat } from "$lib/components/stats"; - import Items from "$lib/layouts/stats/Items.svelte"; import { format } from "numerable"; const misc = $derived(getMiscContext().misc); {#if misc && misc.season_of_jerry != null} - Season of Jerry - - {#snippet text()} - {#if misc.season_of_jerry} -
- {#each Object.entries(misc.season_of_jerry) as [text, data], index (index)} - - {/each} -
- {/if} - {/snippet} -
+
+ Season of Jerry +
+ {#each Object.entries(misc.season_of_jerry) as [text, data], index (index)} + + {/each} +
+
{/if} diff --git a/src/lib/sections/stats/misc/kills.svelte b/src/lib/sections/stats/misc/kills.svelte index a98828d4a..d961ceebb 100644 --- a/src/lib/sections/stats/misc/kills.svelte +++ b/src/lib/sections/stats/misc/kills.svelte @@ -1,8 +1,9 @@ {#if misc && misc.kills != null} -
- Kills -
+
+ Kills +
{#if (misc.kills.kills && misc.kills.kills.length > 0) || (misc.kills.deaths && misc.kills.deaths.length > 0)} - + {#if misc.kills.kills} -
-
Kills
+
+
Kills
+ 0 ? 20 : 0} scrollDirection="vertical"> {#snippet item({ index, style })}
@@ -36,8 +38,9 @@
{/if} {#if misc.kills.deaths} -
-
Deaths
+
+
Deaths
+ 0 ? 20 : 0} scrollDirection="vertical"> {#snippet item({ index, style })}
@@ -49,7 +52,7 @@
{/if} - + {/if}
{/if} diff --git a/src/lib/sections/stats/misc/mythological.svelte b/src/lib/sections/stats/misc/mythological.svelte index 8a56e052a..ba963b0a1 100644 --- a/src/lib/sections/stats/misc/mythological.svelte +++ b/src/lib/sections/stats/misc/mythological.svelte @@ -2,67 +2,76 @@ import { getMiscContext } from "$ctx"; import { SectionSubtitle } from "$lib/components/sections"; import { AdditionStat } from "$lib/components/stats"; - import Items from "$lib/layouts/stats/Items.svelte"; + import { RARITY_COLORS } from "$lib/shared/constants/rarities"; + import { Label } from "$ui/label"; import { format } from "numerable"; const misc = $derived(getMiscContext().misc); {#if misc && misc.mythological_event != null} - Mythological Event - - {#snippet text()} - {#if misc.mythological_event} -
- {#if misc.mythological_event.kills} - - {/if} +
+ Mythological Event +
+ {#if misc.mythological_event.kills} + + {/if} - {#if misc.mythological_event.burrows_dug_next?.total} - -

Rarities used:

- {#each Object.entries(misc.mythological_event.burrows_dug_next) as [tier, count], index (index)} - {#if tier !== "total"} - - {/if} - {/each} - - {/if} + {#if misc.mythological_event.burrows_dug_next?.total} + + + {#each Object.entries(misc.mythological_event.burrows_dug_next) as [tier, count], index (index)} + {#if tier !== "total"} + + {/if} + {/each} + + {/if} - {#if misc.mythological_event.burrows_dug_combat?.total} - -

Rarities used:

- {#each Object.entries(misc.mythological_event.burrows_dug_combat) as [tier, count], index (index)} - {#if tier !== "total"} - - {/if} - {/each} - - {/if} + {#if misc.mythological_event.burrows_dug_combat?.total} + + + {#each Object.entries(misc.mythological_event.burrows_dug_combat) as [tier, count], index (index)} + {#if tier !== "total"} + + {/if} + {/each} + + {/if} - {#if misc.mythological_event.burrows_dug_treasure?.total} - -

Rarities used:

- {#each Object.entries(misc.mythological_event.burrows_dug_treasure) as [tier, count], index (index)} - {#if tier !== "total"} - - {/if} - {/each} - - {/if} + {#if misc.mythological_event.burrows_dug_treasure?.total} + + + {#each Object.entries(misc.mythological_event.burrows_dug_treasure) as [tier, count], index (index)} + {#if tier !== "total"} + + {/if} + {/each} + + {/if} - {#if misc.mythological_event.burrows_chains_complete?.total} - -

Rarities used:

- {#each Object.entries(misc.mythological_event.burrows_chains_complete) as [tier, count], index (index)} - {#if tier !== "total"} - - {/if} - {/each} - - {/if} -
+ {#if misc.mythological_event.burrows_chains_complete?.total} + + + {#each Object.entries(misc.mythological_event.burrows_chains_complete) as [tier, count], index (index)} + {#if tier !== "total"} + + {/if} + {/each} + {/if} - {/snippet} - +
+
{/if} diff --git a/src/lib/sections/stats/misc/pet.svelte b/src/lib/sections/stats/misc/pet.svelte index 66b914a03..2f6d7b969 100644 --- a/src/lib/sections/stats/misc/pet.svelte +++ b/src/lib/sections/stats/misc/pet.svelte @@ -2,41 +2,59 @@ import { getMiscContext } from "$ctx"; import { SectionSubtitle } from "$lib/components/sections"; import { AdditionStat } from "$lib/components/stats"; - import Items from "$lib/layouts/stats/Items.svelte"; + import { RARITY_COLORS } from "$lib/shared/constants/rarities"; import { titleCase } from "$lib/shared/helper"; + import { cn } from "$lib/shared/utils"; + import { Label } from "$ui/label"; import { format } from "numerable"; const misc = $derived(getMiscContext().misc); {#if misc && misc.pet_milestones != null} - Pet Milestones - - {#snippet text()} - {#if misc.pet_milestones} -
- - {#if misc.pet_milestones.sea_creatures_killed.rarity} - - {/if} - {#if misc.pet_milestones.sea_creatures_killed.progress !== null} - - {/if} - - - {#if misc.pet_milestones.ores_mined} - - {#if misc.pet_milestones.ores_mined.rarity} - - {/if} - - {#if misc.pet_milestones.ores_mined.progress !== null} - - {/if} - +
+ Pet Milestones +
+ +
+ {#if misc.pet_milestones.sea_creatures_killed.rarity} + + {/if} + {#if misc.pet_milestones.sea_creatures_killed.progress !== null} + {/if}
+
+ + {#if misc.pet_milestones.ores_mined} + +
+ {#if misc.pet_milestones.ores_mined.rarity} + + {/if} + + {#if misc.pet_milestones.ores_mined.progress !== null} + + {/if} +
+
{/if} - {/snippet} - +
+
{/if} diff --git a/src/lib/sections/stats/misc/potions.svelte b/src/lib/sections/stats/misc/potions.svelte deleted file mode 100644 index 2a5345301..000000000 --- a/src/lib/sections/stats/misc/potions.svelte +++ /dev/null @@ -1,26 +0,0 @@ - - - - diff --git a/src/lib/sections/stats/misc/races.svelte b/src/lib/sections/stats/misc/races.svelte deleted file mode 100644 index 210239d1f..000000000 --- a/src/lib/sections/stats/misc/races.svelte +++ /dev/null @@ -1,56 +0,0 @@ - - - - diff --git a/src/lib/sections/stats/misc/uncategorized.svelte b/src/lib/sections/stats/misc/uncategorized.svelte index b819581d4..91d75c3e1 100644 --- a/src/lib/sections/stats/misc/uncategorized.svelte +++ b/src/lib/sections/stats/misc/uncategorized.svelte @@ -2,22 +2,17 @@ import { getMiscContext } from "$ctx"; import { SectionSubtitle } from "$lib/components/sections"; import { AdditionStat } from "$lib/components/stats"; - import Items from "$lib/layouts/stats/Items.svelte"; import { format } from "numerable"; const misc = $derived(getMiscContext().misc); {#if misc && misc.uncategorized != null && Object.values(misc.uncategorized).filter((value) => value).length > 0} - Uncategorized - - {#snippet text()} - {#if misc.uncategorized} -
- - -
- {/if} - {/snippet} -
+
+ Uncategorized +
+ + +
+
{/if} diff --git a/src/lib/sections/stats/misc/upgrades.svelte b/src/lib/sections/stats/misc/upgrades.svelte index bbfd3c370..1bbd49007 100644 --- a/src/lib/sections/stats/misc/upgrades.svelte +++ b/src/lib/sections/stats/misc/upgrades.svelte @@ -2,25 +2,20 @@ import { getMiscContext } from "$ctx"; import { SectionSubtitle } from "$lib/components/sections"; import { AdditionStat } from "$lib/components/stats"; - import Items from "$lib/layouts/stats/Items.svelte"; import { format } from "numerable"; const misc = $derived(getMiscContext().misc); {#if misc && misc.profile_upgrades != null} - Upgrades - - {#snippet text()} - {#if misc.profile_upgrades} -
- - - - - -
- {/if} - {/snippet} -
+
+ Upgrades +
+ + + + + +
+
{/if} diff --git a/src/lib/sections/stats/skills/current-tab-context.svelte.ts b/src/lib/sections/stats/skills/current-tab-context.svelte.ts new file mode 100644 index 000000000..003a8ac06 --- /dev/null +++ b/src/lib/sections/stats/skills/current-tab-context.svelte.ts @@ -0,0 +1,16 @@ +import { createContext } from "svelte"; +import type { TabNames } from "../types"; + +export class CurrentTabContext { + #current: TabNames | null = $state(null); + + get current() { + return this.#current; + } + + set current(value: TabNames | null) { + this.#current = value; + } +} + +export const [getCurrentTabContext, setCurrentTabContext] = createContext(); diff --git a/src/lib/sections/stats/skills/enchanting.svelte b/src/lib/sections/stats/skills/enchanting.svelte index f6397a031..0fda79484 100644 --- a/src/lib/sections/stats/skills/enchanting.svelte +++ b/src/lib/sections/stats/skills/enchanting.svelte @@ -1,42 +1,39 @@ -Enchanting {#if enchanting} {#if enchanting.unlocked === false} -

This player hasn't unlocked Enchanting yet.

+ {:else} - - - - Experiments - - + + Experiments + {#if enchanting && enchanting.data} - {@const enchantingStats = Object.entries(enchanting.data)} - + {const enchantingStats = Object.entries(enchanting.data)} + {#each enchantingStats as [_key, enchating], index (index)} -
-
+
+
{enchating.name}
{#if enchating.stats} -
+
{#if enchating.stats.bonusClicks} - + {/if} {#if enchating.stats.lastAttempt} @@ -47,22 +44,22 @@
{/if} {#if enchating.stats} -
+
{#each enchating.stats.games as game, index (index)}
-

{`${game.name}`}

+

{game.name}

{#if game.attempts} - + {/if} {#if game.claims} - + {/if} {#if game.bestScore} - + {/if}
@@ -72,13 +69,13 @@ {/if}
{/each} - + {:else} -

No data available

+ {/if} {/if} {:else} -

This player doesn't have anything related to enchanting.

+ {/if} diff --git a/src/lib/sections/stats/skills/farming.svelte b/src/lib/sections/stats/skills/farming.svelte index 7226887a4..445bef5b2 100644 --- a/src/lib/sections/stats/skills/farming.svelte +++ b/src/lib/sections/stats/skills/farming.svelte @@ -1,57 +1,88 @@ -Farming {#if farming} -
-
- {#if farming.pelts} - - {/if} - {#if farming.contestsAttended} - - {/if} - {#if farming.uniqueGolds} - - {/if} -
- - {#if farming.medals} -
- {#each Object.entries(farming.medals) as [medal, medalData], index (index)} - {#if medalData.total} - - {#each Object.entries(medalData) as [key, value], index (index)} - - {/each} - +
+ + {#snippet child({ props })} + + + + + EL + + + + For more in-depth Farming stats, check out Elite + + + + {/snippet} + + {#if farming.pelts || farming.contestsAttended || farming.uniqueGolds} +
+
+ {#if farming.pelts} + + {/if} + {#if farming.contestsAttended} + + {/if} + {#if farming.uniqueGolds} + {/if} - {/each} +
{/if} -
- Farming Tools - {#if farmingTools && farmingTools.tools && farmingTools.tools.length > 0} - - {#snippet text()} + {#if farming.medals} +
+
+ {#each Object.entries(farming.medals) as [medal, medalData], index (index)} + {#if medalData.total} + +
+ {#each Object.entries(medalData) as [key, value], index (index)} + + {/each} +
+
+ {/if} + {/each} +
+
+ {/if} +
+ Farming Tools + {#if farmingTools && farmingTools.tools && farmingTools.tools.length > 0}
{#if highestPriorityFarmingTool && highestPriorityFarmingTool.display_name}

@@ -60,45 +91,45 @@

{/if}
- {/snippet} - {#each farmingTools.tools as tool, index (index)} - - {/each} - - {:else} -

This player doesn't have any farming tools.

- {/if} + + {#each farmingTools.tools as tool, index (index)} + + {/each} + + {:else} + + {/if} +
- {#if farming.contests} - {#if Object.entries(farming.contests).find(([_, cropData]) => (cropData.amount ?? 0) > 0)} - - - - Farming Crops - - - {@const crops = Object.entries(farming.contests)} - - {#each crops as [_, cropData], index (index)} - -
-

{cropData.name}

- {#if cropData.collected != null} - - {/if} - {#if cropData.amount != null} - - {/if} -
-
- {/each} -
-
-
+ {#if farming.contests} + {#if Object.entries(farming.contests).find(([_, cropData]) => (cropData.amount ?? 0) > 0)} + + Farming Crops + + {const crops = $derived(Object.entries(farming.contests))} + + + {#each crops as [_, cropData], index (index)} + +
+

{cropData.name}

+ {#if cropData.collected != null} + + {/if} + {#if cropData.amount != null} + + {/if} +
+
+ {/each} +
+
+
+ {/if} {/if} - {/if} +
{:else} -

This player doesn't have anything related to farming.

+ {/if} diff --git a/src/lib/sections/stats/skills/fishing.svelte b/src/lib/sections/stats/skills/fishing.svelte index 7c1f2797b..e7168ccec 100644 --- a/src/lib/sections/stats/skills/fishing.svelte +++ b/src/lib/sections/stats/skills/fishing.svelte @@ -1,22 +1,45 @@ -Fishing {#if fishing} -
- - - - - {#if fishing.trophyFish} - - {/if} -
+
+
+
+ + + + + {#if fishing.trophyFish} + + {/if} +
+
- Fishing Rods - {#if fishingTools && fishingTools.tools && fishingTools.tools.length > 0} - - {#snippet text()} +
+ Fishing Rods + {#if fishingTools && fishingTools.tools && fishingTools.tools.length > 0}
{#if highestPriorityFishingTool && highestPriorityFishingTool.display_name}

@@ -48,170 +72,130 @@

{/if}
- {/snippet} - {#each fishingTools.tools as tool, index (index)} - - {/each} - - {:else} -

This player doesn't have any fishing tools.

- {/if} - {#if fishing.waterSeaCreatures} - {#if Object.entries(fishing.waterSeaCreatures).find(([_, waterSeaCreature]) => (waterSeaCreature.amount ?? 0) > 0)} - - - - Sea Creatures - - - {@const waterSeaCreatures = Object.entries(fishing.waterSeaCreatures)} - - {#each waterSeaCreatures as [_, waterSeaCreature], index (index)} -
-
- {waterSeaCreature.name} -
-
- - - - - - -
- {waterSeaCreature.amount} Kills -
-
-
- {/each} -
-
-
+ + {#each fishingTools.tools as tool, index (index)} + + {/each} + + {:else} + + {/if} +
+ + {#if fishing.waterSeaCreatures} + {#if Object.entries(fishing.waterSeaCreatures).find(([_, waterSeaCreature]) => (waterSeaCreature.amount ?? 0) > 0)} + {@render creaturesDisplay("Sea Creatures", fishing.waterSeaCreatures)} + {/if} {/if} - {/if} - {#if fishing.lavaSeaCreatures} - {#if Object.entries(fishing.lavaSeaCreatures).find(([_, lavaSeaCreature]) => (lavaSeaCreature.amount ?? 0) > 0)} - - - - Lava Sea Creatures - - - {@const lavaSeaCreatures = Object.entries(fishing.lavaSeaCreatures)} - - {#each lavaSeaCreatures as [_, lavaSeaCreature], index (index)} -
-
- {lavaSeaCreature.name} -
-
- - - - - - -
- {lavaSeaCreature.amount} Kills -
-
-
- {/each} -
-
-
+ {#if fishing.lavaSeaCreatures} + {#if Object.entries(fishing.lavaSeaCreatures).find(([_, lavaSeaCreature]) => (lavaSeaCreature.amount ?? 0) > 0)} + {@render creaturesDisplay("Lava Sea Creatures", fishing.lavaSeaCreatures)} + {/if} {/if} - {/if} - {#if fishing.trophyFish != null && (fishing.trophyFish.totalCaught ?? 0) > 0} - - - - Trophy Fish - - -
- {#if fishing.trophyFish} - - {#if fishing.trophyFish.stage && fishing.trophyFish.stage.name} - -
- {#each fishing.trophyFish.stage.progress as tier, index (index)} - {#if tier.tier} - - {/if} - {/each} -
-
+ {#if fishing.trophyFish != null && (fishing.trophyFish.totalCaught ?? 0) > 0} + + Trophy Fish + +
+ {#if fishing.trophyFish} + + {#if fishing.trophyFish.stage && fishing.trophyFish.stage.name} + +
    + {#each fishing.trophyFish.stage.progress as tier, index (index)} + {#if tier.tier} +
  • + {titleCase(tier.tier)}: + {tier.caught} / {tier.total} +
  • + {/if} + {/each} +
+
+ {/if} {/if} - {/if} -
+
- {#if fishing.trophyFish && fishing.trophyFish.trophyFish} - {@const trophyFishes = Object.entries(fishing.trophyFish.trophyFish)} + {#if fishing.trophyFish && fishing.trophyFish.trophyFish} + {const trophyFishes = Object.entries(fishing.trophyFish.trophyFish)} + - - {@const colors = { - bronze: { - bg: "bg-[oklch(55.23%_0.1295_59.21)]", - text: "text-[oklch(55.23%_0.1295_59.21)]/80" - }, - silver: { - bg: "bg-[oklch(77.02%_0.0014_286.37)]", - text: "text-[oklch(77.02%_0.0014_286.37)]/80" - }, - gold: { - bg: "bg-[oklch(82.61%_0.1706_80.88)]", - text: "text-[oklch(82.61%_0.1706_80.88)]/80" - }, - diamond: { - bg: "bg-[oklch(87.66%_0.1178_208.16)]", - text: "text-[oklch(87.66%_0.1178_208.16)]/80" - } - } satisfies ColorSchema} - {#each trophyFishes as [_, trophyFish], index (index)} - {@const highestTier = tiers.find((tier) => (trophyFish[tier] ?? 0) > 0)} - {@const highestTierColor = highestTier ? colors[highestTier].text : "text-text/60"} - -
-
-

{trophyFish.name} x{format((trophyFish.bronze ?? 0) + (trophyFish.silver ?? 0) + (trophyFish.gold ?? 0) + (trophyFish.diamond ?? 0))}

-
-
-
-
- {format(trophyFish.bronze)} -
-
-
- {format(trophyFish.silver)} + + {#each trophyFishes as [_, trophyFish], index (index)} + {const highestTier = tiers.find((tier) => (trophyFish[tier] ?? 0) > 0)} + {const highestTierColor = highestTier ? colors[highestTier].text : "text-text/60"} + +
+
+

{trophyFish.name} x{format((trophyFish.bronze ?? 0) + (trophyFish.silver ?? 0) + (trophyFish.gold ?? 0) + (trophyFish.diamond ?? 0))}

-
-
- {format(trophyFish.gold)} -
-
-
- {format(trophyFish.diamond)} +
+
+
+ {format(trophyFish.bronze)} +
+
+
+ {format(trophyFish.silver)} +
+
+
+ {format(trophyFish.gold)} +
+
+
+ {format(trophyFish.diamond)} +
-
- {#snippet tooltip()} - {#if trophyFish.description} -
- {@html renderLore(trophyFish.description, true, undefined, { breakSpaces: true })} -
- {/if} - {/snippet} -
- {/each} - - {/if} - - - {/if} + {#snippet tooltip()} + {#if trophyFish.description} +
+ {@html renderLore(trophyFish.description, true, undefined, { breakSpaces: true })} +
+ {/if} + {/snippet} + + {/each} +
+ {/if} + + + {/if} +
{:else} -

This player doesn't have anything related to fishing.

+ {/if} + +{#snippet creaturesDisplay(title: string, creaturesList: ModelsKill[])} + + {title} + + + {const creatures = Object.entries(creaturesList)} + + {#each creatures as [_, creature], index (index)} +
+
+ {creature.name} +
+
+ + + + + + +
+ {creature.amount} Kills +
+
+
+ {/each} +
+
+
+{/snippet} diff --git a/src/lib/sections/stats/skills/foraging.svelte b/src/lib/sections/stats/skills/foraging.svelte index fda62faf6..4f00900fa 100644 --- a/src/lib/sections/stats/skills/foraging.svelte +++ b/src/lib/sections/stats/skills/foraging.svelte @@ -1,13 +1,16 @@ -Foraging - {#if foraging} -
- {#if foraging.whispers} - -
    - {#each Object.entries(foraging.whispers) as [type, amount], index (index)} - {#if amount != null} -
  • - -
  • +
    +
    + {#if foraging.whispers} + +
      + {#each Object.entries(foraging.whispers) as [type, amount], index (index)} + {#if amount != null} +
    • + {type}: + {format(amount ?? 0)} +
    • + {/if} + {/each} +
    +
    + {/if} + {#if foraging.hinaChapter} + + {/if} + {#if foraging.fishFamily} + = (foraging.fishFamily.total ?? 0)} /> + {/if} +
    +
    + Tree Gifts + {#if foraging.treeGift} + + {#each Object.entries(foraging.treeGift) as [name, data], index (index)} + {#if data != null} + {const hasMaxed = data.milestone === data.maxMilestone} + {const hasUnlocked = data.milestone} + +
    +
    + {name.replaceAll("_", " ").toLowerCase()} +
    + Level: + {format(data.milestone)} +
    +
    +
    +
    {/if} {/each} -
-
- {/if} - {#if foraging.hinaChapter} - - {/if} - {#if foraging.fishFamily} - = (foraging.fishFamily.total ?? 0)} /> - {/if} -
- - Tree Gifts - {#if foraging.treeGift} - - {#each Object.entries(foraging.treeGift) as [name, data], index (index)} - {#if data != null} - {@const hasMaxed = data.milestone === data.maxMilestone} - {@const hasUnlocked = data.milestone} - -
-
- {name.replaceAll("_", " ").toLowerCase()} -
- Level: - {format(data.milestone)} -
-
-
-
- {/if} - {/each} -
- {:else} -

This player doesn't have any tree gifts.

- {/if} + + {:else} + + {/if} +
- Foraging Tools - {#if foragingTools && foragingTools.tools && foragingTools.tools.length > 0} - - {#snippet text()} +
+ Foraging Tools + {#if foragingTools && foragingTools.tools && foragingTools.tools.length > 0}
{#if highestPriorityForagingTool && highestPriorityForagingTool.display_name}

@@ -80,48 +83,53 @@

{/if}
- {/snippet} - {#each foragingTools.tools as tool, index (index)} - - {/each} - - {:else} -

This player doesn't have any foraging tools.

- {/if} - - Heart of the Forest -
- {#if foraging.level?.level != null} - - {/if} - {#if foraging.tokens} - - {/if} - {#if foraging.cotf} - - {/if} - {#if foraging.selectedAxeAbility} - - {/if} -
- {#if foraging.hotf && foraging.hotf.length > 0} -
-
-
- {#each foraging.hotf as item, index (index)} - {#if item.display_name} -
- -
- {:else} -
- {/if} + + {#each foragingTools.tools as tool, index (index)} + {/each} -
+ + {:else} + + {/if} +
+ +
+ Heart of the Forest +
+ {#if foraging.level?.level != null} + + {/if} + {#if foraging.tokens} + + {/if} + {#if foraging.cotf} + + {/if} + {#if foraging.selectedAxeAbility} + + {/if}
- {/if} + + {#if foraging.hotf && foraging.hotf.length > 0} + +
+
+ {#each foraging.hotf as item, index (index)} + {#if item.display_name} +
+ +
+ {:else} +
+ {/if} + {/each} +
+
+
+ {/if} +
{:else} -

This player doesn't have anything related to foraging.

+ {/if} diff --git a/src/lib/sections/stats/skills/hunting.svelte b/src/lib/sections/stats/skills/hunting.svelte index 089156f8c..15d034e76 100644 --- a/src/lib/sections/stats/skills/hunting.svelte +++ b/src/lib/sections/stats/skills/hunting.svelte @@ -1,27 +1,21 @@ {#if hunting} - - {#snippet text()} -
+
+
+
= summary.maxUnlocked} /> = summary.maxSyphoned} />
- {/snippet} +
{#if hunting.shards} - { - event.stopPropagation(); - }} /> - {#if filteredShards.length === 0} -

No hunting shards match your search.

- {/if} - currentRarity, (value) => (selectedRarity = value as RarityTab)}> - - {#each rarityTabs as rarity (rarity)} - - {titleCase(rarity)} - - {/each} - - - {#each rarityTabs as rarity (rarity)} - {#if currentRarity === rarity} - - {#if visibleShards.length === 0} -

No {titleCase(rarity)} shards match your search.

- {:else} - - {#snippet viewportChildren()} -
- {#each visibleShards as shard, index (shard.shardId ?? `${shard.name}-${index}`)} - {@const hasMaxed = isMaxed(shard)} - {@const familyText = getFamilyText(shard)} - {@const rarityClass = getRarityClass(getShardRarity(shard), "text")} - -
-
-
{shard.name}
-
-
- Syphoned: - {format(shard.syphoned ?? 0)} / {format(shard.maxSyphon ?? 0)} -
-
- Owned: - {format(shard.owned ?? 0)} -
- {#if shard.abilityName} -
- Ability: - {shard.abilityName} - {#if shard.abilityLevel != null || shard.abilityMaxLevel != null} - ({shard.abilityLevel ?? 0}/{shard.abilityMaxLevel ?? 0}) - {/if} -
- {/if} - {#if familyText} -
- Family: - {familyText} -
- {/if} - {#if shard.capturedTimestamp} -
- Captured: - {formatDate(shard.capturedTimestamp, "dd MMMM yyyy 'at' HH:mm", { in: tz(Intl.DateTimeFormat().resolvedOptions().timeZone) })} -
- {/if} -
-
-
- {#snippet tooltip()} -
- {#each shard.lore ?? [] as lore, loreIndex (loreIndex)} - - {@html renderLore(lore, true, loreIndex)} - {/each} -
- {/snippet} -
- {/each} + [shard.name, shard.abilityName, getFamilyText(shard)]} itemKey={(shard, index) => shard.shardId ?? `${shard.name}-${index}`} emptyTitle="No items found" noResultsLabel="No shards match your search."> + {#snippet item(shard)} + {const hasMaxed = isMaxed(shard)} + {const familyText = getFamilyText(shard)} + {const rarityClass = getRarityClass(getShardRarity(shard), "text")} + +
+
+
{shard.name}
+
+
+ Syphoned: + {format(shard.syphoned ?? 0)} / {format(shard.maxSyphon ?? 0)} +
+
+ Owned: + {format(shard.owned ?? 0)} +
+ {#if shard.abilityName} +
+ Ability: + {shard.abilityName} + {#if shard.abilityLevel != null || shard.abilityMaxLevel != null} + ({shard.abilityLevel ?? 0}/{shard.abilityMaxLevel ?? 0}) + {/if}
- {/snippet} - - - - - - - {/if} - - {/if} - {/each} - + {/if} + {#if familyText} +
+ Family: + {familyText} +
+ {/if} + {#if shard.capturedTimestamp} +
+ Captured: + {formatDate(shard.capturedTimestamp, "dd MMMM yyyy 'at' HH:mm", { in: tz(Intl.DateTimeFormat().resolvedOptions().timeZone) })} +
+ {/if} +
+
+
+ {#snippet tooltip()} +
+ {#each shard.lore ?? [] as lore, loreIndex (loreIndex)} + + {@html renderLore(lore, true, loreIndex)} + {/each} +
+ {/snippet} +
+ {/snippet} +
{/if} - +
{:else} -

This player doesn't have anything related to hunting.

+ {/if} diff --git a/src/lib/sections/stats/skills/mining.svelte b/src/lib/sections/stats/skills/mining.svelte index 2759550d5..60bd610f5 100644 --- a/src/lib/sections/stats/skills/mining.svelte +++ b/src/lib/sections/stats/skills/mining.svelte @@ -8,7 +8,15 @@ import { renderLore } from "$lib/shared/helper"; import { animateObfuscatedText } from "$lib/shared/mc-text/obfuscated"; import { cn } from "$lib/shared/utils"; + import EmptyStat from "$src/lib/components/EmptyStat.svelte"; + import ScrollAreaItems from "$src/lib/components/ScrollAreaItems.svelte"; + import { Label } from "$ui/label"; + import { Separator } from "$ui/separator"; import { tz } from "@date-fns/tz"; + import AnvilIcon from "@lucide/svelte/icons/anvil"; + import CheckIcon from "@lucide/svelte/icons/check"; + import PickaxeIcon from "@lucide/svelte/icons/pickaxe"; + import XIcon from "@lucide/svelte/icons/x"; import { formatDate, formatDistanceToNowStrict } from "date-fns"; import { format } from "numerable"; import { cubicOut } from "svelte/easing"; @@ -20,240 +28,260 @@ const highestPriorityMiningTool = $derived(miningTools?.highest_priority_tool); -Mining Tools -{#if mining} - {#if miningTools && miningTools.tools && miningTools.tools.length > 0} - - {#snippet text()} -
- {#if highestPriorityMiningTool && highestPriorityMiningTool.display_name} -

- Active Tool: - {@html renderLore(highestPriorityMiningTool.display_name)} -

- {/if} -
- {/snippet} - {#each miningTools.tools as tool, index (index)} - - {/each} -
- {:else} -

This player doesn't have any mining tools.

- {/if} - - Dwarven Mines & Crystal Hollows -
- {#if mining.commissions} - {#if mining.commissions.milestone} - - {/if} - {#if mining.commissions.completions} - Commissions from achievements across profiles - {/if} - {/if} - {#if mining.crystalHollows} - {#if mining.crystalHollows.crystalHollowsLastAccess} - Date.now() - 5 * 60 * 60 * 1000 ? "Purchased" : "Expired"} asterisk={true}> - {@const passActive = mining.crystalHollows.crystalHollowsLastAccess > Date.now() - 5 * 60 * 60 * 1000} -

- Last purchased: - - {#if passActive} - {formatDistanceToNowStrict(mining.crystalHollows.crystalHollowsLastAccess, { - addSuffix: true, - in: tz(Intl.DateTimeFormat().resolvedOptions().timeZone) - })} - {:else} - {formatDate(mining.crystalHollows.crystalHollowsLastAccess, "dd MMMM yyyy 'at' HH:mm", { in: tz(Intl.DateTimeFormat().resolvedOptions().timeZone) })} - ({formatDistanceToNowStrict(mining.crystalHollows.crystalHollowsLastAccess, { - addSuffix: true, - in: tz(Intl.DateTimeFormat().resolvedOptions().timeZone) - })}) - {/if} - -

-
+
+ {#if mining} +
+ Mining Tools + {#if miningTools && miningTools.tools && miningTools.tools.length > 0} + {#if highestPriorityMiningTool && highestPriorityMiningTool.display_name} +

+ Active Tool: + {@html renderLore(highestPriorityMiningTool.display_name)} +

+ {/if} + + {#each miningTools.tools as tool, index (index)} + + {/each} + + {:else} + {/if} +
- - {@const placableCrystals = ["jade", "amber", "amethyst", "sapphire", "topaz"]} -

Crystals:

- {#if mining.crystalHollows.progress} - {#if mining.crystalHollows.progress.crystals} -
    - {#each Object.entries(mining.crystalHollows.progress.crystals).filter(([crystalName, _crystalStatus]) => placableCrystals.includes(crystalName)) as [crystalName, crystalStatus], index (index)} -
  • - - - {crystalName}: - - {crystalStatus.replace("_", " ").toLowerCase()} - - -
  • - {/each} -
- -

Other Crystals:

-
    - {#each Object.entries(mining.crystalHollows.progress.crystals).filter(([crystalName, _crystalStatus]) => !placableCrystals.includes(crystalName)) as [crystalName, crystalStatus], index (index)} -
  • - - - {crystalName}: - - {crystalStatus.replace("_", " ").toLowerCase()} - - -
  • - {/each} -
+
+ Dwarven Mines & Crystal Hollows +
+ {#if mining.commissions} + {#if mining.commissions.milestone} + {/if} - - {#if mining.crystalHollows.progress.parts} -

Precursor parts delivered:

-
    - {#each Object.entries(mining.crystalHollows.progress.parts) as [partName, partStatus], index (index)} - {@const delivered = partStatus === "DELIVERED"} -
  • - {delivered ? "✔" : "✖"} - {#if partName.startsWith("FTX")} - {partName.replace("_", " ")} - {:else} - {partName.replace("_", " ").toLowerCase()} - {/if} -
  • - {/each} -
+ {#if mining.commissions.completions} + Commissions from achievements across profiles {/if} {/if} -
- {/if} -
- - Heart of the Mountain -
- {#if mining.level?.level != null} - - {/if} - {#if mining.tokens} - - {/if} - {#if mining.peakOfTheMountain} - - {/if} - {#if mining.powder} - {#each Object.keys(mining.powder) as key, index (index)} - {@const value = mining.powder[key as keyof typeof mining.powder]} - {#if value} - -
    - {#each Object.entries(value) as [type, amount], index (index)} - {#if amount != null} -
  • - -
  • + {#if mining.crystalHollows} + {#if mining.crystalHollows.crystalHollowsLastAccess} + Date.now() - 5 * 60 * 60 * 1000 ? "Purchased" : "Expired"} asterisk={true}> + {const passActive = mining.crystalHollows.crystalHollowsLastAccess > Date.now() - 5 * 60 * 60 * 1000} +
+ +
+ {/if} + + + {const placableCrystals = ["jade", "amber", "amethyst", "sapphire", "topaz"]} + + {#if mining.crystalHollows.progress} + {#if mining.crystalHollows.progress.crystals} + +
    + {#each Object.entries(mining.crystalHollows.progress.crystals).filter(([crystalName, _crystalStatus]) => placableCrystals.includes(crystalName)) as [crystalName, crystalStatus], index (index)} +
  • + + {crystalName}: + + {crystalStatus.replace("_", " ").toLowerCase()} + + +
  • + {/each} +
+ + + +
    + {#each Object.entries(mining.crystalHollows.progress.crystals).filter(([crystalName, _crystalStatus]) => !placableCrystals.includes(crystalName)) as [crystalName, crystalStatus], index (index)} +
  • + + {crystalName}: + + {crystalStatus.replace("_", " ").toLowerCase()} + + +
  • + {/each} +
+ {/if} + {#if mining.crystalHollows.progress.crystals && mining.crystalHollows.progress.parts} + + {/if} + + {#if mining.crystalHollows.progress.parts} + +
    + {#each Object.entries(mining.crystalHollows.progress.parts) as [partName, partStatus], index (index)} + {const delivered = partStatus === "DELIVERED"} + +
  • + {#if delivered} + + {:else} + + {/if} + {#if partName.startsWith("FTX")} + {partName.replace("_", " ")} + {:else} + {partName.replace("_", " ").toLowerCase()} + {/if} +
  • + {/each} +
+ {/if} + {/if}
{/if} - {/each} - {/if} - {#if mining.selectedPickaxeAbility} - - {/if} -
+
+
- {#if mining.hotm && mining.hotm.length > 0} -
-
-
- {#each mining.hotm as item, index (index)} - {#if item.display_name} -
- -
- {:else} -
+
+ Heart of the Mountain +
+ {#if mining.level?.level != null} + + {/if} + {#if mining.tokens} + + {/if} + {#if mining.peakOfTheMountain} + + {/if} + {#if mining.powder} + {#each Object.keys(mining.powder) as key, index (index)} + {const value = mining.powder[key as keyof typeof mining.powder]} + {#if value} + +
    + {#each Object.entries(value) as [type, amount], index (index)} + {#if amount != null} +
  • + {type}: + + {format(amount ?? 0)} + +
  • + {/if} + {/each} +
+
{/if} {/each} -
+ {/if} + {#if mining.selectedPickaxeAbility} + + {/if}
- {/if} - {#if mining.glaciteTunnels} - Glacite Tunnels -
- {#if mining.glaciteTunnels.mineshaftsEntered != null} - - {/if} - - {#if mining.glaciteTunnels.fossils} - - {/if} - {#if mining.glaciteTunnels.fossils} - - {#each mining.glaciteTunnels.fossils.fossils as fossil, index (index)} - {@const hasFound = fossil.found} - -
-
- {fossil.name} -
+ {#if mining.hotm && mining.hotm.length > 0} + +
+
+ {#each mining.hotm as item, index (index)} + {#if item.display_name} +
+
- {#snippet tooltip()} -
- {fossil.found ? "Found" : "Not Found"} -
- {/snippet} - + {:else} +
+ {/if} {/each} - - {/if} - +
+
+
+ {/if} - - {#if mining.glaciteTunnels.corpses} - + {#if mining.glaciteTunnels} +
+ Glacite Tunnels +
+ {#if mining.glaciteTunnels.mineshaftsEntered != null} + + {/if} + + + {#if mining.glaciteTunnels.fossils} + + {/if} + {#if mining.glaciteTunnels.fossils} + + {#each mining.glaciteTunnels.fossils.fossils as fossil, index (index)} + {const hasFound = fossil.found} + +
+
+ {fossil.name} +
+
+ {#snippet tooltip()} +
+ {fossil.found ? "Found" : "Not Found"} +
+ {/snippet} +
+ {/each} +
+ {/if} +
+ + + {#if mining.glaciteTunnels.corpses} + - - {#each mining.glaciteTunnels.corpses.corpses as corpse, index (index)} - {@const hasUnlocked = corpse.amount} - -
-
- {corpse.name} -
- Amount: - {format(corpse.amount)} + + {#each mining.glaciteTunnels.corpses.corpses as corpse, index (index)} + {const hasUnlocked = corpse.amount} + +
+
+ {corpse.name} +
+ Amount: + {format(corpse.amount)} +
+
-
-
- - {/each} - - {/if} - -
- {/if} +
+ {/each} +
+ {/if} +
+
+
+ {/if} - {#if mining.forge} - Forge -
- {#if mining.forge.length === 0} - No items currently forging! - {/if} - {#each mining.forge as item, index (index)} - {#if item.endingTime != null} - {@const ended = item.endingTime < Date.now()} - - {formatDate(item.endingTime, "dd MMMM yyyy 'at' HH:mm")} - - {/if} - {/each} -
+ {#if mining.forge} +
+ Forge +
+ {#if mining.forge.length === 0} + + {/if} + {#each mining.forge as item, index (index)} + {#if item.endingTime != null} + {const ended = item.endingTime < Date.now()} + + {formatDate(item.endingTime, "dd MMMM yyyy 'at' HH:mm")} + + {/if} + {/each} +
+
+ {/if} + {:else} + {/if} -{:else} -

This player doesn't have anything related to mining.

-{/if} +
diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 08d273582..b56d135ed 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -170,7 +170,7 @@ {/snippet} {#snippet failed()}{/snippet} - {@const newsroom = await listPosts({ page: 1, limit: 3 })} + {const newsroom = await listPosts({ page: 1, limit: 3 })} {#if newsroom.docs.length > 0}
From add1bfe4d23155ec89c9efab6ff2eb07386e145d Mon Sep 17 00:00:00 2001 From: DarthGigi <47110839+DarthGigi@users.noreply.github.com> Date: Tue, 16 Jun 2026 16:29:12 +0200 Subject: [PATCH 10/11] chore: remove unused Minecraft font buffer from asset initialization --- src/routes/stats/[ign]/[[profile]]/card/+server.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/routes/stats/[ign]/[[profile]]/card/+server.ts b/src/routes/stats/[ign]/[[profile]]/card/+server.ts index 32fde4610..f4ad22d09 100644 --- a/src/routes/stats/[ign]/[[profile]]/card/+server.ts +++ b/src/routes/stats/[ign]/[[profile]]/card/+server.ts @@ -118,14 +118,12 @@ async function initializeAssets() { // prettier-ignore montserratNormalBuffer, minecraftFontBuffer, - minecraftUpperFontBuffer, skycryptLogo, skycryptBackground ] = await Promise.all([ // prettier-ignore fetch(`${baseUrl}/fonts/montserrat/montserrat-normal.woff2`).then((res) => res.arrayBuffer()), fetch(`${baseUrl}/fonts/minecraft/MinecraftSevenv2-Regular.woff2`).then((res) => res.arrayBuffer()), - fetch(`${baseUrl}/fonts/minecraft/MinecraftTenv2-Regular.woff2`).then((res) => res.arrayBuffer()), fetch(`${baseUrl}/favicon.png`).then((res) => res.arrayBuffer()), fetch(`${baseUrl}/img/bg.png`).then((res) => res.arrayBuffer()) ]); @@ -138,10 +136,6 @@ async function initializeAssets() { { name: "Minecraft", data: minecraftFontBuffer - }, - { - name: "Minecraft-Upper", - data: minecraftUpperFontBuffer } ]; From 1989097dba2c98b10b097f5021633798eed49d00 Mon Sep 17 00:00:00 2001 From: DarthGigi <47110839+DarthGigi@users.noreply.github.com> Date: Tue, 16 Jun 2026 16:29:37 +0200 Subject: [PATCH 11/11] fix: disable themes for now --- src/lib/shared/themes/engine.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib/shared/themes/engine.ts b/src/lib/shared/themes/engine.ts index 77db4e9f3..abd3d406d 100644 --- a/src/lib/shared/themes/engine.ts +++ b/src/lib/shared/themes/engine.ts @@ -65,6 +65,8 @@ export class ThemeEngine { root.classList.remove("light"); root.classList.add("dark"); } + // TODO: Enable themes + return; for (const [key, cssVar] of Object.entries(COLOR_CSS_MAP)) { const value = theme.colors?.[key as ThemeColorKey];