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/.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/.prettierrc b/.prettierrc index 0f2cb621a..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/app.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/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/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/app.css b/src/app.css deleted file mode 100644 index 9d4ac0038..000000000 --- a/src/app.css +++ /dev/null @@ -1,422 +0,0 @@ -@import "tailwindcss"; -@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 *)); - -@plugin "tailwindcss-motion"; - -@theme { - /* Colors */ - --color-icon: var(--icon); - --color-link: var(--link); - --color-hover: var(--hover); - --color-skillbar: var(--skillbar); - --color-maxedbar: var(--maxedbar); - --color-maxed: var(--maxed); - --color-gold: var(--gold); - --color-text: var(--text); - --color-background: var(--background); - --color-background-grey: var(--grey_background); - --color-background-lore: var(--lore_background); - --color-header: var(--header); - --color-bg: var(--bg); - --color-logo: var(--logo); - --color-mctooltip-bg: var(--mctooltip-bg); - - /* Text Shadow */ - --text-shadow-sm: 0 0px 2px var(--tw-shadow-color); - --text-shadow-md: 0 0px 4px var(--tw-shadow-color); - --text-shadow-lg: 0 0px 8px var(--tw-shadow-color); - --tw-shadow-color: --alpha(var(--color-background) / 50%); - - /* Animations */ - --animate-shine: shine 4s infinite; - --animate-spin-slow: spin 3s linear infinite; - --animate-chroma: chroma-bg 40000s linear infinite; - - @keyframes shine { - 0% { - transform: translateY(120%); - } - 33%, - 100% { - transform: translateY(-120%); - } - } - - @keyframes chroma-bg { - from { - background-position-x: 0; - } - - to { - background-position-x: 999999px; - } - } - - /* 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); -} - -@theme inline { - --color-minecraft-0: var(--§0); - --color-minecraft-1: var(--§1); - --color-minecraft-2: var(--§2); - --color-minecraft-3: var(--§3); - --color-minecraft-4: var(--§4); - --color-minecraft-5: var(--§5); - --color-minecraft-6: var(--§6); - --color-minecraft-7: var(--§7); - --color-minecraft-8: var(--§8); - --color-minecraft-9: var(--§9); - --color-minecraft-a: var(--§a); - --color-minecraft-b: var(--§b); - --color-minecraft-c: var(--§c); - --color-minecraft-d: var(--§d); - --color-minecraft-e: var(--§e); - --color-minecraft-f: var(--§f); -} - -@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-style: normal; - font-display: block; - 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; - } - - @font-face { - font-family: "Minecraft"; - src: url("/fonts/minecraft/MinecraftSevenv2-Regular.woff2") format("woff2"); - font-weight: normal; - font-style: normal; - 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); - - /* Link Green (used for Links, Unclaimed Slayers, Crafted Minions etc.) */ - --link: oklch(81.56% 0.2459 146.24); - - /* Hover Green (used only for link hovers) */ - --hover: oklch(83.81% 0.2303 149.89); - - /* Skill Bar Green (used for Skill Progress Bars) */ - --skillbar: oklch(63.98% 0.1731 150.18); - - /* Maxed Bar Gold (used for Maxed Progress Bars) */ - --maxedbar: oklch(69.69% 0.1423 76.74); - - /* Maxed Gold (used for Maxed things etc.) */ - --maxed: oklch(72.84% 0.1506 75.86); - - /* Golden Text (used for Golden Text) */ - --gold: oklch(82.84% 0.1548 78.27); - - /* Header Logo */ - --logo: oklch(68.48% 0.2338 351.45); - - /* 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 */ - --grey_background: oklch(0.24 0 0); - /* used for item lore */ - --lore_background: oklch(0.17 0 0 / 0.9); - - /* used when --bg can't be used */ - --bg: oklch(0.18 0 0); - - /* Normal Background */ - --bg-url: url(/img/bg.avif); - - /* Minecraft Tooltip */ - --mctooltip-bg: oklch(12.142% 0.05582 328.352 / 0.93); - - /* Minecraft color codes (nice-dark palette) */ - --§0: oklch(0 0 0); - --§1: oklch(0.32 0.14 264.6); - --§2: oklch(0.64 0.22 142.5); - --§3: oklch(0.58 0.1 194.78); - --§4: oklch(0.42 0.17 28.49); - --§5: oklch(0.5 0.23 328.34); - --§6: oklch(0.71 0.15 72.75); - --§7: oklch(0.5 0 0); - --§8: oklch(0.31 0 0); - --§9: oklch(0.51 0.25 273.16); - --§a: oklch(0.7 0.2 143.13); - --§b: oklch(0.69 0.11 211.66); - --§c: oklch(0.56 0.17 24.75); - --§d: oklch(0.7 0.19 338.3); - --§e: oklch(0.84 0.17 93.53); - --§f: oklch(0.66 0 0); - - color-scheme: dark; - } - - ::-webkit-scrollbar { - width: 10px; - } - - ::-webkit-scrollbar-thumb { - background-color: var(--icon); - border-radius: 5px; - } - - ::-webkit-scrollbar-track { - background-color: transparent; - } - - *:focus-visible { - outline: var(--color-skillbar) auto 1px; - } - - *::selection { - background-color: var(--color-link); - color: var(--color-text); - text-shadow: var(--text-shadow-lg); - } - - *::target-text { - background-color: var(--color-skillbar); - color: var(--color-text); - text-shadow: var(--text-shadow-md); - } - - ::view-transition-group(root) { - animation-duration: 0.7s; - animation-timing-function: ease-out; - } - - ::view-transition-new(root) { - animation-name: reveal; - animation-fill-mode: both; - } - - ::view-transition-old(root) { - animation: none; - animation-fill-mode: both; - z-index: -1; - } - - @keyframes reveal { - from { - clip-path: polygon(50% -71%, -50% 71%, -50% 71%, 50% -71%); - } - to { - clip-path: polygon(50% -71%, -50% 71%, 50% 171%, 171% 50%); - } - } -} - -@layer components { - .virtual-list-wrapper { - @apply overflow-x-hidden overflow-y-auto; - } - - .virtual-list-inner { - @apply overflow-x-auto overflow-y-clip; - } - - .lore-enchantment { - @apply group-data-[rainbow=false]/html:text-minecraft-6! group-data-[rainbow=true]/html:chroma-gradient; - } - - [data-tooltip-content] { - @apply text-sm text-pretty; - } - - [data-arrow] { - @apply text-background-grey; - } - - ::-webkit-color-swatch-wrapper { - padding: 0; - } - - ::-webkit-color-swatch { - border: none; - } -} - -@utility nice-colors-dark { - /* these colors look nice and have significant contrast with white */ - --§0: oklch(0 0 0); - --§1: oklch(0.32 0.14 264.6); - --§2: oklch(0.64 0.22 142.5); - --§3: oklch(0.58 0.1 194.78); - --§4: oklch(0.42 0.17 28.49); - --§5: oklch(0.5 0.23 328.34); - --§6: oklch(0.71 0.15 72.75); - --§7: oklch(0.5 0 0); - --§8: oklch(0.31 0 0); - --§9: oklch(0.51 0.25 273.16); - --§a: oklch(0.7 0.2 143.13); - --§b: oklch(0.69 0.11 211.66); - --§c: oklch(0.56 0.17 24.75); - --§d: oklch(0.7 0.19 338.3); - --§e: oklch(0.84 0.17 93.53); - --§f: oklch(0.66 0 0); -} - -@utility light { - --text: oklch(0 0 0); - --background: oklch(1 0 0); - --header: oklch(0.89 0 0); - --grey_background: oklch(0.92 0 0); - --lore_background: oklch(1 0 0 / 0.93); - - --bg: oklch(1 0 0) color-scheme: light; -} - -@utility shine { - @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 enchanted { - filter: url(#enchanted-glint); -} - -@utility enchanted-item { - filter: url(#enchanted-glint) drop-shadow(2px 2px 2px oklch(0 0 0 / 0.4)); -} - -@utility true-colors { - /* Minecraft color codes */ - --§0: oklch(0 0 0); - --§1: oklch(0.33 0.23 264.05); - --§2: oklch(0.64 0.22 142.5); - --§3: oklch(0.67 0.11 194.77); - --§4: oklch(0.46 0.19 29.23); - --§5: oklch(0.52 0.24 328.36); - --§6: oklch(0.8 0.17 73.27); - --§7: oklch(0.74 0 0); - --§8: oklch(0.45 0 0); - --§9: oklch(0.56 0.24 275.12); - --§a: oklch(0.88 0.25 143.06); - --§b: oklch(0.91 0.14 195.03); - --§c: oklch(0.68 0.21 24.43); - --§d: oklch(0.74 0.27 327.9); - --§e: oklch(0.97 0.18 109.38); - --§f: oklch(1 0 0); -} - -@utility april-fools-2024 { - --§0: oklch(0.65 0.26 356.94); - --§1: oklch(0.66 0.23 35.4); - --§2: oklch(0.66 0.28 347.13); - --§3: oklch(0.66 0.24 4.74); - --§4: oklch(0.28 0.1 10.33); - --§5: oklch(0.72 0.14 356.27); - --§6: oklch(0.65 0.16 357.22); - --§7: oklch(0.67 0.24 357.79); - --§8: oklch(0.62 0.18 334.19); - --§9: oklch(0.83 0.09 357.41); - --§a: oklch(0.91 0.04 355.91); - --§b: oklch(0.44 0.15 4.7); - --§c: oklch(0.28 0.1 10.33); - --§d: oklch(0.55 0.16 0.51); - --§e: oklch(0.73 0.2 351.99); - --§f: oklch(0.97 0.01 350.09); -} - -@utility nice-colors-light { - /* these colors look nice and have significant contrast with black */ - --§0: oklch(0.54 0 0); - --§1: oklch(0.5 0.28 269.85); - --§2: oklch(0.66 0.23 142.5); - --§3: oklch(0.71 0.12 185.91); - --§4: oklch(0.5 0.19 27.28); - --§5: oklch(0.66 0.3 328.31); - --§6: oklch(0.8 0.17 73.27); - --§7: oklch(0.78 0 0); - --§8: oklch(0.68 0 0); - --§9: oklch(0.66 0.16 273.97); - --§a: oklch(0.79 0.2 143.36); - --§b: oklch(0.81 0.11 211.69); - --§c: oklch(0.68 0.2 24.09); - --§d: oklch(0.74 0.23 336.42); - --§e: oklch(0.94 0.16 109.12); - --§f: oklch(1 0 0); -} - -@utility chroma-gradient { - @apply relative animate-chroma bg-size-[8.875rem_8.875rem] bg-clip-text bg-origin-padding text-transparent!; - background-image: repeating-linear-gradient(-45deg, oklch(62.8% 0.258 29.2), oklch(77.2% 0.174 64.6), oklch(93.1% 0.229 123), oklch(87% 0.29 142), oklch(87.2% 0.255 148), oklch(90.5% 0.155 195), oklch(56.3% 0.241 261), oklch(46.6% 0.304 271), oklch(62.7% 0.307 316), oklch(65.3% 0.268 355), oklch(62.8% 0.258 29.2) 100px); -} - -@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)]; -} diff --git a/src/app.html b/src/app.html index 56e866700..a9f55664c 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/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/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/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 5d746ee50..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 = { @@ -39,22 +40,22 @@ { - 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 0d746c29d..1d11766e7 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..ffe705755 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}
- + @@ -53,7 +52,7 @@
{#if user.role} - {@const Icon = iconMapper[user.role]} + {const Icon = iconMapper[user.role]} - import { getPreferences } from "$ctx"; - import { cn } from "$lib/shared/utils"; - - const preferences = getPreferences(); -
+
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..efe7a5ab7 100644 --- a/src/lib/components/misc/Navbar.svelte +++ b/src/lib/components/misc/Navbar.svelte @@ -4,10 +4,11 @@ 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"; + import { Button } from "$ui/button"; + import { cn } from "$utils"; + import ArrowBigLeft from "@lucide/svelte/icons/arrow-big-left"; + import ArrowBigRight from "@lucide/svelte/icons/arrow-big-right"; + import { ScrollArea } from "bits-ui"; import { onDestroy, tick, type Snippet } from "svelte"; const { children }: { children?: Snippet } = $props(); @@ -137,19 +138,19 @@ {#snippet viewportChildren()} -
-
-
+
+
+
{#each filteredSectionOrderPreferences as section, index (index)} - handleSectionClick(section.name)}> + {/each}
{/snippet} - + @@ -158,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/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/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 061e2d0e5..ee09e6075 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/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 558bcd80f..a86ede782 100644 --- a/src/lib/components/stats/CardBuilder.svelte +++ b/src/lib/components/stats/CardBuilder.svelte @@ -1,10 +1,18 @@ {#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} @@ -179,39 +207,39 @@ {/snippet} {#snippet resetButton()} - + {/snippet} {#snippet imagePreview()} -
+
-

Preview

+
- + + +
- + {#if isImagePending}
{/if} - - Card Preview + + Card Preview
{/snippet} @@ -224,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()} +
@@ -254,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/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 @@ + + +
svg]:size-4 group-has-data-[size=lg]/avatar-group:[&>svg]:size-5 group-has-data-[size=sm]/avatar-group:[&>svg]:size-3 ring-background relative flex shrink-0 items-center justify-center ring-2", + className + )} + {...restProps} +> + {@render children?.()} +
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/layouts/stats/AdditionalStats.svelte b/src/lib/layouts/stats/AdditionalStats.svelte index 516acc580..74916e1d3 100644 --- a/src/lib/layouts/stats/AdditionalStats.svelte +++ b/src/lib/layouts/stats/AdditionalStats.svelte @@ -1,27 +1,27 @@ @@ -39,20 +39,20 @@ {/if} {#if profile.bank != null && profile.personalBank != null} -
-

+
+

+ {#if profile.personalBank} -

+

+ {/if}
@@ -60,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} @@ -99,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 a85ff6851..64eebee99 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,8 @@ {/if}
-
+
+
{#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 196caa3ab..42640c02c 100644 --- a/src/lib/layouts/stats/PlayerProfile.svelte +++ b/src/lib/layouts/stats/PlayerProfile.svelte @@ -1,21 +1,25 @@
{#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 d2968a621..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 e60c48e1c..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 fd9d86729..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 a2bff7861..7fddea195 100644 --- a/src/lib/sections/stats/farming/garden.svelte +++ b/src/lib/sections/stats/farming/garden.svelte @@ -1,99 +1,101 @@ - - - - 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} -
+
{gardenUpgrade.name}
@@ -104,19 +106,20 @@
{/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)} -
+
{gardenChip.name}
@@ -127,35 +130,43 @@
{/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} -
+
{mutation.name}
{/each} - +
{/if} -
+ + +
{@render milestones(garden)}
-
+ + +
{@render upgrades(garden)}
-
+ + +
{/if} @@ -167,20 +178,21 @@ {#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} -
+
{upgrade.name} {upgrade.level?.level} @@ -188,26 +200,27 @@
{/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} -
+
{milestone.name} {milestone.level?.level} @@ -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 88ee7d1d4..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,14 +28,14 @@ {/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} -
+
{item.name}
@@ -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 26ed89c71..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 5c5757341..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/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 ? "!" : ""}` : ""; } /** 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]; 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/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; diff --git a/src/routes/+error.svelte b/src/routes/+error.svelte index e38e56974..55159e733 100644 --- a/src/routes/+error.svelte +++ b/src/routes/+error.svelte @@ -1,14 +1,10 @@
-
+

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..68676f484 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"; @@ -23,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()); @@ -85,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(); @@ -209,7 +216,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!", @@ -234,7 +241,7 @@ {#if showNewsroomToast} {#snippet failed()}{/snippet} - {@const latestNewsroom = await listLatestPostsForNotifications({ limit: 5 })} + {const latestNewsroom = await listLatestPostsForNotifications({ limit: 5 })} {/if} @@ -244,7 +251,7 @@ {#if internalState.themeEditorOpen && !isMobile.current} -
+
{/if} diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index d2518fee0..b56d135ed 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)} -
+
@@ -173,10 +170,10 @@ {/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}
-
+

Newsroom

Latest announcements and updates

diff --git a/src/routes/layout.css b/src/routes/layout.css new file mode 100644 index 000000000..130c9132c --- /dev/null +++ b/src/routes/layout.css @@ -0,0 +1,751 @@ +@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 (&: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"] *)); + +@plugin "tailwindcss-motion"; + +@theme { + /* Colors */ + --color-icon: var(--icon); + --color-link: var(--link); + --color-hover: var(--hover); + --color-skillbar: var(--primary); + --color-maxedbar: var(--maxedbar); + --color-maxed: var(--maxed); + --color-gold: var(--gold); + --color-text: var(--text); + --color-background: var(--background); + --color-background-grey: var(--grey_background); + --color-background-lore: var(--lore_background); + --color-header: var(--header); + --color-bg: var(--bg); + --color-logo: var(--logo); + --color-mctooltip-bg: var(--mctooltip-bg); + + /* Text Shadow */ + --text-shadow-sm: 0 0px 2px var(--tw-shadow-color); + --text-shadow-md: 0 0px 4px var(--tw-shadow-color); + --text-shadow-lg: 0 0px 8px var(--tw-shadow-color); + --tw-shadow-color: --alpha(var(--color-background) / 50%); + + /* Animations */ + --animate-shine: shine 4s infinite; + --animate-spin-slow: spin 3s linear infinite; + --animate-chroma: chroma-bg 40000s linear infinite; + + @keyframes shine { + 0% { + transform: translateY(120%); + } + 33%, + 100% { + transform: translateY(-120%); + } + } + + @keyframes chroma-bg { + from { + background-position-x: 0; + } + + to { + background-position-x: 999999px; + } + } + + /* Fonts */ + --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 { + --color-minecraft-0: var(--§0); + --color-minecraft-1: var(--§1); + --color-minecraft-2: var(--§2); + --color-minecraft-3: var(--§3); + --color-minecraft-4: var(--§4); + --color-minecraft-5: var(--§5); + --color-minecraft-6: var(--§6); + --color-minecraft-7: var(--§7); + --color-minecraft-8: var(--§8); + --color-minecraft-9: var(--§9); + --color-minecraft-a: var(--§a); + --color-minecraft-b: var(--§b); + --color-minecraft-c: var(--§c); + --color-minecraft-d: var(--§d); + --color-minecraft-e: var(--§e); + --color-minecraft-f: var(--§f); +} + +@layer base { + @font-face { + 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: + /* 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 { + font-family: "Minecraft"; + src: url("/fonts/minecraft/MinecraftSevenv2-Regular.woff2") format("woff2"); + font-weight: normal; + font-style: normal; + font-display: swap; + } + + /* 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: var(--chart-2); + + /* Link Green (used for Links, Unclaimed Slayers, Crafted Minions etc.) */ + --link: oklch(81.56% 0.2459 146.24); + + /* Hover Green (used only for link hovers) */ + --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: var(--primary); + + /* Maxed Bar Gold (used for Maxed Progress Bars) */ + --maxedbar: oklch(69.69% 0.1423 76.74); + + /* Maxed Gold (used for Maxed things etc.) */ + --maxed: oklch(72.84% 0.1506 75.86); + + /* Golden Text (used for Golden Text) */ + --gold: oklch(82.84% 0.1548 78.27); + + /* Header Logo */ + --logo: oklch(68.48% 0.2338 351.45); + + /* Most of the text */ + --text: oklch(1 0 0); + /* background of the header */ + --header: oklch(0.28 0 0); + /* used for info box and theme/pack selector */ + --grey_background: oklch(0.24 0 0); + /* used for item lore */ + --lore_background: oklch(0.17 0 0 / 0.9); + + /* used when --bg can't be used */ + --bg: oklch(0.18 0 0); + + /* Normal Background */ + --bg-url: url(/img/bg.avif); + + /* Minecraft Tooltip */ + --mctooltip-bg: oklch(12.142% 0.05582 328.352 / 0.93); + + /* Minecraft color codes (nice-dark palette) */ + --§0: oklch(0 0 0); + --§1: oklch(0.32 0.14 264.6); + --§2: oklch(0.64 0.22 142.5); + --§3: oklch(0.58 0.1 194.78); + --§4: oklch(0.42 0.17 28.49); + --§5: oklch(0.5 0.23 328.34); + --§6: oklch(0.71 0.15 72.75); + --§7: oklch(0.5 0 0); + --§8: oklch(0.31 0 0); + --§9: oklch(0.51 0.25 273.16); + --§a: oklch(0.7 0.2 143.13); + --§b: oklch(0.69 0.11 211.66); + --§c: oklch(0.56 0.17 24.75); + --§d: oklch(0.7 0.19 338.3); + --§e: oklch(0.84 0.17 93.53); + --§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 { + width: 10px; + } + + ::-webkit-scrollbar-thumb { + background-color: var(--icon); + border-radius: 5px; + } + + ::-webkit-scrollbar-track { + background-color: transparent; + } + + *:focus-visible { + outline: var(--color-skillbar) auto 1px; + } + + *::selection { + background-color: var(--color-link); + color: var(--color-text); + text-shadow: var(--text-shadow-lg); + } + + *::target-text { + background-color: var(--color-skillbar); + color: var(--color-text); + text-shadow: var(--text-shadow-md); + } + + ::view-transition-group(root) { + animation-duration: 0.7s; + animation-timing-function: ease-out; + } + + ::view-transition-new(root) { + animation-name: reveal; + animation-fill-mode: both; + } + + ::view-transition-old(root) { + animation: none; + animation-fill-mode: both; + z-index: -1; + } + + @keyframes reveal { + from { + clip-path: polygon(50% -71%, -50% 71%, -50% 71%, 50% -71%); + } + to { + 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 { + .virtual-list-wrapper { + @apply overflow-x-hidden overflow-y-auto; + } + + .virtual-list-inner { + @apply overflow-x-auto overflow-y-clip; + } + + .lore-enchantment { + @apply group-data-[rainbow=false]/html:text-minecraft-6! group-data-[rainbow=true]/html:chroma-gradient; + } + + [data-tooltip-content] { + @apply text-sm text-pretty; + } + + [data-arrow] { + @apply text-background-grey; + } + + ::-webkit-color-swatch-wrapper { + padding: 0; + } + + ::-webkit-color-swatch { + border: none; + } +} + +@utility nice-colors-dark { + /* these colors look nice and have significant contrast with white */ + --§0: oklch(0 0 0); + --§1: oklch(0.32 0.14 264.6); + --§2: oklch(0.64 0.22 142.5); + --§3: oklch(0.58 0.1 194.78); + --§4: oklch(0.42 0.17 28.49); + --§5: oklch(0.5 0.23 328.34); + --§6: oklch(0.71 0.15 72.75); + --§7: oklch(0.5 0 0); + --§8: oklch(0.31 0 0); + --§9: oklch(0.51 0.25 273.16); + --§a: oklch(0.7 0.2 143.13); + --§b: oklch(0.69 0.11 211.66); + --§c: oklch(0.56 0.17 24.75); + --§d: oklch(0.7 0.19 338.3); + --§e: oklch(0.84 0.17 93.53); + --§f: oklch(0.66 0 0); +} + +@utility light { + --text: oklch(0 0 0); + --background: oklch(1 0 0); + --header: oklch(0.89 0 0); + --grey_background: oklch(0.92 0 0); + --lore_background: oklch(1 0 0 / 0.93); + + --bg: oklch(1 0 0); + color-scheme: light; +} + +@utility shine { + @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); +} + +@utility enchanted-item { + filter: url(#enchanted-glint) drop-shadow(2px 2px 2px oklch(0 0 0 / 0.4)); +} + +@utility true-colors { + /* Minecraft color codes */ + --§0: oklch(0 0 0); + --§1: oklch(0.33 0.23 264.05); + --§2: oklch(0.64 0.22 142.5); + --§3: oklch(0.67 0.11 194.77); + --§4: oklch(0.46 0.19 29.23); + --§5: oklch(0.52 0.24 328.36); + --§6: oklch(0.8 0.17 73.27); + --§7: oklch(0.74 0 0); + --§8: oklch(0.45 0 0); + --§9: oklch(0.56 0.24 275.12); + --§a: oklch(0.88 0.25 143.06); + --§b: oklch(0.91 0.14 195.03); + --§c: oklch(0.68 0.21 24.43); + --§d: oklch(0.74 0.27 327.9); + --§e: oklch(0.97 0.18 109.38); + --§f: oklch(1 0 0); +} + +@utility april-fools-2024 { + --§0: oklch(0.65 0.26 356.94); + --§1: oklch(0.66 0.23 35.4); + --§2: oklch(0.66 0.28 347.13); + --§3: oklch(0.66 0.24 4.74); + --§4: oklch(0.28 0.1 10.33); + --§5: oklch(0.72 0.14 356.27); + --§6: oklch(0.65 0.16 357.22); + --§7: oklch(0.67 0.24 357.79); + --§8: oklch(0.62 0.18 334.19); + --§9: oklch(0.83 0.09 357.41); + --§a: oklch(0.91 0.04 355.91); + --§b: oklch(0.44 0.15 4.7); + --§c: oklch(0.28 0.1 10.33); + --§d: oklch(0.55 0.16 0.51); + --§e: oklch(0.73 0.2 351.99); + --§f: oklch(0.97 0.01 350.09); +} + +@utility nice-colors-light { + /* these colors look nice and have significant contrast with black */ + --§0: oklch(0.54 0 0); + --§1: oklch(0.5 0.28 269.85); + --§2: oklch(0.66 0.23 142.5); + --§3: oklch(0.71 0.12 185.91); + --§4: oklch(0.5 0.19 27.28); + --§5: oklch(0.66 0.3 328.31); + --§6: oklch(0.8 0.17 73.27); + --§7: oklch(0.78 0 0); + --§8: oklch(0.68 0 0); + --§9: oklch(0.66 0.16 273.97); + --§a: oklch(0.79 0.2 143.36); + --§b: oklch(0.81 0.11 211.69); + --§c: oklch(0.68 0.2 24.09); + --§d: oklch(0.74 0.23 336.42); + --§e: oklch(0.94 0.16 109.12); + --§f: oklch(1 0 0); +} + +@utility chroma-gradient { + @apply relative animate-chroma bg-size-[8.875rem_8.875rem] bg-clip-text bg-origin-padding text-transparent!; + background-image: repeating-linear-gradient(-45deg, oklch(62.8% 0.258 29.2), oklch(77.2% 0.174 64.6), oklch(93.1% 0.229 123), oklch(87% 0.29 142), oklch(87.2% 0.255 148), oklch(90.5% 0.155 195), oklch(56.3% 0.241 261), oklch(46.6% 0.304 271), oklch(62.7% 0.307 316), oklch(65.3% 0.268 355), oklch(62.8% 0.258 29.2) 100px); +} + +@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; + } + } +} 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... diff --git a/src/routes/stats/[ign]/[[profile]]/card/+server.ts b/src/routes/stats/[ign]/[[profile]]/card/+server.ts index 4a25e5b82..f4ad22d09 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"; @@ -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 } ]; 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 63df20ab4..000000000 Binary files a/static/fonts/icomoon/icomoon.ttf and /dev/null differ diff --git a/static/fonts/icomoon/icomoon.woff b/static/fonts/icomoon/icomoon.woff deleted file mode 100644 index 02f7b8fcb..000000000 Binary files a/static/fonts/icomoon/icomoon.woff and /dev/null differ diff --git a/static/fonts/icomoon/icomoon.woff2 b/static/fonts/icomoon/icomoon.woff2 deleted file mode 100644 index 54494bbc4..000000000 Binary files a/static/fonts/icomoon/icomoon.woff2 and /dev/null differ 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 a75a8ed40..000000000 Binary files a/static/fonts/minecraft/MinecraftTenv2-Regular.woff2 and /dev/null differ diff --git a/static/fonts/montserrat/montserrat-italic.woff2 b/static/fonts/montserrat/montserrat-italic.woff2 deleted file mode 100644 index b0cfe1fc0..000000000 Binary files a/static/fonts/montserrat/montserrat-italic.woff2 and /dev/null differ diff --git a/static/fonts/montserrat/montserrat-normal.woff2 b/static/fonts/montserrat/montserrat-normal.woff2 index 61220a0f6..3b2eaa95e 100644 Binary files a/static/fonts/montserrat/montserrat-normal.woff2 and b/static/fonts/montserrat/montserrat-normal.woff2 differ 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: {