first commit

This commit is contained in:
Omer Sabic 2024-03-11 06:37:35 +01:00
commit 8b4c542cc3
47 changed files with 4186 additions and 0 deletions

10
.gitignore vendored Normal file
View File

@ -0,0 +1,10 @@
.DS_Store
node_modules
/build
/.svelte-kit
/package
.env
.env.*
!.env.example
vite.config.js.timestamp-*
vite.config.ts.timestamp-*

1
.npmrc Normal file
View File

@ -0,0 +1 @@
engine-strict=true

4
.prettierignore Normal file
View File

@ -0,0 +1,4 @@
# Ignore files for PNPM, NPM and YARN
pnpm-lock.yaml
package-lock.json
yarn.lock

15
.prettierrc Normal file
View File

@ -0,0 +1,15 @@
{
"useTabs": true,
"singleQuote": true,
"trailingComma": "none",
"printWidth": 100,
"plugins": ["prettier-plugin-svelte", "prettier-plugin-tailwindcss"],
"overrides": [
{
"files": "*.svelte",
"options": {
"parser": "svelte"
}
}
]
}

38
README.md Normal file
View File

@ -0,0 +1,38 @@
# create-svelte
Everything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/main/packages/create-svelte).
## Creating a project
If you're seeing this, you've probably already done this step. Congrats!
```bash
# create a new project in the current directory
npm create svelte@latest
# create a new project in my-app
npm create svelte@latest my-app
```
## Developing
Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
```bash
npm run dev
# or start the server and open the app in a new browser tab
npm run dev -- --open
```
## Building
To create a production version of your app:
```bash
npm run build
```
You can preview the production build with `npm run preview`.
> To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment.

14
components.json Normal file
View File

@ -0,0 +1,14 @@
{
"$schema": "https://shadcn-svelte.com/schema.json",
"style": "default",
"tailwind": {
"config": "tailwind.config.js",
"css": "src/app.pcss",
"baseColor": "stone"
},
"aliases": {
"components": "$lib/components",
"utils": "$lib/utils.js"
},
"typescript": true
}

3199
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

39
package.json Normal file
View File

@ -0,0 +1,39 @@
{
"name": "podmail",
"version": "0.0.1",
"private": true,
"scripts": {
"dev": "vite dev",
"build": "vite build",
"preview": "vite preview",
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
"lint": "prettier --check .",
"format": "prettier --write ."
},
"devDependencies": {
"@sveltejs/adapter-auto": "^3.0.0",
"@sveltejs/kit": "^2.0.0",
"@sveltejs/vite-plugin-svelte": "^3.0.0",
"autoprefixer": "^10.4.16",
"postcss": "^8.4.32",
"postcss-load-config": "^5.0.2",
"prettier": "^3.1.1",
"prettier-plugin-svelte": "^3.1.2",
"prettier-plugin-tailwindcss": "^0.5.9",
"svelte": "^4.2.7",
"svelte-check": "^3.6.0",
"tailwindcss": "^3.3.6",
"tslib": "^2.4.1",
"typescript": "^5.0.0",
"vite": "^5.0.3"
},
"type": "module",
"dependencies": {
"bits-ui": "^0.19.5",
"clsx": "^2.1.0",
"lucide-svelte": "^0.354.0",
"tailwind-merge": "^2.2.1",
"tailwind-variants": "^0.2.0"
}
}

13
postcss.config.cjs Normal file
View File

@ -0,0 +1,13 @@
const tailwindcss = require('tailwindcss');
const autoprefixer = require('autoprefixer');
const config = {
plugins: [
//Some plugins, like tailwindcss/nesting, need to run before Tailwind,
tailwindcss(),
//But others, like autoprefixer, need to run after,
autoprefixer
]
};
module.exports = config;

13
src/app.d.ts vendored Normal file
View File

@ -0,0 +1,13 @@
// See https://kit.svelte.dev/docs/types#app
// for information about these interfaces
declare global {
namespace App {
// interface Error {}
// interface Locals {}
// interface PageData {}
// interface PageState {}
// interface Platform {}
}
}
export {};

12
src/app.html Normal file
View File

@ -0,0 +1,12 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
%sveltekit.head%
</head>
<body data-sveltekit-preload-data="hover" class="bg-background">
<div style="display: contents">%sveltekit.body%</div>
</body>
</html>

62
src/app.pcss Normal file
View File

@ -0,0 +1,62 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer base {
:root {
--background: 25 70% 98%;
--foreground: 25 67% 4%;
--muted: 25 30% 95%;
--muted-foreground: 25 2% 29%;
--popover: 25 70% 98%;
--popover-foreground: 25 67% 4%;
--card: 25 70% 98%;
--card-foreground: 25 67% 4%;
--border: 220 13% 91%;
--input: 220 13% 91%;
--primary: 25 31% 75%;
--primary-foreground: 25 31% 15%;
--secondary: 25 18% 90%;
--secondary-foreground: 25 18% 30%;
--accent: 25 23% 83%;
--accent-foreground: 25 23% 23%;
--destructive: 13 96% 20%;
--destructive-foreground: 13 96% 80%;
--ring: 25 31% 75%;
--radius: 0.5rem;
font-size: 16px;
}
.dark {
--background: 25 41% 2%;
--foreground: 25 21% 98%;
--muted: 25 30% 5%;
--muted-foreground: 25 2% 71%;
--popover: 25 41% 2%;
--popover-foreground: 25 21% 98%;
--card: 25 41% 2%;
--card-foreground: 25 21% 98%;
--border: 215 27.9% 16.9%;
--input: 215 27.9% 16.9%;
--primary: 25 31% 75%;
--primary-foreground: 25 31% 15%;
--secondary: 25 5% 14%;
--secondary-foreground: 25 5% 74%;
--accent: 25 11% 20%;
--accent-foreground: 25 11% 80%;
--destructive: 13 96% 49%;
--destructive-foreground: 0 0% 100%;
--ring: 25 31% 75%;
}
}
@font-face {
font-family: 'Epica';
font-style: normal;
font-weight: 500;
src: url('/fonts/epica.otf');
}
.font-epica {
font-family: Epica ui-serif, Georgia, Cambria, "Times New Roman", Times, serif;
}

View File

@ -0,0 +1,17 @@
<script>
// @ts-nocheck
import { Label } from "$lib/components/ui/label";
import { Textarea } from "$lib/components/ui/textarea"
export let text;
</script>
<div>
<Label for="email">Your relay email</Label>
<Textarea name="email" value={text} class="min-h-[1rem] h-[2.75rem] text-[1rem] text-center resize-none" readonly on:click={(e) => {
e.target.select();
navigator.clipboard.writeText(e.target.value);
e.target.unselect()
}}/>
</div>

View File

@ -0,0 +1,16 @@
<script lang="ts">
import { Avatar as AvatarPrimitive } from "bits-ui";
import { cn } from "$lib/utils.js.js";
type $$Props = AvatarPrimitive.FallbackProps;
let className: $$Props["class"] = undefined;
export { className as class };
</script>
<AvatarPrimitive.Fallback
class={cn("flex h-full w-full items-center justify-center rounded-full bg-muted", className)}
{...$$restProps}
>
<slot />
</AvatarPrimitive.Fallback>

View File

@ -0,0 +1,18 @@
<script lang="ts">
import { Avatar as AvatarPrimitive } from "bits-ui";
import { cn } from "$lib/utils.js.js";
type $$Props = AvatarPrimitive.ImageProps;
let className: $$Props["class"] = undefined;
export let src: $$Props["src"] = undefined;
export let alt: $$Props["alt"] = undefined;
export { className as class };
</script>
<AvatarPrimitive.Image
{src}
{alt}
class={cn("aspect-square h-full w-full", className)}
{...$$restProps}
/>

View File

@ -0,0 +1,18 @@
<script lang="ts">
import { Avatar as AvatarPrimitive } from "bits-ui";
import { cn } from "$lib/utils.js.js";
type $$Props = AvatarPrimitive.Props;
let className: $$Props["class"] = undefined;
export let delayMs: $$Props["delayMs"] = undefined;
export { className as class };
</script>
<AvatarPrimitive.Root
{delayMs}
class={cn("relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full", className)}
{...$$restProps}
>
<slot />
</AvatarPrimitive.Root>

View File

@ -0,0 +1,13 @@
import Root from "./avatar.svelte";
import Image from "./avatar-image.svelte";
import Fallback from "./avatar-fallback.svelte";
export {
Root,
Image,
Fallback,
//
Root as Avatar,
Image as AvatarImage,
Fallback as AvatarFallback,
};

View File

@ -0,0 +1,25 @@
<script lang="ts">
import { Button as ButtonPrimitive } from "bits-ui";
import { cn } from "$lib/utils.js.js";
import { buttonVariants, type Props, type Events } from "./index.js";
type $$Props = Props;
type $$Events = Events;
let className: $$Props["class"] = undefined;
export let variant: $$Props["variant"] = "default";
export let size: $$Props["size"] = "default";
export let builders: $$Props["builders"] = [];
export { className as class };
</script>
<ButtonPrimitive.Root
{builders}
class={cn(buttonVariants({ variant, size, className }))}
type="button"
{...$$restProps}
on:click
on:keydown
>
<slot />
</ButtonPrimitive.Root>

View File

@ -0,0 +1,49 @@
import Root from "./button.svelte";
import { tv, type VariantProps } from "tailwind-variants";
import type { Button as ButtonPrimitive } from "bits-ui";
const buttonVariants = tv({
base: "inline-flex items-center justify-center rounded-md text-sm font-medium whitespace-nowrap ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
variants: {
variant: {
default: "bg-primary text-primary-foreground hover:bg-primary/90",
destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
outline:
"border border-input bg-background hover:bg-accent hover:text-accent-foreground",
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
ghost: "hover:bg-accent hover:text-accent-foreground",
link: "text-primary underline-offset-4 hover:underline",
},
size: {
default: "h-10 px-4 py-2",
sm: "h-9 rounded-md px-3",
lg: "h-11 rounded-md px-8",
icon: "h-10 w-10",
},
},
defaultVariants: {
variant: "default",
size: "default",
},
});
type Variant = VariantProps<typeof buttonVariants>["variant"];
type Size = VariantProps<typeof buttonVariants>["size"];
type Props = ButtonPrimitive.Props & {
variant?: Variant;
size?: Size;
};
type Events = ButtonPrimitive.Events;
export {
Root,
type Props,
type Events,
//
Root as Button,
type Props as ButtonProps,
type Events as ButtonEvents,
buttonVariants,
};

View File

@ -0,0 +1,27 @@
import Root from "./input.svelte";
export type FormInputEvent<T extends Event = Event> = T & {
currentTarget: EventTarget & HTMLInputElement;
};
export type InputEvents = {
blur: FormInputEvent<FocusEvent>;
change: FormInputEvent<Event>;
click: FormInputEvent<MouseEvent>;
focus: FormInputEvent<FocusEvent>;
focusin: FormInputEvent<FocusEvent>;
focusout: FormInputEvent<FocusEvent>;
keydown: FormInputEvent<KeyboardEvent>;
keypress: FormInputEvent<KeyboardEvent>;
keyup: FormInputEvent<KeyboardEvent>;
mouseover: FormInputEvent<MouseEvent>;
mouseenter: FormInputEvent<MouseEvent>;
mouseleave: FormInputEvent<MouseEvent>;
paste: FormInputEvent<ClipboardEvent>;
input: FormInputEvent<InputEvent>;
};
export {
Root,
//
Root as Input,
};

View File

@ -0,0 +1,35 @@
<script lang="ts">
import type { HTMLInputAttributes } from "svelte/elements";
import { cn } from "$lib/utils.js.js";
import type { InputEvents } from "./index.js";
type $$Props = HTMLInputAttributes;
type $$Events = InputEvents;
let className: $$Props["class"] = undefined;
export let value: $$Props["value"] = undefined;
export { className as class };
</script>
<input
class={cn(
"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
className
)}
bind:value
on:blur
on:change
on:click
on:focus
on:focusin
on:focusout
on:keydown
on:keypress
on:keyup
on:mouseover
on:mouseenter
on:mouseleave
on:paste
on:input
{...$$restProps}
/>

View File

@ -0,0 +1,7 @@
import Root from "./label.svelte";
export {
Root,
//
Root as Label,
};

View File

@ -0,0 +1,21 @@
<script lang="ts">
import { Label as LabelPrimitive } from "bits-ui";
import { cn } from "$lib/utils.js.js";
type $$Props = LabelPrimitive.Props;
type $$Events = LabelPrimitive.Events;
let className: $$Props["class"] = undefined;
export { className as class };
</script>
<LabelPrimitive.Root
class={cn(
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
className
)}
{...$$restProps}
on:mousedown
>
<slot />
</LabelPrimitive.Root>

View File

@ -0,0 +1,17 @@
import { Popover as PopoverPrimitive } from "bits-ui";
import Content from "./popover-content.svelte";
const Root = PopoverPrimitive.Root;
const Trigger = PopoverPrimitive.Trigger;
const Close = PopoverPrimitive.Close;
export {
Root,
Content,
Trigger,
Close,
//
Root as Popover,
Content as PopoverContent,
Trigger as PopoverTrigger,
Close as PopoverClose,
};

View File

@ -0,0 +1,22 @@
<script lang="ts">
import { Popover as PopoverPrimitive } from "bits-ui";
import { cn, flyAndScale } from "$lib/utils.js.js";
type $$Props = PopoverPrimitive.ContentProps;
let className: $$Props["class"] = undefined;
export let transition: $$Props["transition"] = flyAndScale;
export let transitionConfig: $$Props["transitionConfig"] = undefined;
export { className as class };
</script>
<PopoverPrimitive.Content
{transition}
{transitionConfig}
class={cn(
"z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none",
className
)}
{...$$restProps}
>
<slot />
</PopoverPrimitive.Content>

View File

@ -0,0 +1,34 @@
import { Select as SelectPrimitive } from "bits-ui";
import Label from "./select-label.svelte";
import Item from "./select-item.svelte";
import Content from "./select-content.svelte";
import Trigger from "./select-trigger.svelte";
import Separator from "./select-separator.svelte";
const Root = SelectPrimitive.Root;
const Group = SelectPrimitive.Group;
const Input = SelectPrimitive.Input;
const Value = SelectPrimitive.Value;
export {
Root,
Group,
Input,
Label,
Item,
Value,
Content,
Trigger,
Separator,
//
Root as Select,
Group as SelectGroup,
Input as SelectInput,
Label as SelectLabel,
Item as SelectItem,
Value as SelectValue,
Content as SelectContent,
Trigger as SelectTrigger,
Separator as SelectSeparator,
};

View File

@ -0,0 +1,39 @@
<script lang="ts">
import { Select as SelectPrimitive } from "bits-ui";
import { cn, flyAndScale } from "$lib/utils.js.js";
import { scale } from "svelte/transition";
type $$Props = SelectPrimitive.ContentProps;
type $$Events = SelectPrimitive.ContentEvents;
export let sideOffset: $$Props["sideOffset"] = 4;
export let inTransition: $$Props["inTransition"] = flyAndScale;
export let inTransitionConfig: $$Props["inTransitionConfig"] = undefined;
export let outTransition: $$Props["outTransition"] = scale;
export let outTransitionConfig: $$Props["outTransitionConfig"] = {
start: 0.95,
opacity: 0,
duration: 50,
};
let className: $$Props["class"] = undefined;
export { className as class };
</script>
<SelectPrimitive.Content
{inTransition}
{inTransitionConfig}
{outTransition}
{outTransitionConfig}
{sideOffset}
class={cn(
"relative z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md outline-none",
className
)}
{...$$restProps}
on:keydown
>
<div class="w-full p-1">
<slot />
</div>
</SelectPrimitive.Content>

View File

@ -0,0 +1,40 @@
<script lang="ts">
import { cn } from "$lib/utils.js.js";
import Check from "lucide-svelte/icons/check";
import { Select as SelectPrimitive } from "bits-ui";
type $$Props = SelectPrimitive.ItemProps;
type $$Events = SelectPrimitive.ItemEvents;
let className: $$Props["class"] = undefined;
export let value: $$Props["value"];
export let label: $$Props["label"] = undefined;
export let disabled: $$Props["disabled"] = undefined;
export { className as class };
</script>
<SelectPrimitive.Item
{value}
{disabled}
{label}
class={cn(
"relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none data-[disabled]:pointer-events-none data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground data-[disabled]:opacity-50",
className
)}
{...$$restProps}
on:click
on:keydown
on:focusin
on:focusout
on:pointerleave
on:pointermove
>
<span class="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<SelectPrimitive.ItemIndicator>
<Check class="h-4 w-4" />
</SelectPrimitive.ItemIndicator>
</span>
<slot>
{label ? label : value}
</slot>
</SelectPrimitive.Item>

View File

@ -0,0 +1,16 @@
<script lang="ts">
import { Select as SelectPrimitive } from "bits-ui";
import { cn } from "$lib/utils.js.js";
type $$Props = SelectPrimitive.LabelProps;
let className: $$Props["class"] = undefined;
export { className as class };
</script>
<SelectPrimitive.Label
class={cn("py-1.5 pl-8 pr-2 text-sm font-semibold", className)}
{...$$restProps}
>
<slot />
</SelectPrimitive.Label>

View File

@ -0,0 +1,11 @@
<script lang="ts">
import { Select as SelectPrimitive } from "bits-ui";
import { cn } from "$lib/utils.js.js";
type $$Props = SelectPrimitive.SeparatorProps;
let className: $$Props["class"] = undefined;
export { className as class };
</script>
<SelectPrimitive.Separator class={cn("-mx-1 my-1 h-px bg-muted", className)} {...$$restProps} />

View File

@ -0,0 +1,27 @@
<script lang="ts">
import { Select as SelectPrimitive } from "bits-ui";
import ChevronDown from "lucide-svelte/icons/chevron-down";
import { cn } from "$lib/utils.js.js";
type $$Props = SelectPrimitive.TriggerProps;
type $$Events = SelectPrimitive.TriggerEvents;
let className: $$Props["class"] = undefined;
export { className as class };
</script>
<SelectPrimitive.Trigger
class={cn(
"flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
className
)}
{...$$restProps}
let:builder
on:click
on:keydown
>
<slot {builder} />
<div>
<ChevronDown class="h-4 w-4 opacity-50" />
</div>
</SelectPrimitive.Trigger>

View File

@ -0,0 +1,28 @@
import Root from "./textarea.svelte";
type FormTextareaEvent<T extends Event = Event> = T & {
currentTarget: EventTarget & HTMLTextAreaElement;
};
type TextareaEvents = {
blur: FormTextareaEvent<FocusEvent>;
change: FormTextareaEvent<Event>;
click: FormTextareaEvent<MouseEvent>;
focus: FormTextareaEvent<FocusEvent>;
keydown: FormTextareaEvent<KeyboardEvent>;
keypress: FormTextareaEvent<KeyboardEvent>;
keyup: FormTextareaEvent<KeyboardEvent>;
mouseover: FormTextareaEvent<MouseEvent>;
mouseenter: FormTextareaEvent<MouseEvent>;
mouseleave: FormTextareaEvent<MouseEvent>;
paste: FormTextareaEvent<ClipboardEvent>;
input: FormTextareaEvent<InputEvent>;
};
export {
Root,
//
Root as Textarea,
type TextareaEvents,
type FormTextareaEvent,
};

View File

@ -0,0 +1,31 @@
<script lang="ts">
import type { HTMLTextareaAttributes } from "svelte/elements";
import { cn } from "$lib/utils.js.js";
type $$Props = HTMLTextareaAttributes;
let className: $$Props["class"] = undefined;
export let value: $$Props["value"] = undefined;
export { className as class };
</script>
<textarea
class={cn(
"flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
className
)}
bind:value
on:blur
on:change
on:click
on:focus
on:keydown
on:keypress
on:keyup
on:mouseover
on:mouseenter
on:mouseleave
on:paste
on:input
{...$$restProps}
/>

19
src/lib/icons/logo.svelte Normal file
View File

@ -0,0 +1,19 @@
<script lang="ts">
// export let width = null;
export let style = "";
let className = "";
export {className as class};
</script>
<svg class={className} style="aspect-ratio: 247/46; {style}" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0.175659 28.192L25.4877 90.576H39.5997L64.9117 28.192H46.6557L32.6557 64.368L18.5437 28.192H0.175659Z" fill="#F3776F"/>
<path d="M91.8127 91.248C96.0687 91.248 100.213 90.464 104.245 88.784C108.053 87.216 111.413 84.864 114.325 81.952C117.237 79.04 119.589 75.568 121.157 71.76C122.837 67.84 123.733 63.696 123.733 59.328C123.733 55.072 122.837 50.928 121.157 46.896C119.589 43.088 117.237 39.728 114.325 36.816C111.413 33.904 107.941 31.552 104.245 29.984C100.213 28.304 96.0687 27.408 91.8127 27.408C87.4447 27.408 83.3007 28.304 79.3807 29.984C75.5727 31.552 72.1007 33.904 69.1887 36.816C66.2767 39.728 63.9247 43.2 62.3567 46.896C60.6767 50.928 59.8927 55.072 59.8927 59.328C59.8927 63.696 60.6767 67.84 62.3567 71.76C63.9247 75.568 66.2767 79.04 69.1887 81.952C72.1007 84.864 75.5727 87.216 79.3807 88.784C83.3007 90.464 87.4447 91.248 91.8127 91.248ZM91.8127 44.208C100.101 44.208 106.933 51.04 106.933 59.328C106.933 67.728 100.101 74.448 91.8127 74.448C83.4127 74.448 76.6927 67.728 76.6927 59.328C76.6927 51.04 83.4127 44.208 91.8127 44.208Z" fill="#E67269"/>
<path d="M158.201 91.36C168.729 91.36 178.585 86.208 184.521 77.584L170.633 68.064C167.833 72.096 163.241 74.56 158.201 74.56C149.913 74.56 143.081 67.84 143.081 59.44C143.081 51.152 149.913 44.32 158.201 44.32C163.129 44.32 167.721 46.784 170.633 50.816L184.297 41.072C181.385 37.04 177.577 33.568 173.097 31.216C168.617 28.864 163.353 27.52 158.201 27.52C153.945 27.52 149.689 28.416 145.769 30.096C141.961 31.664 138.601 34.016 135.577 36.928C132.665 39.84 130.425 43.312 128.745 47.008C127.177 51.04 126.281 55.184 126.281 59.44C126.281 63.808 127.177 67.952 128.745 71.872C130.425 75.68 132.665 79.152 135.577 82.064C138.601 84.976 141.961 87.328 145.769 88.896C149.689 90.576 153.945 91.36 158.201 91.36Z" fill="#DA6E62"/>
<path d="M247.519 27.52H230.719V30.992C226.351 28.752 221.423 27.52 216.383 27.52C212.015 27.52 207.871 28.416 203.951 30.096C200.143 31.664 196.671 34.016 193.759 36.928C190.847 39.84 188.495 43.2 186.927 47.008C185.247 51.04 184.463 55.184 184.463 59.44C184.463 63.808 185.247 67.952 186.927 71.872C188.495 75.68 190.847 79.152 193.759 82.064C196.671 84.976 200.143 87.328 203.951 88.896C207.871 90.576 212.015 91.36 216.383 91.36C221.311 91.36 226.351 90.24 230.719 88V90.576H247.519V27.52ZM223.999 72.544C221.647 73.888 219.071 74.56 216.383 74.56C207.983 74.56 201.263 67.84 201.263 59.44C201.263 51.152 207.983 44.32 216.383 44.32C219.295 44.32 222.095 45.216 224.559 46.784C226.911 48.352 228.815 50.48 230.047 53.056C230.943 55.072 231.391 57.2 231.391 59.552C231.391 62.128 230.719 64.816 229.375 67.056C228.143 69.296 226.239 71.2 223.999 72.544Z" fill="#CD695C"/>
<path d="M256.313 5.90399V90.576H273.225V0.303986L256.313 5.90399Z" fill="#C06555"/>
<path d="M311.544 91.36C322.072 91.36 331.928 86.208 337.864 77.584L323.976 68.064C321.176 72.096 316.584 74.56 311.544 74.56C303.256 74.56 296.424 67.84 296.424 59.44C296.424 51.152 303.256 44.32 311.544 44.32C316.472 44.32 321.064 46.784 323.976 50.816L337.64 41.072C334.728 37.04 330.92 33.568 326.44 31.216C321.96 28.864 316.696 27.52 311.544 27.52C307.288 27.52 303.032 28.416 299.112 30.096C295.304 31.664 291.944 34.016 288.92 36.928C286.008 39.84 283.768 43.312 282.088 47.008C280.52 51.04 279.624 55.184 279.624 59.44C279.624 63.808 280.52 67.952 282.088 71.872C283.768 75.68 286.008 79.152 288.92 82.064C291.944 84.976 295.304 87.328 299.112 88.896C303.032 90.576 307.288 91.36 311.544 91.36Z" fill="#B3604F"/>
<path d="M400.863 27.52H384.063V30.992C379.695 28.752 374.767 27.52 369.727 27.52C365.359 27.52 361.215 28.416 357.295 30.096C353.487 31.664 350.015 34.016 347.103 36.928C344.191 39.84 341.839 43.2 340.271 47.008C338.591 51.04 337.807 55.184 337.807 59.44C337.807 63.808 338.591 67.952 340.271 71.872C341.839 75.68 344.191 79.152 347.103 82.064C350.015 84.976 353.487 87.328 357.295 88.896C361.215 90.576 365.359 91.36 369.727 91.36C374.655 91.36 379.695 90.24 384.063 88V90.576H400.863V27.52ZM377.343 72.544C374.991 73.888 372.415 74.56 369.727 74.56C361.327 74.56 354.607 67.84 354.607 59.44C354.607 51.152 361.327 44.32 369.727 44.32C372.639 44.32 375.439 45.216 377.903 46.784C380.255 48.352 382.159 50.48 383.391 53.056C384.287 55.072 384.735 57.2 384.735 59.552C384.735 62.128 384.063 64.816 382.719 67.056C381.487 69.296 379.583 71.2 377.343 72.544Z" fill="#A75B48"/>
<path d="M406.072 91.248H432.28C443.592 91.248 452.776 82.064 452.776 70.752C452.776 59.44 443.592 50.144 432.28 50.144H427.576C426.008 50.144 424.664 48.912 424.664 47.232C424.664 45.664 426.008 44.32 427.576 44.32H450.984V26.736H427.576C416.264 26.736 407.08 35.92 407.08 47.232C407.08 58.544 416.264 67.728 427.576 67.728H432.28C433.848 67.728 435.192 69.072 435.192 70.752C435.192 72.32 433.96 73.664 432.28 73.664H406.072V91.248Z" fill="#9A5742"/>
<path d="M476.016 57.088V43.872H493.824V28.192H476.016V8.14401L459.216 13.744V57.088C459.216 61.792 460.112 66.384 461.904 70.64C463.696 74.784 466.16 78.48 469.408 81.616C472.544 84.752 476.24 87.328 480.384 89.008C484.64 90.8 489.12 91.696 493.824 91.696V74.896C483.968 74.896 476.016 66.944 476.016 57.088Z" fill="#8D523B"/>
</svg>

1
src/lib/index.ts Normal file
View File

@ -0,0 +1 @@
// place files you want to import through the `$lib` alias in this folder.

62
src/lib/utils.js.ts Normal file
View File

@ -0,0 +1,62 @@
import { type ClassValue, clsx } from "clsx";
import { twMerge } from "tailwind-merge";
import { cubicOut } from "svelte/easing";
import type { TransitionConfig } from "svelte/transition";
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
type FlyAndScaleParams = {
y?: number;
x?: number;
start?: number;
duration?: number;
};
export const flyAndScale = (
node: Element,
params: FlyAndScaleParams = { y: -8, x: 0, start: 0.95, duration: 150 }
): TransitionConfig => {
const style = getComputedStyle(node);
const transform = style.transform === "none" ? "" : style.transform;
const scaleConversion = (
valueA: number,
scaleA: [number, number],
scaleB: [number, number]
) => {
const [minA, maxA] = scaleA;
const [minB, maxB] = scaleB;
const percentage = (valueA - minA) / (maxA - minA);
const valueB = percentage * (maxB - minB) + minB;
return valueB;
};
const styleToString = (
style: Record<string, number | string | undefined>
): string => {
return Object.keys(style).reduce((str, key) => {
if (style[key] === undefined) return str;
return str + `${key}:${style[key]};`;
}, "");
};
return {
duration: params.duration ?? 200,
delay: 0,
css: (t) => {
const y = scaleConversion(t, [0, 1], [params.y ?? 5, 0]);
const x = scaleConversion(t, [0, 1], [params.x ?? 0, 0]);
const scale = scaleConversion(t, [0, 1], [params.start ?? 0.95, 1]);
return styleToString({
transform: `${transform} translate3d(${x}px, ${y}px, 0) scale(${scale})`,
opacity: t
});
},
easing: cubicOut
};
};

View File

@ -0,0 +1,7 @@
<script>
import '../app.pcss';
</script>
<div class="max-w-xl mx-auto p-8 h-screen">
<slot />
</div>

32
src/routes/+page.svelte Normal file
View File

@ -0,0 +1,32 @@
<script>
// @ts-nocheck
import { Label } from '$lib/components/ui/label';
import { Button } from '$lib/components/ui/button';
</script>
<div>
<Label>Your Latest Podcast</Label>
<Button class="flex w-full flex-row justify-start rounded text-left" variant="secondary">
<div class="items-center justify-center rounded-lg p-2">
<img src="/icons/play.svg" width={16} height={16} alt="" />
</div>
<div>
<h3 class="text-md">Your Daily Pod</h3>
<p class="text-sm text-muted-foreground">January 18th, 2024</p>
</div>
</Button>
<Label>Your Newsletters</Label>
<div class="overflow-scroll">
{#each [5, 4, 3, 2, 1] as _}
<Button class="flex w-full flex-row justify-start rounded text-left mt-4" variant="secondary">
<div class="items-center justify-center rounded-lg p-2">
<img src="/icons/play.svg" width={16} height={16} alt="" />
</div>
<div>
<h3 class="text-md">Your Daily Pod</h3>
<p class="text-sm text-muted-foreground">January 18th, 2024</p>
</div>
</Button>
{/each}
</div>
</div>

View File

@ -0,0 +1,16 @@
<script>
import { Button } from "$lib/components/ui/button";
</script>
<div class="text-center h-full">
<img src="/icons/logo.svg" class="mx-auto max-w-xs w-full" alt="">
<h2 class="font-epica text-3xl mt-16">Welcome to VocalCast</h2>
<p>Turn all your favorite newsletters <br/>into a daily podcast.</p>
<div class="mt-[100%]">
<Button class="w-full">Sign up</Button>
<Button class="w-full mt-4" variant="ghost">Log in</Button>
</div>
</div>

BIN
static/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
static/fonts/epica.otf Normal file

Binary file not shown.

11
static/icons/logo.svg Normal file
View File

@ -0,0 +1,11 @@
<svg width="494" height="92" viewBox="0 0 494 92" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0.175659 28.192L25.4877 90.576H39.5997L64.9117 28.192H46.6557L32.6557 64.368L18.5437 28.192H0.175659Z" fill="#F3776F"/>
<path d="M91.8127 91.248C96.0687 91.248 100.213 90.464 104.245 88.784C108.053 87.216 111.413 84.864 114.325 81.952C117.237 79.04 119.589 75.568 121.157 71.76C122.837 67.84 123.733 63.696 123.733 59.328C123.733 55.072 122.837 50.928 121.157 46.896C119.589 43.088 117.237 39.728 114.325 36.816C111.413 33.904 107.941 31.552 104.245 29.984C100.213 28.304 96.0687 27.408 91.8127 27.408C87.4447 27.408 83.3007 28.304 79.3807 29.984C75.5727 31.552 72.1007 33.904 69.1887 36.816C66.2767 39.728 63.9247 43.2 62.3567 46.896C60.6767 50.928 59.8927 55.072 59.8927 59.328C59.8927 63.696 60.6767 67.84 62.3567 71.76C63.9247 75.568 66.2767 79.04 69.1887 81.952C72.1007 84.864 75.5727 87.216 79.3807 88.784C83.3007 90.464 87.4447 91.248 91.8127 91.248ZM91.8127 44.208C100.101 44.208 106.933 51.04 106.933 59.328C106.933 67.728 100.101 74.448 91.8127 74.448C83.4127 74.448 76.6927 67.728 76.6927 59.328C76.6927 51.04 83.4127 44.208 91.8127 44.208Z" fill="#E67269"/>
<path d="M158.201 91.36C168.729 91.36 178.585 86.208 184.521 77.584L170.633 68.064C167.833 72.096 163.241 74.56 158.201 74.56C149.913 74.56 143.081 67.84 143.081 59.44C143.081 51.152 149.913 44.32 158.201 44.32C163.129 44.32 167.721 46.784 170.633 50.816L184.297 41.072C181.385 37.04 177.577 33.568 173.097 31.216C168.617 28.864 163.353 27.52 158.201 27.52C153.945 27.52 149.689 28.416 145.769 30.096C141.961 31.664 138.601 34.016 135.577 36.928C132.665 39.84 130.425 43.312 128.745 47.008C127.177 51.04 126.281 55.184 126.281 59.44C126.281 63.808 127.177 67.952 128.745 71.872C130.425 75.68 132.665 79.152 135.577 82.064C138.601 84.976 141.961 87.328 145.769 88.896C149.689 90.576 153.945 91.36 158.201 91.36Z" fill="#DA6E62"/>
<path d="M247.519 27.52H230.719V30.992C226.351 28.752 221.423 27.52 216.383 27.52C212.015 27.52 207.871 28.416 203.951 30.096C200.143 31.664 196.671 34.016 193.759 36.928C190.847 39.84 188.495 43.2 186.927 47.008C185.247 51.04 184.463 55.184 184.463 59.44C184.463 63.808 185.247 67.952 186.927 71.872C188.495 75.68 190.847 79.152 193.759 82.064C196.671 84.976 200.143 87.328 203.951 88.896C207.871 90.576 212.015 91.36 216.383 91.36C221.311 91.36 226.351 90.24 230.719 88V90.576H247.519V27.52ZM223.999 72.544C221.647 73.888 219.071 74.56 216.383 74.56C207.983 74.56 201.263 67.84 201.263 59.44C201.263 51.152 207.983 44.32 216.383 44.32C219.295 44.32 222.095 45.216 224.559 46.784C226.911 48.352 228.815 50.48 230.047 53.056C230.943 55.072 231.391 57.2 231.391 59.552C231.391 62.128 230.719 64.816 229.375 67.056C228.143 69.296 226.239 71.2 223.999 72.544Z" fill="#CD695C"/>
<path d="M256.313 5.90399V90.576H273.225V0.303986L256.313 5.90399Z" fill="#C06555"/>
<path d="M311.544 91.36C322.072 91.36 331.928 86.208 337.864 77.584L323.976 68.064C321.176 72.096 316.584 74.56 311.544 74.56C303.256 74.56 296.424 67.84 296.424 59.44C296.424 51.152 303.256 44.32 311.544 44.32C316.472 44.32 321.064 46.784 323.976 50.816L337.64 41.072C334.728 37.04 330.92 33.568 326.44 31.216C321.96 28.864 316.696 27.52 311.544 27.52C307.288 27.52 303.032 28.416 299.112 30.096C295.304 31.664 291.944 34.016 288.92 36.928C286.008 39.84 283.768 43.312 282.088 47.008C280.52 51.04 279.624 55.184 279.624 59.44C279.624 63.808 280.52 67.952 282.088 71.872C283.768 75.68 286.008 79.152 288.92 82.064C291.944 84.976 295.304 87.328 299.112 88.896C303.032 90.576 307.288 91.36 311.544 91.36Z" fill="#B3604F"/>
<path d="M400.863 27.52H384.063V30.992C379.695 28.752 374.767 27.52 369.727 27.52C365.359 27.52 361.215 28.416 357.295 30.096C353.487 31.664 350.015 34.016 347.103 36.928C344.191 39.84 341.839 43.2 340.271 47.008C338.591 51.04 337.807 55.184 337.807 59.44C337.807 63.808 338.591 67.952 340.271 71.872C341.839 75.68 344.191 79.152 347.103 82.064C350.015 84.976 353.487 87.328 357.295 88.896C361.215 90.576 365.359 91.36 369.727 91.36C374.655 91.36 379.695 90.24 384.063 88V90.576H400.863V27.52ZM377.343 72.544C374.991 73.888 372.415 74.56 369.727 74.56C361.327 74.56 354.607 67.84 354.607 59.44C354.607 51.152 361.327 44.32 369.727 44.32C372.639 44.32 375.439 45.216 377.903 46.784C380.255 48.352 382.159 50.48 383.391 53.056C384.287 55.072 384.735 57.2 384.735 59.552C384.735 62.128 384.063 64.816 382.719 67.056C381.487 69.296 379.583 71.2 377.343 72.544Z" fill="#A75B48"/>
<path d="M406.072 91.248H432.28C443.592 91.248 452.776 82.064 452.776 70.752C452.776 59.44 443.592 50.144 432.28 50.144H427.576C426.008 50.144 424.664 48.912 424.664 47.232C424.664 45.664 426.008 44.32 427.576 44.32H450.984V26.736H427.576C416.264 26.736 407.08 35.92 407.08 47.232C407.08 58.544 416.264 67.728 427.576 67.728H432.28C433.848 67.728 435.192 69.072 435.192 70.752C435.192 72.32 433.96 73.664 432.28 73.664H406.072V91.248Z" fill="#9A5742"/>
<path d="M476.016 57.088V43.872H493.824V28.192H476.016V8.14401L459.216 13.744V57.088C459.216 61.792 460.112 66.384 461.904 70.64C463.696 74.784 466.16 78.48 469.408 81.616C472.544 84.752 476.24 87.328 480.384 89.008C484.64 90.8 489.12 91.696 493.824 91.696V74.896C483.968 74.896 476.016 66.944 476.016 57.088Z" fill="#8D523B"/>
</svg>

After

Width:  |  Height:  |  Size: 5.1 KiB

1
static/icons/play.svg Normal file
View File

@ -0,0 +1 @@
<svg fill="none" xmlns="http://www.w3.org/2000/svg"><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"> <path d="M15 12.3301L9 16.6603L9 8L15 12.3301Z" fill="#000000"></path> </g></svg>

After

Width:  |  Height:  |  Size: 290 B

18
svelte.config.js Normal file
View File

@ -0,0 +1,18 @@
import adapter from '@sveltejs/adapter-auto';
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
/** @type {import('@sveltejs/kit').Config} */
const config = {
// Consult https://kit.svelte.dev/docs/integrations#preprocessors
// for more information about preprocessors
preprocess: [vitePreprocess({})],
kit: {
// adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list.
// If your environment is not supported or you settled on a specific environment, switch out the adapter.
// See https://kit.svelte.dev/docs/adapters for more information about adapters.
adapter: adapter()
}
};
export default config;

64
tailwind.config.js Normal file
View File

@ -0,0 +1,64 @@
import { fontFamily } from "tailwindcss/defaultTheme";
/** @type {import('tailwindcss').Config} */
const config = {
darkMode: ["class"],
content: ["./src/**/*.{html,js,svelte,ts}"],
safelist: ["dark"],
theme: {
container: {
center: true,
padding: "2rem",
screens: {
"2xl": "1400px"
}
},
extend: {
colors: {
border: "hsl(var(--border) / <alpha-value>)",
input: "hsl(var(--input) / <alpha-value>)",
ring: "hsl(var(--ring) / <alpha-value>)",
background: "hsl(var(--background) / <alpha-value>)",
foreground: "hsl(var(--foreground) / <alpha-value>)",
primary: {
DEFAULT: "hsl(var(--primary) / <alpha-value>)",
foreground: "hsl(var(--primary-foreground) / <alpha-value>)"
},
secondary: {
DEFAULT: "hsl(var(--secondary) / <alpha-value>)",
foreground: "hsl(var(--secondary-foreground) / <alpha-value>)"
},
destructive: {
DEFAULT: "hsl(var(--destructive) / <alpha-value>)",
foreground: "hsl(var(--destructive-foreground) / <alpha-value>)"
},
muted: {
DEFAULT: "hsl(var(--muted) / <alpha-value>)",
foreground: "hsl(var(--muted-foreground) / <alpha-value>)"
},
accent: {
DEFAULT: "hsl(var(--accent) / <alpha-value>)",
foreground: "hsl(var(--accent-foreground) / <alpha-value>)"
},
popover: {
DEFAULT: "hsl(var(--popover) / <alpha-value>)",
foreground: "hsl(var(--popover-foreground) / <alpha-value>)"
},
card: {
DEFAULT: "hsl(var(--card) / <alpha-value>)",
foreground: "hsl(var(--card-foreground) / <alpha-value>)"
}
},
borderRadius: {
lg: "var(--radius)",
md: "calc(var(--radius) - 2px)",
sm: "calc(var(--radius) - 4px)"
},
fontFamily: {
sans: [...fontFamily.sans]
}
}
},
};
export default config;

18
tsconfig.json Normal file
View File

@ -0,0 +1,18 @@
{
"extends": "./.svelte-kit/tsconfig.json",
"compilerOptions": {
"allowJs": true,
"checkJs": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"skipLibCheck": true,
"sourceMap": true,
"strict": true,
"moduleResolution": "bundler"
}
// Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias
//
// If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
// from the referenced tsconfig.json - TypeScript does not merge them in
}

6
vite.config.ts Normal file
View File

@ -0,0 +1,6 @@
import { sveltekit } from '@sveltejs/kit/vite';
import { defineConfig } from 'vite';
export default defineConfig({
plugins: [sveltekit()]
});