Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

⬆️ Svelte 5 #246

Merged
merged 13 commits into from
Oct 21, 2024
7 changes: 6 additions & 1 deletion eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,12 @@ export default tseslint.config(
parser: svelteParser,
parserOptions: { project: './tsconfig.eslint.json', parser: tseslint.parser },
},
rules: { 'svelte/no-at-html-tags': 'off' },
rules: {
'@typescript-eslint/no-empty-function': 'off', // This is how you do optional events in SvelteKit
'@typescript-eslint/no-unsafe-assignment': 'off', // This rule is broken when using `$props()`.
'prefer-const': 'off', // This rule is broken when using `$props()`.
'svelte/no-at-html-tags': 'off',
},
},

{
Expand Down
16 changes: 9 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
"repository": "github:NatoBoram/Leanish",
"scripts": {
"act": "act --secret-file .env.local --var-file .env.vars.local",
"clean": "rm -rf .svelte-kit build dist node_modules playwright-report test-results",
"dev": "vite dev",
"dev:android": "pnpm run build:csr && cap run android",
"build": "vite build",
Expand All @@ -61,20 +62,21 @@
"package:watch": "svelte-kit sync && svelte-package -w",
"prepublishOnly": "BUILD_ADAPTER=node pnpm run build && pnpm run package",
"test": "pnpm run test:integration && pnpm run test:unit",
"test:integration": "playwright test",
"test:unit": "vitest --sequence.concurrent",
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
"lint": "prettier --check . && eslint .",
"lint:fix": "eslint --fix .; pnpm run format --list-different",
"format": "prettier --write .",
"test:integration": "playwright test",
"test:unit": "vitest --sequence.concurrent",
"generate:android": "capacitor-assets generate --android --iconBackgroundColor '#171717' --iconBackgroundColorDark '#171717' --logoSplashScale 0.5 --splashBackgroundColor '#0A0A0A' --splashBackgroundColorDark '#0A0A0A'",
"generate:pwa": "capacitor-assets generate --pwa --pwaManifestPath static/manifest.webmanifest",
"ionic:build": "pnpm run build:csr",
"ionic:serve": "vite dev --host=0.0.0.0 --port=8100",
"docker:build": "docker build --secret id=BUILD_BASE --tag leanish .",
"docker:run": "docker run --publish 127.0.0.1:3000:3000 leanish",
"docker:kill": "docker ps --format '{{.Image}} {{.ID}}' | grep leanish | awk '{print $2}' | xargs docker kill"
"docker:kill": "docker ps --format '{{.Image}} {{.ID}}' | grep leanish | awk '{print $2}' | xargs docker kill",
"sync": "svelte-kit sync"
},
"dependencies": {
"@capacitor/android": "^6.1.2",
Expand All @@ -95,15 +97,15 @@
"@sveltejs/adapter-static": "^3.0.5",
"@sveltejs/kit": "^2.7.2",
"@sveltejs/package": "^2.3.5",
"@sveltejs/vite-plugin-svelte": "^3.1.2",
"@sveltejs/vite-plugin-svelte": "^4.0.0",
"@tailwindcss/forms": "^0.5.9",
"@tailwindcss/typography": "^0.5.15",
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
"@ts-stack/markdown": "^1.5.0",
"@types/cookie": "^0.6.0",
"@vitejs/plugin-basic-ssl": "^1.1.0",
"autoprefixer": "^10.4.20",
"cookie": "^0.7.2",
"cookie": "^1.0.1",
"eslint": "^9.13.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-svelte": "^2.45.1",
Expand All @@ -115,9 +117,9 @@
"prettier-plugin-svelte": "^3.2.7",
"prettier-plugin-tailwindcss": "^0.6.8",
"publint": "^0.2.11",
"svelte": "^4.2.19",
"svelte": "^5.0.3",
"svelte-check": "^4.0.5",
"svelte-eslint-parser": "^0.41.1",
"svelte-eslint-parser": "^0.42.0",
"tailwindcss": "^3.4.14",
"tslib": "^2.8.0",
"typescript": "^5.6.3",
Expand Down
241 changes: 99 additions & 142 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

16 changes: 10 additions & 6 deletions src/lib/ClickOutside.svelte
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
<script lang="ts">
import { createEventDispatcher, onMount } from 'svelte'
import { onMount, type Snippet } from 'svelte'

const dispatch = createEventDispatcher<{ clickoutside: MouseEvent }>()
let node: Node

let className: string | undefined = ''
export { className as class }
interface Props {
readonly class?: string | undefined
readonly children?: Snippet
readonly onClickoutside: (event: MouseEvent) => void
}

const { class: className = '', children, onClickoutside }: Props = $props()

function handleClick(event: MouseEvent) {
if (!node.contains(event.target as Node)) dispatch('clickoutside', event)
if (!node.contains(event.target as Node)) onClickoutside(event)
}

onMount(() => {
Expand All @@ -20,5 +24,5 @@
</script>

<div class={className} bind:this={node}>
<slot />
{@render children?.()}
</div>
10 changes: 7 additions & 3 deletions src/lib/DepthSelector.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@
import { goto, invalidate } from '$app/navigation'
import { page } from '$app/stores'

export let maxDepth: number
interface Props {
readonly maxDepth: number
}

const { maxDepth }: Props = $props()

let input: HTMLInputElement

Expand Down Expand Up @@ -31,10 +35,10 @@
id="max_depth"
max={50}
min={1}
on:change={() => {
onchange={() => {
debounceChangeDepth($page.url)
}}
on:keypress={e => {
onkeypress={e => {
if (e.key === 'Enter') debounceChangeDepth($page.url)
}}
type="number"
Expand Down
20 changes: 14 additions & 6 deletions src/lib/Dismissable.svelte
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
<script lang="ts">
import { XMark } from '@natoboram/heroicons.svelte/24/solid'
import { createEventDispatcher } from 'svelte'
import type { Snippet } from 'svelte'

let className: string | undefined = undefined
export { className as class }
interface Props {
readonly class?: string | undefined
readonly children?: Snippet
readonly onDismiss: () => void
}

const dispatch = createEventDispatcher<{ dismiss: undefined }>()
const { class: className = undefined, children, onDismiss }: Props = $props()
</script>

<div class="relative rounded-md p-4 pr-12 {className}">
<button class="absolute right-4 top-4" on:click={() => dispatch('dismiss')}>
<button
class="absolute right-4 top-4"
onclick={() => {
onDismiss()
}}
>
<XMark class="h-6 w-6" />
</button>
<slot />
{@render children?.()}
</div>
4 changes: 2 additions & 2 deletions src/lib/Error.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,15 @@
Loading...
{:then [FlatButton, Spinner]}
<div class="flex gap-2 sm:flex-row">
<FlatButton class="base-container rounded" on:click={back}>
<FlatButton class="base-container rounded" onclick={back}>
{#if backing}
<Spinner />
{/if}

Back
</FlatButton>

<FlatButton class="primary rounded" on:click={refresh}>
<FlatButton class="primary rounded" onclick={refresh}>
{#if refreshing}
<Spinner />
{/if}
Expand Down
15 changes: 9 additions & 6 deletions src/lib/LimitSelector.svelte
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
<script lang="ts">
import { goto, invalidate } from '$app/navigation'
import { page } from '$app/stores'
import { createEventDispatcher } from 'svelte'

export let limit: number
interface Props {
readonly limit: number
readonly onLimit?: (limit: number) => void
}

const { limit, onLimit = () => {} }: Props = $props()

const dispatch = createEventDispatcher<{ limit: number }>()
let input: HTMLInputElement

let timeout: NodeJS.Timeout
Expand All @@ -31,7 +34,7 @@
url.searchParams.set('limit', String(newLimit))
await goto(url.toString(), { noScroll: true })
await invalidate('app:paginate')
dispatch('limit', newLimit)
onLimit(newLimit)
}
</script>

Expand All @@ -43,10 +46,10 @@
id="limit"
max={50}
min={1}
on:change={() => {
onchange={() => {
debounceChangeLimit($page.url)
}}
on:keypress={e => {
onkeypress={e => {
if (e.key === 'Enter') debounceChangeLimit($page.url)
}}
type="number"
Expand Down
14 changes: 9 additions & 5 deletions src/lib/ListingTypeSelector.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,12 @@
await invalidate('app:paginate')
}

export let type_: ListingType = 'Local'
export let name = 'type_'
interface Props {
readonly type_?: ListingType
readonly name?: string
}

const { type_ = 'Local', name = 'type_' }: Props = $props()
</script>

<div class="flex flex-row">
Expand All @@ -22,7 +26,7 @@
class="rounded-l-lg px-4 py-2 {type_ === 'Subscribed'
? 'hover:bg-primary/80'
: 'hover:bg-muted/20'}"
on:click={() => clickListingType($page.url, 'Subscribed')}
onclick={() => clickListingType($page.url, 'Subscribed')}
>
Subscribed
</button>
Expand All @@ -33,7 +37,7 @@
class:text-on-base-container={type_ !== 'Local'}
class:text-on-primary={type_ === 'Local'}
class="px-4 py-2 {type_ === 'Local' ? 'hover:bg-primary/80' : 'hover:bg-muted/20'}"
on:click={() => clickListingType($page.url, 'Local')}
onclick={() => clickListingType($page.url, 'Local')}
>
Local
</button>
Expand All @@ -44,7 +48,7 @@
class:text-on-base-container={type_ !== 'All'}
class:text-on-primary={type_ === 'All'}
class="rounded-r-lg px-4 py-2 {type_ === 'All' ? 'hover:bg-primary/80' : 'hover:bg-muted/20'}"
on:click={() => clickListingType($page.url, 'All')}
onclick={() => clickListingType($page.url, 'All')}
>
All
</button>
Expand Down
2 changes: 1 addition & 1 deletion src/lib/Modal.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<div class="relative z-10" aria-labelledby="modal-title" role="dialog" aria-modal="true">
<!-- Backdrop -->
<div class="fixed inset-0 bg-base bg-opacity-50 transition-opacity" />
<div class="fixed inset-0 bg-base bg-opacity-50 transition-opacity"></div>

<div class="fixed inset-0 z-10 overflow-y-auto">
<div class="flex min-h-full items-end justify-center p-4 text-center sm:items-center sm:p-0">
Expand Down
43 changes: 28 additions & 15 deletions src/lib/PaginationBar.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,30 @@
ChevronLeft,
ChevronRight,
} from '@natoboram/heroicons.svelte/20/solid'
import { createEventDispatcher } from 'svelte'
import FlatButton from './buttons/FlatButton.svelte'

let className: string | undefined = undefined
export { className as class }
interface Props {
readonly class?: string | undefined
readonly length: number
readonly limit: number
readonly nav?: HTMLElement
readonly onFirst: () => void
readonly onPrevious: (destination: number) => void
readonly onNext: (destination: number) => void
}

$effect(() => void nav)

export let length: number
export let limit: number
export let nav: HTMLElement | undefined = undefined
let {
class: className = undefined,
length,
limit,
nav = $bindable(),
onFirst,
onNext,
onPrevious,
}: Props = $props()

const dispatch = createEventDispatcher<{ previous: number; next: number; first: 1 }>()
let input: HTMLInputElement

function initialIndex(url: URL): number {
Expand Down Expand Up @@ -50,7 +63,7 @@
url.searchParams.set('page', String(1))
await goto(url, { noScroll: true })

dispatch('first', 1)
onFirst()
await invalidate('app:paginate')
}

Expand All @@ -67,7 +80,7 @@
url.searchParams.set('page', String(destination))
await goto(url, { noScroll: true })

dispatch('next', destination)
onNext(destination)
await invalidate('app:paginate')
}

Expand All @@ -78,7 +91,7 @@
url.searchParams.set('page', String(destination))
await goto(url, { noScroll: true })

dispatch('previous', destination)
onPrevious(destination)
await invalidate('app:paginate')
}
</script>
Expand All @@ -90,7 +103,7 @@
<div class="flex flex-row items-center gap-2 justify-self-start">
<!-- First -->
{#if canFirst($page.url)}
<FlatButton on:click={() => firstPage($page.url)} class="base-container w-28 rounded-lg">
<FlatButton onclick={() => firstPage($page.url)} class="base-container w-28 rounded-lg">
<ChevronDoubleLeft />
First
</FlatButton>
Expand All @@ -103,7 +116,7 @@

<!-- Previous -->
{#if hasPrevious($page.url)}
<FlatButton class="base-container w-32 rounded-lg" on:click={() => previous($page.url)}>
<FlatButton class="base-container w-32 rounded-lg" onclick={() => previous($page.url)}>
<ChevronLeft />
Previous
</FlatButton>
Expand All @@ -125,10 +138,10 @@
class="w-16 rounded-md border-none bg-base-container px-4 py-2 text-on-base-container [-moz-appearance:textfield]"
id="page"
min={1}
on:change={() => {
onchange={() => {
debounceChangePage($page.url)
}}
on:keypress={e => {
onkeypress={e => {
if (e.key === 'Enter') debounceChangePage($page.url)
}}
type="number"
Expand All @@ -140,7 +153,7 @@
{#if length >= limit}
<FlatButton
class="base-container w-28 justify-self-end rounded-lg"
on:click={() => next($page.url)}
onclick={() => next($page.url)}
>
Next
<ChevronRight />
Expand Down
Loading
Loading