I've used typescript for 30 minutes and I already love it

This commit is contained in:
Eclypsed
2024-01-21 23:51:15 -05:00
parent ae8f030afb
commit 266a805ac0
12 changed files with 1411 additions and 10 deletions

16
.prettierrc Normal file
View File

@@ -0,0 +1,16 @@
{
"tabWidth": 4,
"singleQuote": true,
"semi": false,
"printWidth": 200,
"bracketSpacing": true,
"plugins": ["prettier-plugin-svelte", "prettier-plugin-tailwindcss"],
"overrides": [
{
"files": "*.svelte",
"options": {
"parser": "svelte"
}
}
]
}

1187
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -13,11 +13,20 @@
"@sveltejs/adapter-auto": "^3.0.0",
"@sveltejs/kit": "^2.0.0",
"@sveltejs/vite-plugin-svelte": "^3.0.0",
"autoprefixer": "^10.4.17",
"postcss": "^8.4.33",
"prettier": "^3.2.4",
"prettier-plugin-svelte": "^3.1.2",
"prettier-plugin-tailwindcss": "^0.5.11",
"svelte": "^4.2.7",
"svelte-check": "^3.6.0",
"tailwindcss": "^3.4.1",
"tslib": "^2.4.1",
"typescript": "^5.0.0",
"vite": "^5.0.3"
},
"type": "module"
"type": "module",
"dependencies": {
"@fortawesome/fontawesome-free": "^6.5.1"
}
}

6
postcss.config.js Normal file
View File

@@ -0,0 +1,6 @@
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}

51
src/app.css Normal file
View File

@@ -0,0 +1,51 @@
@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+HK:wght@500&family=Noto+Sans+JP:wght@500&family=Noto+Sans+KR:wght@500&family=Noto+Sans+SC:wght@500&family=Noto+Sans+TC:wght@500&family=Noto+Sans:wght@500&display=swap');
@tailwind base;
@tailwind components;
@tailwind utilities;
img {
max-width: 100%;
}
/* Hide scrollbar for Chrome, Safari and Opera */
.no-scrollbar::-webkit-scrollbar {
display: none;
}
/* Hide scrollbar for IE, Edge and Firefox */
.no-scrollbar {
-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */
}
/* Default scrollbar for Chrome, Safari, Edge and Opera */
::-webkit-scrollbar {
width: 20px;
}
::-webkit-scrollbar-track {
background: transparent;
}
::-webkit-scrollbar-thumb {
border-radius: 10px;
box-shadow: inset 10px 10px rgba(100, 100, 100, 0.6);
border: solid 7px transparent;
}
/* Default scrollbar for Chrome, Safari, Edge, and Opera */
:root {
scrollbar-width: thin; /* Default scrollbar width for Firefox */
scrollbar-color: grey transparent; /* Default scrollbar colors for Firefox */
--lazuli-primary: #00a4dc;
--jellyfin-purple: #aa5cc3;
--jellyfin-blue: #00a4dc;
--youtube-red: #ff0000;
}
@media screen and (max-width: 768px) {
:root {
font-size: 0.7rem;
}
}

18
src/app.d.ts vendored
View File

@@ -1,13 +1,15 @@
// 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 {}
}
namespace App {
// interface Error {}
// interface Locals {}
// interface PageData {}
// interface PageState {}
// interface Platform {}
}
type AlertType = 'info' | 'success' | 'warning' | 'caution'
}
export {};
export {}

View File

@@ -0,0 +1,43 @@
<script lang="ts">
export let alertType: AlertType
export let alertMessage: string
import { onMount, createEventDispatcher } from 'svelte'
import { slide, fly } from 'svelte/transition'
let show: boolean = false
const dispatch = createEventDispatcher<{ closeAlert: null }>()
type BgColors = {
[key in AlertType]: string
}
const bgColors: BgColors = {
info: 'bg-neutral-500',
success: 'bg-emerald-500',
caution: 'bg-amber-500',
warning: 'bg-red-500',
}
export const triggerClose = () => {
show = false
dispatch('closeAlert')
}
onMount(() => {
show = true
setTimeout(() => triggerClose(), 10000)
})
</script>
{#if show}
<div in:fly={{ x: 500 }} out:slide={{ axis: 'y' }} class="py-1">
<div class="flex gap-1 overflow-hidden rounded-md">
<div class="flex w-full items-center p-4 {bgColors[alertType]}">
{alertMessage}
</div>
<button class="w-16 {bgColors[alertType]}" on:click={() => triggerClose()}>
<i class="fa-solid fa-x" />
</button>
</div>
</div>
{/if}

View File

@@ -0,0 +1,25 @@
<script lang="ts">
import Alert from './alert.svelte'
let alertBox: HTMLDivElement
let alertQueue: Alert[] = []
export const addAlert = (alertType: AlertType, alertMessage: string) => {
if (alertQueue.length > 5) alertQueue[0].triggerClose()
const alert = new Alert({
target: alertBox,
props: { alertType, alertMessage },
})
alert.$on('closeAlert', () => {
const index = alertQueue.indexOf(alert)
if (index > -1) alertQueue.splice(index, 1)
setTimeout(() => alert.$destroy(), 300)
})
alertQueue.push(alert)
}
</script>
<div bind:this={alertBox} class="fixed right-0 top-0 z-50 max-h-screen w-full max-w-sm overflow-hidden p-4"></div>

View File

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

11
src/lib/stores.ts Normal file
View File

@@ -0,0 +1,11 @@
import { writable } from 'svelte/store'
import type { Writable } from 'svelte/store'
export const pageWidth: Writable<number> = writable(0)
export const newestAlert: Writable<[AlertType, string] | null> = writable(null)
export const currentlyPlaying = writable(null)
const youtubeMusicBackground: string = 'https://www.gstatic.com/youtube/media/ytm/images/sbg/wsbg@4000x2250.png' // Default Youtube music background
export const backgroundImage: Writable<string> = writable(youtubeMusicBackground)

31
src/routes/+layout.svelte Normal file
View File

@@ -0,0 +1,31 @@
<script lang="ts">
import '../app.css'
import '@fortawesome/fontawesome-free/css/all.min.css'
import AlertBox from '$lib/components/util/alertBox.svelte'
import { newestAlert, backgroundImage, pageWidth } from '$lib/stores'
import { fade } from 'svelte/transition'
let alertBox: AlertBox
$: if ($newestAlert !== null && alertBox) alertBox.addAlert(...$newestAlert)
</script>
<svelte:window bind:innerWidth={$pageWidth} />
<div class="no-scrollbar relative font-notoSans text-white">
<div class="fixed isolate -z-10 h-full w-screen bg-black">
<div id="background-gradient" class="absolute z-10 h-1/2 w-full bg-cover" />
{#key $backgroundImage}
<img id="background-image" src={$backgroundImage} alt="" class="absolute h-1/2 w-full object-cover blur-lg" transition:fade={{ duration: 1000 }} />
{/key}
</div>
<slot />
<AlertBox bind:this={alertBox} />
</div>
<style>
#background-gradient {
background: linear-gradient(to bottom, rgba(0, 0, 0, 0.7), black);
}
#background-image {
mask-image: linear-gradient(to bottom, black, rgba(0, 0, 0, 0.3));
}
</style>

21
tailwind.config.js Normal file
View File

@@ -0,0 +1,21 @@
const defaultTheme = require('tailwindcss/defaultTheme')
/** @type {import('tailwindcss').Config} */
export default {
content: ['./src/**/*.{html,js,svelte,ts}'],
theme: {
extend: {
fontFamily: {
notoSans: ["'Noto Sans', 'Noto Sans HK', 'Noto Sans JP', 'Noto Sans KR', 'Noto Sans SC', 'Noto Sans TC'", ...defaultTheme.fontFamily.sans],
},
colors: {
'lazuli-primary': '#00a4dc',
'neutral-925': 'rgb(16, 16, 16)',
'jellyfin-purple': '#aa5cc3',
'jellyfin-blue': '#00a4dc',
'youtube-red': '#ff0000',
},
},
},
plugins: [],
}