Skip to content

Commit

Permalink
Merge pull request #81 from SkyCryptWebsite/dev
Browse files Browse the repository at this point in the history
  • Loading branch information
DarthGigi authored Jan 9, 2025
2 parents 61f47e4 + 235b263 commit f47cdae
Show file tree
Hide file tree
Showing 8 changed files with 1,084 additions and 504 deletions.
18 changes: 9 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
},
"devDependencies": {
"@eslint/js": "^9.17.0",
"@sveltejs/kit": "^2.15.1",
"@sveltejs/kit": "^2.15.2",
"@sveltejs/vite-plugin-svelte": "^5.0.3",
"@types/compression": "^1.7.5",
"@types/eslint": "^9.6.1",
Expand All @@ -44,8 +44,8 @@
"prettier": "^3.4.2",
"prettier-plugin-svelte": "^3.3.2",
"prettier-plugin-tailwindcss": "^0.6.9",
"svelte": "5.16.1",
"svelte-check": "^4.1.1",
"svelte": "5.17.3",
"svelte-check": "^4.1.3",
"svelte-interactions": "^0.2.0",
"svelte-preprocess": "^6.0.3",
"svelte-seo": "^1.6.1",
Expand All @@ -54,8 +54,8 @@
"tailwind-merge": "^2.6.0",
"tailwindcss": "^3.4.17",
"tslib": "^2.8.1",
"typescript": "^5.7.2",
"typescript-eslint": "^8.19.0",
"typescript": "^5.7.3",
"typescript-eslint": "^8.19.1",
"vaul-svelte": "1.0.0-next.3",
"vite": "^6.0.7"
},
Expand All @@ -71,7 +71,7 @@
"fs-extra": "^11.2.0",
"lodash": "^4.17.21",
"micromatch": "^4.0.8",
"minecraft-data": "^3.80.1",
"minecraft-data": "^3.83.1",
"mongo-sanitize": "^1.1.0",
"mongodb": "^6.12.0",
"os": "^0.1.2",
Expand All @@ -83,12 +83,12 @@
"sharp": "^0.33.5",
"simple-git": "^3.27.0",
"skinview3d": "^3.1.0",
"skyhelper-networth": "^1.27.0",
"skyhelper-networth": "^1.27.1",
"svelte-persisted-store": "^0.12.0",
"sveltekit-superforms": "^2.22.1",
"upng-js": "^2.1.0",
"util": "^0.12.5",
"uuid": "^11.0.3",
"uuid": "^11.0.4",
"zod": "^3.24.1"
},
"engines": {
Expand Down Expand Up @@ -117,6 +117,6 @@
}
},
"optionalDependencies": {
"@rollup/rollup-linux-x64-gnu": "^4.29.1"
"@rollup/rollup-linux-x64-gnu": "^4.30.1"
}
}
1,245 changes: 894 additions & 351 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

7 changes: 4 additions & 3 deletions src/lib/components/ContainedItem.svelte
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
<script lang="ts">
import { cn } from "$lib/shared/utils";
import type { ProcessedSkyBlockItem } from "$lib/types/global";
import { Avatar } from "bits-ui";
import Image from "lucide-svelte/icons/image";
let { piece }: { piece: ProcessedSkyBlockItem } = $props();
let { piece, isInventory }: { piece: ProcessedSkyBlockItem; isInventory?: boolean } = $props();
</script>

<div class="data-[enchanted=true]:shine relative flex aspect-square items-center justify-center overflow-clip rounded-lg p-0" data-enchanted={piece.shiny}>
<Avatar.Root>
<Avatar.Image loading="lazy" src={piece.texture_path} alt={piece.display_name} class="group-data-[enchanted=true]:enchanted h-auto w-14 select-none" />
<Avatar.Image loading="lazy" src={piece.texture_path} alt={piece.display_name} class={cn("group-data-[enchanted=true]:enchanted h-auto w-14 select-none", isInventory ? "w-8" : "w-14")} />
<Avatar.Fallback>
<Image class="size-8" />
<Image class={cn(isInventory ? "size-8" : "size-14")} />
</Avatar.Fallback>
</Avatar.Root>
</div>
169 changes: 29 additions & 140 deletions src/lib/components/Item.svelte
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
<script lang="ts">
import { page } from "$app/stores";
import ContainedItem from "$lib/components/ContainedItem.svelte";
import type { IsHover } from "$lib/hooks/is-hover.svelte";
import { RARITIES, RARITY_COLORS } from "$lib/shared/constants/items";
import { packConfigs } from "$lib/shared/constants/packs";
import { getRarityClass, removeFormatting, renderLore } from "$lib/shared/helper";
import { getRarityClass } from "$lib/shared/helper";
import { cn, flyAndScale } from "$lib/shared/utils";
import { itemContent, showItem } from "$lib/stores/internal";
import type { ProcessedSkyBlockItem, ProcessedSkyblockPet } from "$lib/types/global";
import { Avatar, Button, Dialog, Tooltip } from "bits-ui";
import { Avatar, Tooltip } from "bits-ui";
import Image from "lucide-svelte/icons/image";
import { getContext } from "svelte";
import { writable } from "svelte/store";
import { fade } from "svelte/transition";
import { Drawer } from "vaul-svelte";
import Content from "./item/item-content.svelte";
type Props = {
piece: ProcessedSkyBlockItem | ProcessedSkyblockPet;
Expand All @@ -24,150 +20,43 @@
let { piece, isInventory, showCount, showRecombobulated }: Props = $props();
const skyblockItem = $derived(piece as ProcessedSkyBlockItem);
const itemName = $derived(skyblockItem.display_name ?? "???");
const itemNameHtml = $derived(renderLore(itemName));
const isMulticolor = $derived((itemNameHtml.match(/<\/span>/g) || []).length > 1);
const bgColor = $derived(getRarityClass(piece.rarity ?? ("common".toLowerCase() as string), "bg"));
const recombobulated = $derived(showRecombobulated && (skyblockItem.recombobulated ?? false));
const enchanted = $derived(skyblockItem.shiny);
const shine = $derived(enchanted || skyblockItem.shiny);
const packData = $derived(packConfigs.find((pack) => pack.id === skyblockItem.texture_pack));
const showNumbers = $derived(showCount && (skyblockItem.Count ?? 0) > 1);
const showDialog = writable<boolean>(false);
const showDialogDelayed = writable<boolean>(false);
const isHover = getContext<IsHover>("isHover");
showDialog.subscribe((value) => {
setTimeout(() => showDialogDelayed.set(value), 0);
});
showDialogDelayed.subscribe((value) => {
if (!value) setTimeout(() => showDialog.set(value), 300);
});
</script>

{#snippet itemContents(isDrawer: boolean = false)}
<div class={cn(`nice-colors-dark flex flex-nowrap items-center justify-center gap-4 p-5`, { "rounded-t-[10px]": isDrawer }, bgColor)}>
<Avatar.Root class="shrink-0 px-2">
<Avatar.Image loading="lazy" src={$page.url.origin + piece.texture_path} alt={piece.display_name} class="data-[enchanted=true]:enchanted h-auto w-8 flex-none shrink-0 overflow-hidden [image-rendering:pixelated]" data-enchanted={enchanted} />
<Avatar.Fallback>
<Image class="size-8" />
</Avatar.Fallback>
</Avatar.Root>

<p class="relative text-wrap text-center text-base font-semibold uppercase data-[multicolor=true]:rounded-full data-[multicolor=true]:bg-background-lore data-[multicolor=true]:px-2 data-[multicolor=true]:py-1 data-[multicolor=false]:text-text sm:text-lg" data-multicolor={isMulticolor}>
{@html isMulticolor ? itemNameHtml : removeFormatting(itemNameHtml)}
</p>
</div>
<div class="w-full overflow-auto">
<div class="w-full p-6 font-semibold leading-snug">
{#each skyblockItem.lore as lore}
{@html renderLore(lore)}
{/each}
{#if skyblockItem.containsItems && skyblockItem.containsItems.length > 0}
<div class="mt-4 border-t border-text/10 pt-4">
<div class="grid grid-cols-9 gap-1">
{#each skyblockItem.containsItems.slice(0, Math.min(skyblockItem.containsItems.length, 54)) as containedItem}
{#if containedItem.texture_path}
<div class="flex aspect-square items-center justify-center rounded bg-text/[0.04]">
<ContainedItem piece={containedItem} />
</div>
{:else}
<div class="aspect-square rounded bg-text/[0.04]"></div>
{/if}
{/each}
</div>
</div>
<Tooltip.Root group="armor" disableHoverableContent={true} openDelay={0} closeDelay={0}>
<Tooltip.Trigger
class="nice-colors-dark"
onclick={() => {
if (skyblockItem.containsItems) return;
itemContent.set(piece);
showItem.set(true);
}}>
<div class={cn(`relative flex aspect-square items-center justify-center overflow-clip rounded-lg`, isInventory ? "p-0" : `p-2 ${bgColor}`, { shine: shine })}>
<Avatar.Root>
<Avatar.Image loading="lazy" src={piece.texture_path} alt={piece.display_name} class="data-[enchanted=true]:enchanted h-auto w-14 select-none [image-rendering:pixelated]" data-enchanted={enchanted} />
<Avatar.Fallback>
<Image class={cn(isInventory ? "size-8 sm:size-14" : "size-14")} />
</Avatar.Fallback>
</Avatar.Root>
{#if recombobulated}
<div class="absolute -right-3 -top-3 z-10 size-6 rotate-45 bg-[--color]" style="--color: var(--§{RARITY_COLORS[RARITIES[RARITIES.indexOf(piece.rarity ?? 'common') - 1]]})"></div>
{/if}

{#if packData}
<div class="pt-4">
<Button.Root href={packData.link} target="_blank">
<div class="flex items-center justify-between gap-4 rounded-[0.625rem] bg-text/[0.05] p-2 transition-colors hover:bg-text/[0.08]">
<div class="flex items-center gap-2">
<Avatar.Root class="shrink-0 select-none">
<Avatar.Image loading="lazy" src="/resourcepacks/{packData.folder}/pack.png" alt={packData.name} class="pointer-events-none aspect-square size-10 h-full select-none rounded-lg" />
<Avatar.Fallback class="flex size-10 items-center justify-center rounded-lg bg-icon/90 text-center font-semibold uppercase">
{packData.name.slice(0, 2)}
</Avatar.Fallback>
</Avatar.Root>
<div class="flex flex-col">
<div class="font-semibold text-link">
<span class="underline">
{packData.name}
</span>
<span class="text-sm text-text/60">{packData.version}</span>
</div>
<div class="text-sm text-text/60">
by <span class="text-text/80">{packData.author}</span>
</div>
</div>
</div>
</div>
</Button.Root>
{#if showNumbers}
<div class="absolute bottom-0.5 right-0.5 text-sm font-semibold text-white text-shadow-[.1em_.1em_.1em_#000] sm:text-2xl">
{skyblockItem.Count}
</div>
{/if}
</div>
</div>
{/snippet}

{#snippet itemIcon()}
<div class={cn(`relative flex aspect-square items-center justify-center overflow-clip rounded-lg`, isInventory ? "p-0" : `p-2 ${bgColor}`, { shine: shine })}>
<Avatar.Root>
<Avatar.Image loading="lazy" src={$page.url.origin + piece.texture_path} alt={piece.display_name} class="data-[enchanted=true]:enchanted h-auto w-14 select-none [image-rendering:pixelated]" data-enchanted={enchanted} />
<Avatar.Fallback>
<Image class={cn(isInventory ? "size-8 sm:size-14" : "size-14")} />
</Avatar.Fallback>
</Avatar.Root>
{#if recombobulated}
<div class="absolute -right-3 -top-3 z-10 size-6 rotate-45 bg-[--color]" style="--color: var(--§{RARITY_COLORS[RARITIES[RARITIES.indexOf(piece.rarity ?? 'common') - 1]]})"></div>
{/if}
{#if showNumbers}
<div class="absolute bottom-0.5 right-0.5 text-sm font-semibold text-white text-shadow-[.1em_.1em_.1em_#000] sm:text-2xl">
{skyblockItem.Count}
</div>
{/if}
</div>
{/snippet}

{#snippet tooltip()}
<Tooltip.Root group="armor" openDelay={0} closeDelay={0}>
<Tooltip.Trigger class="nice-colors-dark" onclick={() => showDialog.set(!$showDialog)}>
{@render itemIcon()}
</Tooltip.Trigger>
<Tooltip.Content class="pointer-events-none z-50 flex max-h-[calc(96%-3rem)] max-w-[calc(100vw-2.5rem)] select-text flex-col overflow-hidden rounded-lg bg-background-lore font-icomoon" transition={flyAndScale} transitionConfig={{ x: -8, duration: 150 }} sideOffset={8} side="right" align="center">
{@render itemContents()}
</Tooltip.Trigger>
{#if isHover.current}
<Tooltip.Content class="z-50 flex max-h-[calc(96%-3rem)] max-w-[calc(100vw-2.5rem)] select-text flex-col overflow-hidden rounded-lg bg-background-lore font-icomoon" transition={flyAndScale} transitionConfig={{ x: -8, duration: 150 }} sideOffset={8} side="right" align="center">
<Content {piece} {isInventory} {showCount} {showRecombobulated} />
</Tooltip.Content>
</Tooltip.Root>
{/snippet}

{#snippet drawer()}
<Drawer.Root shouldScaleBackground={true} setBackgroundColorOnScale={false}>
<Drawer.Trigger class="nice-colors-dark">
{@render itemIcon()}
</Drawer.Trigger>
<Drawer.Portal>
<Drawer.Overlay class="fixed inset-0 z-40 bg-black/80" />
<Drawer.Content class="fixed bottom-0 left-0 right-0 z-50 flex max-h-[96%] flex-col rounded-t-[10px] bg-background-lore">
{@render itemContents(true)}
</Drawer.Content>
</Drawer.Portal>
</Drawer.Root>
{/snippet}

{#if isHover.current}
{@render tooltip()}
{#if $showDialog}
<Dialog.Root bind:open={$showDialogDelayed}>
<Dialog.Portal>
<Dialog.Overlay transition={fade} transitionConfig={{ duration: 150 }} class="fixed inset-0 z-40 bg-black/80" />
<Dialog.Content class="fixed left-[50%] top-[50%] z-50 flex max-h-[calc(96%-3rem)] max-w-[calc(100vw-2.5rem)] -translate-x-1/2 -translate-y-1/2 select-text flex-col overflow-hidden rounded-lg bg-background-lore font-icomoon" transition={flyAndScale} transitionConfig={{ x: -8, duration: 150 }}>
{@render itemContents()}
</Dialog.Content>
</Dialog.Portal>
</Dialog.Root>
{/if}
{:else}
{@render drawer()}
{/if}
</Tooltip.Root>
91 changes: 91 additions & 0 deletions src/lib/components/item/item-content.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<script lang="ts">
import ContainedItem from "$lib/components/ContainedItem.svelte";
import { packConfigs } from "$lib/shared/constants/packs";
import { getRarityClass, removeFormatting, renderLore } from "$lib/shared/helper";
import { cn } from "$lib/shared/utils";
import type { ProcessedSkyBlockItem, ProcessedSkyblockPet } from "$lib/types/global";
import { Avatar, Button } from "bits-ui";
import Image from "lucide-svelte/icons/image";
type Props = {
piece: ProcessedSkyBlockItem | ProcessedSkyblockPet;
isInventory?: boolean;
showCount?: boolean;
showRecombobulated?: boolean;
isDrawer?: boolean;
};
let { piece, isDrawer }: Props = $props();
const skyblockItem = $derived(piece as ProcessedSkyBlockItem);
const itemName = $derived(skyblockItem.display_name ?? "???");
const itemNameHtml = $derived(renderLore(itemName));
const isMulticolor = $derived((itemNameHtml.match(/<\/span>/g) || []).length > 1);
const bgColor = $derived(getRarityClass(piece.rarity ?? ("common".toLowerCase() as string), "bg"));
const enchanted = $derived(skyblockItem.shiny);
const packData = $derived(packConfigs.find((pack) => pack.id === skyblockItem.texture_pack));
</script>

<div class={cn(`nice-colors-dark flex flex-nowrap items-center justify-center gap-4 p-5`, { "rounded-t-[10px]": isDrawer }, bgColor)}>
<Avatar.Root class="shrink-0 px-2">
<Avatar.Image loading="lazy" src={piece.texture_path} alt={piece.display_name} class="data-[enchanted=true]:enchanted h-auto w-8 flex-none shrink-0 overflow-hidden [image-rendering:pixelated]" data-enchanted={enchanted} />
<Avatar.Fallback>
<Image class="size-8" />
</Avatar.Fallback>
</Avatar.Root>

<p class="relative text-wrap text-center text-base font-semibold uppercase data-[multicolor=true]:rounded-full data-[multicolor=true]:bg-background-lore data-[multicolor=true]:px-2 data-[multicolor=true]:py-1 data-[multicolor=false]:text-text sm:text-lg" data-multicolor={isMulticolor}>
{@html isMulticolor ? itemNameHtml : removeFormatting(itemNameHtml)}
</p>
</div>
<div class="w-full overflow-auto">
<div class="w-full p-6 font-semibold leading-snug">
{#each skyblockItem.lore as lore}
{@html renderLore(lore)}
{/each}

{#if Array.isArray(skyblockItem.containsItems) && !skyblockItem.containsItems.every((item) => Object.keys(item).length === 0)}
<div class="mt-4 border-t border-text/10 pt-4">
<div class="grid grid-cols-9 gap-1">
{#each skyblockItem.containsItems.slice(0, Math.min(skyblockItem.containsItems.length, 54)) as containedItem}
{#if containedItem.texture_path}
<div class="flex aspect-square items-center justify-center rounded bg-text/[0.04]">
<ContainedItem piece={containedItem} isInventory={true} />
</div>
{:else}
<div class="aspect-square rounded bg-text/[0.04]"></div>
{/if}
{/each}
</div>
</div>
{/if}

{#if packData}
<div class="pt-4">
<Button.Root href={packData.link} target="_blank">
<div class="flex items-center justify-between gap-4 rounded-[0.625rem] bg-text/[0.05] p-2 transition-colors hover:bg-text/[0.08]">
<div class="flex items-center gap-2">
<Avatar.Root class="shrink-0 select-none">
<Avatar.Image loading="lazy" src="/resourcepacks/{packData.folder}/pack.png" alt={packData.name} class="pointer-events-none aspect-square size-10 h-full select-none rounded-lg" />
<Avatar.Fallback class="flex size-10 items-center justify-center rounded-lg bg-icon/90 text-center font-semibold uppercase">
{packData.name.slice(0, 2)}
</Avatar.Fallback>
</Avatar.Root>
<div class="flex flex-col">
<div class="font-semibold text-link">
<span class="underline">
{packData.name}
</span>
<span class="text-sm text-text/60">{packData.version}</span>
</div>
<div class="text-sm text-text/60">
by <span class="text-text/80">{packData.author}</span>
</div>
</div>
</div>
</div>
</Button.Root>
</div>
{/if}
</div>
</div>
Loading

0 comments on commit f47cdae

Please sign in to comment.