I've used typescript for 30 minutes and I already love it
This commit is contained in:
16
.prettierrc
Normal file
16
.prettierrc
Normal 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
1187
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
11
package.json
11
package.json
@@ -13,11 +13,20 @@
|
|||||||
"@sveltejs/adapter-auto": "^3.0.0",
|
"@sveltejs/adapter-auto": "^3.0.0",
|
||||||
"@sveltejs/kit": "^2.0.0",
|
"@sveltejs/kit": "^2.0.0",
|
||||||
"@sveltejs/vite-plugin-svelte": "^3.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": "^4.2.7",
|
||||||
"svelte-check": "^3.6.0",
|
"svelte-check": "^3.6.0",
|
||||||
|
"tailwindcss": "^3.4.1",
|
||||||
"tslib": "^2.4.1",
|
"tslib": "^2.4.1",
|
||||||
"typescript": "^5.0.0",
|
"typescript": "^5.0.0",
|
||||||
"vite": "^5.0.3"
|
"vite": "^5.0.3"
|
||||||
},
|
},
|
||||||
"type": "module"
|
"type": "module",
|
||||||
|
"dependencies": {
|
||||||
|
"@fortawesome/fontawesome-free": "^6.5.1"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
6
postcss.config.js
Normal file
6
postcss.config.js
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
export default {
|
||||||
|
plugins: {
|
||||||
|
tailwindcss: {},
|
||||||
|
autoprefixer: {},
|
||||||
|
},
|
||||||
|
}
|
||||||
51
src/app.css
Normal file
51
src/app.css
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
4
src/app.d.ts
vendored
4
src/app.d.ts
vendored
@@ -8,6 +8,8 @@ declare global {
|
|||||||
// interface PageState {}
|
// interface PageState {}
|
||||||
// interface Platform {}
|
// interface Platform {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AlertType = 'info' | 'success' | 'warning' | 'caution'
|
||||||
}
|
}
|
||||||
|
|
||||||
export {};
|
export {}
|
||||||
|
|||||||
43
src/lib/components/util/alert.svelte
Normal file
43
src/lib/components/util/alert.svelte
Normal 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}
|
||||||
25
src/lib/components/util/alertBox.svelte
Normal file
25
src/lib/components/util/alertBox.svelte
Normal 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>
|
||||||
@@ -1 +0,0 @@
|
|||||||
// place files you want to import through the `$lib` alias in this folder.
|
|
||||||
11
src/lib/stores.ts
Normal file
11
src/lib/stores.ts
Normal 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
31
src/routes/+layout.svelte
Normal 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
21
tailwind.config.js
Normal 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: [],
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user