init
This commit is contained in:
parent
3b2ec4fe5f
commit
8086aa8f38
51 changed files with 4109 additions and 0 deletions
52
website/src/lib/components/ui/badge/badge.svelte
Normal file
52
website/src/lib/components/ui/badge/badge.svelte
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
<script lang="ts" module>
|
||||
import { type VariantProps, tv } from "tailwind-variants";
|
||||
|
||||
export const badgeVariants = tv({
|
||||
base: "focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive inline-flex w-fit shrink-0 items-center justify-center gap-1 overflow-hidden whitespace-nowrap rounded-md border px-2 py-0.5 text-xs font-medium transition-[color,box-shadow] focus-visible:ring-[3px] [&>svg]:pointer-events-none [&>svg]:size-3",
|
||||
variants: {
|
||||
variant: {
|
||||
default:
|
||||
"bg-primary text-primary-foreground [a&]:hover:bg-primary/90 border-transparent",
|
||||
secondary:
|
||||
"bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90 border-transparent",
|
||||
destructive:
|
||||
"bg-destructive [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/70 border-transparent text-white",
|
||||
outline: "text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground",
|
||||
success:
|
||||
"bg-green-600 hover:bg-green-700 border-transparent text-white",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: "default",
|
||||
},
|
||||
});
|
||||
|
||||
export type BadgeVariant = VariantProps<typeof badgeVariants>["variant"];
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import type { HTMLAnchorAttributes } from "svelte/elements";
|
||||
import { cn, type WithElementRef } from "$lib/utils.js";
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
href,
|
||||
class: className,
|
||||
variant = "default",
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAnchorAttributes> & {
|
||||
variant?: BadgeVariant;
|
||||
} = $props();
|
||||
</script>
|
||||
|
||||
<svelte:element
|
||||
this={href ? "a" : "span"}
|
||||
bind:this={ref}
|
||||
data-slot="badge"
|
||||
{href}
|
||||
class={cn(badgeVariants({ variant }), className)}
|
||||
{...restProps}
|
||||
>
|
||||
{@render children?.()}
|
||||
</svelte:element>
|
||||
2
website/src/lib/components/ui/badge/index.ts
Normal file
2
website/src/lib/components/ui/badge/index.ts
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
export { default as Badge } from "./badge.svelte";
|
||||
export { badgeVariants, type BadgeVariant } from "./badge.svelte";
|
||||
80
website/src/lib/components/ui/button/button.svelte
Normal file
80
website/src/lib/components/ui/button/button.svelte
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
<script lang="ts" module>
|
||||
import { cn, type WithElementRef } from "$lib/utils.js";
|
||||
import type { HTMLAnchorAttributes, HTMLButtonAttributes } from "svelte/elements";
|
||||
import { type VariantProps, tv } from "tailwind-variants";
|
||||
|
||||
export const buttonVariants = tv({
|
||||
base: "focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive inline-flex shrink-0 items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium outline-none transition-all focus-visible:ring-[3px] disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
||||
variants: {
|
||||
variant: {
|
||||
default: "bg-primary text-primary-foreground shadow-xs hover:bg-primary/90",
|
||||
destructive:
|
||||
"bg-destructive shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60 text-white",
|
||||
outline:
|
||||
"bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50 border",
|
||||
secondary: "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
|
||||
ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
|
||||
link: "text-primary underline-offset-4 hover:underline",
|
||||
},
|
||||
size: {
|
||||
default: "h-9 px-4 py-2 has-[>svg]:px-3",
|
||||
sm: "h-8 gap-1.5 rounded-md px-3 has-[>svg]:px-2.5",
|
||||
lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
|
||||
icon: "size-9",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: "default",
|
||||
size: "default",
|
||||
},
|
||||
});
|
||||
|
||||
export type ButtonVariant = VariantProps<typeof buttonVariants>["variant"];
|
||||
export type ButtonSize = VariantProps<typeof buttonVariants>["size"];
|
||||
|
||||
export type ButtonProps = WithElementRef<HTMLButtonAttributes> &
|
||||
WithElementRef<HTMLAnchorAttributes> & {
|
||||
variant?: ButtonVariant;
|
||||
size?: ButtonSize;
|
||||
};
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
let {
|
||||
class: className,
|
||||
variant = "default",
|
||||
size = "default",
|
||||
ref = $bindable(null),
|
||||
href = undefined,
|
||||
type = "button",
|
||||
disabled,
|
||||
children,
|
||||
...restProps
|
||||
}: ButtonProps = $props();
|
||||
</script>
|
||||
|
||||
{#if href}
|
||||
<a
|
||||
bind:this={ref}
|
||||
data-slot="button"
|
||||
class={cn(buttonVariants({ variant, size }), className)}
|
||||
href={disabled ? undefined : href}
|
||||
aria-disabled={disabled}
|
||||
role={disabled ? "link" : undefined}
|
||||
tabindex={disabled ? -1 : undefined}
|
||||
{...restProps}
|
||||
>
|
||||
{@render children?.()}
|
||||
</a>
|
||||
{:else}
|
||||
<button
|
||||
bind:this={ref}
|
||||
data-slot="button"
|
||||
class={cn(buttonVariants({ variant, size }), className)}
|
||||
{type}
|
||||
{disabled}
|
||||
{...restProps}
|
||||
>
|
||||
{@render children?.()}
|
||||
</button>
|
||||
{/if}
|
||||
17
website/src/lib/components/ui/button/index.ts
Normal file
17
website/src/lib/components/ui/button/index.ts
Normal file
|
|
@ -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,
|
||||
};
|
||||
20
website/src/lib/components/ui/card/card-action.svelte
Normal file
20
website/src/lib/components/ui/card/card-action.svelte
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
<script lang="ts">
|
||||
import { cn, type WithElementRef } from "$lib/utils.js";
|
||||
import type { HTMLAttributes } from "svelte/elements";
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
|
||||
</script>
|
||||
|
||||
<div
|
||||
bind:this={ref}
|
||||
data-slot="card-action"
|
||||
class={cn("col-start-2 row-span-2 row-start-1 self-start justify-self-end", className)}
|
||||
{...restProps}
|
||||
>
|
||||
{@render children?.()}
|
||||
</div>
|
||||
15
website/src/lib/components/ui/card/card-content.svelte
Normal file
15
website/src/lib/components/ui/card/card-content.svelte
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
<script lang="ts">
|
||||
import type { HTMLAttributes } from "svelte/elements";
|
||||
import { cn, type WithElementRef } from "$lib/utils.js";
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
|
||||
</script>
|
||||
|
||||
<div bind:this={ref} data-slot="card-content" class={cn("px-6", className)} {...restProps}>
|
||||
{@render children?.()}
|
||||
</div>
|
||||
20
website/src/lib/components/ui/card/card-description.svelte
Normal file
20
website/src/lib/components/ui/card/card-description.svelte
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
<script lang="ts">
|
||||
import type { HTMLAttributes } from "svelte/elements";
|
||||
import { cn, type WithElementRef } from "$lib/utils.js";
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLParagraphElement>> = $props();
|
||||
</script>
|
||||
|
||||
<p
|
||||
bind:this={ref}
|
||||
data-slot="card-description"
|
||||
class={cn("text-muted-foreground text-sm", className)}
|
||||
{...restProps}
|
||||
>
|
||||
{@render children?.()}
|
||||
</p>
|
||||
20
website/src/lib/components/ui/card/card-footer.svelte
Normal file
20
website/src/lib/components/ui/card/card-footer.svelte
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
<script lang="ts">
|
||||
import { cn, type WithElementRef } from "$lib/utils.js";
|
||||
import type { HTMLAttributes } from "svelte/elements";
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
|
||||
</script>
|
||||
|
||||
<div
|
||||
bind:this={ref}
|
||||
data-slot="card-footer"
|
||||
class={cn("[.border-t]:pt-6 flex items-center px-6", className)}
|
||||
{...restProps}
|
||||
>
|
||||
{@render children?.()}
|
||||
</div>
|
||||
23
website/src/lib/components/ui/card/card-header.svelte
Normal file
23
website/src/lib/components/ui/card/card-header.svelte
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
<script lang="ts">
|
||||
import { cn, type WithElementRef } from "$lib/utils.js";
|
||||
import type { HTMLAttributes } from "svelte/elements";
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
|
||||
</script>
|
||||
|
||||
<div
|
||||
bind:this={ref}
|
||||
data-slot="card-header"
|
||||
class={cn(
|
||||
"@container/card-header has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6 grid auto-rows-min grid-rows-[auto_auto] items-start gap-1.5 px-6",
|
||||
className
|
||||
)}
|
||||
{...restProps}
|
||||
>
|
||||
{@render children?.()}
|
||||
</div>
|
||||
20
website/src/lib/components/ui/card/card-title.svelte
Normal file
20
website/src/lib/components/ui/card/card-title.svelte
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
<script lang="ts">
|
||||
import type { HTMLAttributes } from "svelte/elements";
|
||||
import { cn, type WithElementRef } from "$lib/utils.js";
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
|
||||
</script>
|
||||
|
||||
<div
|
||||
bind:this={ref}
|
||||
data-slot="card-title"
|
||||
class={cn("font-semibold leading-none", className)}
|
||||
{...restProps}
|
||||
>
|
||||
{@render children?.()}
|
||||
</div>
|
||||
23
website/src/lib/components/ui/card/card.svelte
Normal file
23
website/src/lib/components/ui/card/card.svelte
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
<script lang="ts">
|
||||
import type { HTMLAttributes } from "svelte/elements";
|
||||
import { cn, type WithElementRef } from "$lib/utils.js";
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
|
||||
</script>
|
||||
|
||||
<div
|
||||
bind:this={ref}
|
||||
data-slot="card"
|
||||
class={cn(
|
||||
"bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm",
|
||||
className
|
||||
)}
|
||||
{...restProps}
|
||||
>
|
||||
{@render children?.()}
|
||||
</div>
|
||||
25
website/src/lib/components/ui/card/index.ts
Normal file
25
website/src/lib/components/ui/card/index.ts
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
import Root from "./card.svelte";
|
||||
import Content from "./card-content.svelte";
|
||||
import Description from "./card-description.svelte";
|
||||
import Footer from "./card-footer.svelte";
|
||||
import Header from "./card-header.svelte";
|
||||
import Title from "./card-title.svelte";
|
||||
import Action from "./card-action.svelte";
|
||||
|
||||
export {
|
||||
Root,
|
||||
Content,
|
||||
Description,
|
||||
Footer,
|
||||
Header,
|
||||
Title,
|
||||
Action,
|
||||
//
|
||||
Root as Card,
|
||||
Content as CardContent,
|
||||
Description as CardDescription,
|
||||
Footer as CardFooter,
|
||||
Header as CardHeader,
|
||||
Title as CardTitle,
|
||||
Action as CardAction,
|
||||
};
|
||||
28
website/src/lib/components/ui/table/index.ts
Normal file
28
website/src/lib/components/ui/table/index.ts
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
import Root from "./table.svelte";
|
||||
import Body from "./table-body.svelte";
|
||||
import Caption from "./table-caption.svelte";
|
||||
import Cell from "./table-cell.svelte";
|
||||
import Footer from "./table-footer.svelte";
|
||||
import Head from "./table-head.svelte";
|
||||
import Header from "./table-header.svelte";
|
||||
import Row from "./table-row.svelte";
|
||||
|
||||
export {
|
||||
Root,
|
||||
Body,
|
||||
Caption,
|
||||
Cell,
|
||||
Footer,
|
||||
Head,
|
||||
Header,
|
||||
Row,
|
||||
//
|
||||
Root as Table,
|
||||
Body as TableBody,
|
||||
Caption as TableCaption,
|
||||
Cell as TableCell,
|
||||
Footer as TableFooter,
|
||||
Head as TableHead,
|
||||
Header as TableHeader,
|
||||
Row as TableRow,
|
||||
};
|
||||
20
website/src/lib/components/ui/table/table-body.svelte
Normal file
20
website/src/lib/components/ui/table/table-body.svelte
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
<script lang="ts">
|
||||
import { cn, type WithElementRef } from "$lib/utils.js";
|
||||
import type { HTMLAttributes } from "svelte/elements";
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLTableSectionElement>> = $props();
|
||||
</script>
|
||||
|
||||
<tbody
|
||||
bind:this={ref}
|
||||
data-slot="table-body"
|
||||
class={cn("[&_tr:last-child]:border-0", className)}
|
||||
{...restProps}
|
||||
>
|
||||
{@render children?.()}
|
||||
</tbody>
|
||||
20
website/src/lib/components/ui/table/table-caption.svelte
Normal file
20
website/src/lib/components/ui/table/table-caption.svelte
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
<script lang="ts">
|
||||
import { cn, type WithElementRef } from "$lib/utils.js";
|
||||
import type { HTMLAttributes } from "svelte/elements";
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLElement>> = $props();
|
||||
</script>
|
||||
|
||||
<caption
|
||||
bind:this={ref}
|
||||
data-slot="table-caption"
|
||||
class={cn("text-muted-foreground mt-4 text-sm", className)}
|
||||
{...restProps}
|
||||
>
|
||||
{@render children?.()}
|
||||
</caption>
|
||||
20
website/src/lib/components/ui/table/table-cell.svelte
Normal file
20
website/src/lib/components/ui/table/table-cell.svelte
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
<script lang="ts">
|
||||
import { cn, type WithElementRef } from "$lib/utils.js";
|
||||
import type { HTMLTdAttributes } from "svelte/elements";
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLTdAttributes> = $props();
|
||||
</script>
|
||||
|
||||
<td
|
||||
bind:this={ref}
|
||||
data-slot="table-cell"
|
||||
class={cn("whitespace-nowrap p-2 align-middle [&:has([role=checkbox])]:pr-0", className)}
|
||||
{...restProps}
|
||||
>
|
||||
{@render children?.()}
|
||||
</td>
|
||||
20
website/src/lib/components/ui/table/table-footer.svelte
Normal file
20
website/src/lib/components/ui/table/table-footer.svelte
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
<script lang="ts">
|
||||
import { cn, type WithElementRef } from "$lib/utils.js";
|
||||
import type { HTMLAttributes } from "svelte/elements";
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLTableSectionElement>> = $props();
|
||||
</script>
|
||||
|
||||
<tfoot
|
||||
bind:this={ref}
|
||||
data-slot="table-footer"
|
||||
class={cn("bg-muted/50 border-t font-medium [&>tr]:last:border-b-0", className)}
|
||||
{...restProps}
|
||||
>
|
||||
{@render children?.()}
|
||||
</tfoot>
|
||||
23
website/src/lib/components/ui/table/table-head.svelte
Normal file
23
website/src/lib/components/ui/table/table-head.svelte
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
<script lang="ts">
|
||||
import { cn, type WithElementRef } from "$lib/utils.js";
|
||||
import type { HTMLThAttributes } from "svelte/elements";
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLThAttributes> = $props();
|
||||
</script>
|
||||
|
||||
<th
|
||||
bind:this={ref}
|
||||
data-slot="table-head"
|
||||
class={cn(
|
||||
"text-foreground h-10 whitespace-nowrap px-2 text-left align-middle font-medium [&:has([role=checkbox])]:pr-0",
|
||||
className
|
||||
)}
|
||||
{...restProps}
|
||||
>
|
||||
{@render children?.()}
|
||||
</th>
|
||||
20
website/src/lib/components/ui/table/table-header.svelte
Normal file
20
website/src/lib/components/ui/table/table-header.svelte
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
<script lang="ts">
|
||||
import { cn, type WithElementRef } from "$lib/utils.js";
|
||||
import type { HTMLAttributes } from "svelte/elements";
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLTableSectionElement>> = $props();
|
||||
</script>
|
||||
|
||||
<thead
|
||||
bind:this={ref}
|
||||
data-slot="table-header"
|
||||
class={cn("[&_tr]:border-b", className)}
|
||||
{...restProps}
|
||||
>
|
||||
{@render children?.()}
|
||||
</thead>
|
||||
23
website/src/lib/components/ui/table/table-row.svelte
Normal file
23
website/src/lib/components/ui/table/table-row.svelte
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
<script lang="ts">
|
||||
import { cn, type WithElementRef } from "$lib/utils.js";
|
||||
import type { HTMLAttributes } from "svelte/elements";
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLTableRowElement>> = $props();
|
||||
</script>
|
||||
|
||||
<tr
|
||||
bind:this={ref}
|
||||
data-slot="table-row"
|
||||
class={cn(
|
||||
"hover:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors",
|
||||
className
|
||||
)}
|
||||
{...restProps}
|
||||
>
|
||||
{@render children?.()}
|
||||
</tr>
|
||||
22
website/src/lib/components/ui/table/table.svelte
Normal file
22
website/src/lib/components/ui/table/table.svelte
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
<script lang="ts">
|
||||
import type { HTMLTableAttributes } from "svelte/elements";
|
||||
import { cn, type WithElementRef } from "$lib/utils.js";
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLTableAttributes> = $props();
|
||||
</script>
|
||||
|
||||
<div data-slot="table-container" class="relative w-full overflow-x-auto">
|
||||
<table
|
||||
bind:this={ref}
|
||||
data-slot="table"
|
||||
class={cn("w-full caption-bottom text-sm", className)}
|
||||
{...restProps}
|
||||
>
|
||||
{@render children?.()}
|
||||
</table>
|
||||
</div>
|
||||
103
website/src/lib/data/coins.ts
Normal file
103
website/src/lib/data/coins.ts
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
export interface Coin {
|
||||
id: number;
|
||||
name: string;
|
||||
symbol: string;
|
||||
price: number;
|
||||
change24h: number;
|
||||
volume24h: number;
|
||||
marketCap: number;
|
||||
priceHistory: { date: string; price: number }[];
|
||||
}
|
||||
|
||||
export const coins: Coin[] = [
|
||||
{
|
||||
id: 1,
|
||||
name: 'Bitcoin',
|
||||
symbol: 'BTC',
|
||||
price: 67890.42,
|
||||
change24h: 2.3,
|
||||
volume24h: 28500000000,
|
||||
marketCap: 1320000000000,
|
||||
priceHistory: [
|
||||
{ date: '2025-05-14', price: 66250.18 },
|
||||
{ date: '2025-05-15', price: 65890.34 },
|
||||
{ date: '2025-05-16', price: 66780.12 },
|
||||
{ date: '2025-05-17', price: 66920.45 },
|
||||
{ date: '2025-05-18', price: 67120.78 },
|
||||
{ date: '2025-05-19', price: 67450.23 },
|
||||
{ date: '2025-05-20', price: 67890.42 }
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'Ethereum',
|
||||
symbol: 'ETH',
|
||||
price: 3456.78,
|
||||
change24h: -1.2,
|
||||
volume24h: 15200000000,
|
||||
marketCap: 420000000000,
|
||||
priceHistory: [
|
||||
{ date: '2025-05-14', price: 3520.45 },
|
||||
{ date: '2025-05-15', price: 3490.23 },
|
||||
{ date: '2025-05-16', price: 3475.67 },
|
||||
{ date: '2025-05-17', price: 3460.12 },
|
||||
{ date: '2025-05-18', price: 3470.54 },
|
||||
{ date: '2025-05-19', price: 3465.89 },
|
||||
{ date: '2025-05-20', price: 3456.78 }
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: 'Ripple',
|
||||
symbol: 'XRP',
|
||||
price: 0.54,
|
||||
change24h: 5.7,
|
||||
volume24h: 2100000000,
|
||||
marketCap: 28500000000,
|
||||
priceHistory: [
|
||||
{ date: '2025-05-14', price: 0.49 },
|
||||
{ date: '2025-05-15', price: 0.50 },
|
||||
{ date: '2025-05-16', price: 0.51 },
|
||||
{ date: '2025-05-17', price: 0.52 },
|
||||
{ date: '2025-05-18', price: 0.53 },
|
||||
{ date: '2025-05-19', price: 0.54 },
|
||||
{ date: '2025-05-20', price: 0.54 }
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: 'Solana',
|
||||
symbol: 'SOL',
|
||||
price: 156.89,
|
||||
change24h: 7.2,
|
||||
volume24h: 5600000000,
|
||||
marketCap: 67800000000,
|
||||
priceHistory: [
|
||||
{ date: '2025-05-14', price: 142.34 },
|
||||
{ date: '2025-05-15', price: 145.67 },
|
||||
{ date: '2025-05-16', price: 148.90 },
|
||||
{ date: '2025-05-17', price: 150.25 },
|
||||
{ date: '2025-05-18', price: 152.30 },
|
||||
{ date: '2025-05-19', price: 154.75 },
|
||||
{ date: '2025-05-20', price: 156.89 }
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: 'Dogecoin',
|
||||
symbol: 'DOGE',
|
||||
price: 0.12,
|
||||
change24h: -2.5,
|
||||
volume24h: 980000000,
|
||||
marketCap: 16500000000,
|
||||
priceHistory: [
|
||||
{ date: '2025-05-14', price: 0.125 },
|
||||
{ date: '2025-05-15', price: 0.124 },
|
||||
{ date: '2025-05-16', price: 0.123 },
|
||||
{ date: '2025-05-17', price: 0.122 },
|
||||
{ date: '2025-05-18', price: 0.121 },
|
||||
{ date: '2025-05-19', price: 0.120 },
|
||||
{ date: '2025-05-20', price: 0.120 }
|
||||
]
|
||||
}
|
||||
];
|
||||
1
website/src/lib/index.ts
Normal file
1
website/src/lib/index.ts
Normal file
|
|
@ -0,0 +1 @@
|
|||
// place files you want to import through the `$lib` alias in this folder.
|
||||
6
website/src/lib/server/db/index.ts
Normal file
6
website/src/lib/server/db/index.ts
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
import { drizzle } from 'drizzle-orm/postgres-js';
|
||||
import postgres from 'postgres';
|
||||
import { env } from '$env/dynamic/private';
|
||||
if (!env.DATABASE_URL) throw new Error('DATABASE_URL is not set');
|
||||
const client = postgres(env.DATABASE_URL);
|
||||
export const db = drizzle(client);
|
||||
6
website/src/lib/server/db/schema.ts
Normal file
6
website/src/lib/server/db/schema.ts
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
import { pgTable, serial, text, integer } from 'drizzle-orm/pg-core';
|
||||
|
||||
export const user = pgTable('user', {
|
||||
id: serial('id').primaryKey(),
|
||||
age: integer('age')
|
||||
});
|
||||
13
website/src/lib/utils.ts
Normal file
13
website/src/lib/utils.ts
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
import { clsx, type ClassValue } from "clsx";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs));
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export type WithoutChild<T> = T extends { child?: any } ? Omit<T, "child"> : T;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export type WithoutChildren<T> = T extends { children?: any } ? Omit<T, "children"> : T;
|
||||
export type WithoutChildrenOrChild<T> = WithoutChildren<WithoutChild<T>>;
|
||||
export type WithElementRef<T, U extends HTMLElement = HTMLElement> = T & { ref?: U | null };
|
||||
Reference in a new issue