Skip to content

Commit

Permalink
Migration to Svelte 5 (#11)
Browse files Browse the repository at this point in the history
* Svelte 5 initial install and migration wip

* State update with $state and $props

* Using runes

* Event handled

* Refactor and update

* Cleanup package

* Event forward

* Migration main page
  • Loading branch information
prokawsar authored Dec 23, 2024
1 parent 8fca872 commit 4a24b0d
Show file tree
Hide file tree
Showing 22 changed files with 244 additions and 170 deletions.
20 changes: 9 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "paper-cost",
"version": "1.4.0",
"version": "1.7.0",
"private": true,
"scripts": {
"dev": "vite dev",
Expand All @@ -12,24 +12,22 @@
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
"test:ui": "playwright test",
"test:unit": "vitest",
"lint": "prettier --plugin-search-dir . --check .",
"format": "prettier --plugin-search-dir . --write ."
"lint": "prettier --check .",
"format": "prettier --write ."
},
"devDependencies": {
"@iconify/svelte": "^4.0.2",
"@playwright/test": "^1.46.1",
"@sveltejs/adapter-auto": "^3.0.0",
"@sveltejs/adapter-vercel": "^5.4.1",
"@sveltejs/kit": "^2.0.0",
"@sveltejs/vite-plugin-svelte": "^3.0.0",
"@sveltejs/kit": "^2.7.2",
"@sveltejs/vite-plugin-svelte": "^4.0.0",
"@types/mixpanel-browser": "^2.49.0",
"@types/node": "^22.5.0",
"autoprefixer": "^10.4.14",
"dotenv": "^16.4.5",
"postcss": "^8.4.27",
"prettier": "^2.8.0",
"prettier-plugin-svelte": "^2.10.1",
"svelte": "^4.0.5",
"prettier": "^3.3.3",
"prettier-plugin-svelte": "^3.2.7",
"svelte-check": "^3.4.3",
"tailwindcss": "^3.3.3",
"tslib": "^2.4.1",
Expand All @@ -44,8 +42,8 @@
"@supabase/supabase-js": "^2.44.3",
"dayjs": "^1.11.11",
"mixpanel-browser": "^2.55.1",
"svelte": "^5.1.0",
"svelte-persisted-store": "^0.11.0",
"svelte-sonner": "^0.3.27",
"tippy.js": "^6.3.7"
"svelte-sonner": "^0.3.27"
}
}
3 changes: 2 additions & 1 deletion src/lib/elements/About.svelte
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
<script lang="ts">
import { version } from '$app/environment'
import type { User } from '@supabase/supabase-js'
export let user: User | null = null
const { user }: { user: User | null } = $props()
</script>

<div class="flex flex-col text-center items-center">
Expand Down
18 changes: 10 additions & 8 deletions src/lib/elements/Button.svelte
Original file line number Diff line number Diff line change
@@ -1,26 +1,28 @@
<script lang="ts">
import { onMount } from 'svelte'
type ButtonProp = {
text: string
onclick: () => void
classNames: string
type: 'button' | 'submit' | 'reset'
}
export let disabled = false
export let text = ''
export let classNames = ''
export let type: 'button' | 'submit' | 'reset' = 'button'
let { text, classNames, type = 'button', onclick, ...rest }: ButtonProp = $props()
let buttonRef: HTMLButtonElement
onMount(() => {
$effect(() => {
if (buttonRef) {
buttonRef.type = type
}
})
</script>

<button
{onclick}
{...rest}
bind:this={buttonRef}
{disabled}
{type}
class="border border-gray-400 rounded-md text-teal-600 font-semibold px-3 py-1 w-fit disabled:text-opacity-60 {classNames}"
on:click
>
{text}
</button>
14 changes: 9 additions & 5 deletions src/lib/elements/Footer.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,13 @@
import { enhance } from '$app/forms'
import mixpanel from '$lib/utils/mixpanel'
export let showSettings = false
export let showAbout = false
export let loading = false
type FooterProp = { showSettings: boolean; showAbout: boolean; loading: boolean }
let {
showSettings = $bindable(),
showAbout = $bindable(),
loading = $bindable()
}: FooterProp = $props()
const navItems = [
{ href: '/', label: 'Home', icon: 'clarity:home-line' },
Expand All @@ -34,7 +38,7 @@
{label}
</a>
{/each}
<button on:click={toggleSettings} class="flex flex-row gap-1 items-center">
<button onclick={toggleSettings} class="flex flex-row gap-1 items-center">
<Icon icon="solar:settings-linear" /> Settings
</button>
</nav>
Expand All @@ -45,7 +49,7 @@
class="absolute w-20 right-3 bottom-11 flex flex-col items-start divide-y divide-orange-400 gap-1 bg-slate-50 p-2 rounded"
>
<button
on:click={() => {
onclick={() => {
showAbout = true
toggleSettings()
}}>About</button
Expand Down
55 changes: 39 additions & 16 deletions src/lib/elements/HistoryRow.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,20 @@
import { get40Percent, type CostHistoryType } from '$lib/utils/services'
import Icon from '@iconify/svelte'
import dayjs from 'dayjs'
import { createEventDispatcher } from 'svelte'
export let cost: CostHistoryType
export let isTrash: boolean = false
let {
cost,
isTrash = false,
ondelete,
onrestore
}: {
cost: CostHistoryType
isTrash?: boolean
ondelete: (id: string) => void
onrestore?: (id: string) => void
} = $props()
const dispatch = createEventDispatcher()
let deleteConfirm = ''
let deleteConfirm = $state('')
</script>

<div class="flex flex-col gap-1 items-center w-full p-1 border border-dashed rounded shadow-sm">
Expand All @@ -29,18 +35,27 @@
</p>

<div class="flex flex-row items-center gap-[2px]">
<button
class:hidden={deleteConfirm == cost.id || !isTrash}
class="border border-green-300 rounded text-green-600 p-[3px] w-fit disabled:border-gray-200 disabled:cursor-not-allowed disabled:text-opacity-45"
on:click|stopPropagation|preventDefault={() => dispatch('restore', cost.id)}
>
<Icon icon="ic:round-settings-backup-restore" />
</button>
{#if onrestore}
<button
class:hidden={deleteConfirm == cost.id || !isTrash}
class="border border-green-300 rounded text-green-600 p-[3px] w-fit disabled:border-gray-200 disabled:cursor-not-allowed disabled:text-opacity-45"
onclick={(e) => {
e.preventDefault()
onrestore(cost.id)
}}
>
<Icon icon="ic:round-settings-backup-restore" />
</button>
{/if}
<button
data-testid="delete-cost-history"
class:hidden={deleteConfirm == cost.id}
class="border border-red-300 rounded text-red-600 p-[3px] w-fit disabled:border-gray-200 disabled:cursor-not-allowed disabled:text-opacity-45"
on:click|stopPropagation|preventDefault={() => (deleteConfirm = cost.id || '')}
onclick={(e) => {
e.preventDefault()
e.stopPropagation()
deleteConfirm = cost.id || ''
}}
>
{#if isTrash}
<Icon icon="ic:baseline-delete-forever" />
Expand All @@ -51,14 +66,22 @@
{#if deleteConfirm == cost.id}
<button
class="border border-yellow-300 p-[3px] rounded text-yellow-600 w-fit disabled:border-gray-200 disabled:cursor-not-allowed disabled:text-opacity-45"
on:click|stopPropagation|preventDefault={() => (deleteConfirm = '')}
onclick={(e) => {
e.preventDefault()
e.stopPropagation()
deleteConfirm = ''
}}
>
<Icon icon="majesticons:multiply" width="16px" />
</button>
<button
data-testid="confirm-delete"
class="border border-green-300 p-[3px] rounded text-green-700 w-fit disabled:border-gray-200 disabled:cursor-not-allowed disabled:text-opacity-45"
on:click|stopPropagation|preventDefault={() => dispatch('delete', cost.id)}
onclick={(e) => {
e.preventDefault()
e.stopPropagation()
ondelete(cost.id)
}}
>
<Icon icon="teenyicons:tick-solid" width="15px" />
</button>
Expand Down
40 changes: 28 additions & 12 deletions src/lib/elements/Input.svelte
Original file line number Diff line number Diff line change
@@ -1,18 +1,33 @@
<script lang="ts">
import { focusedInputStore } from '$lib/stores'
import { makeid } from '$lib/utils/tools'
import { onMount } from 'svelte'
export let id: string = makeid(3)
export let value: string
export let name: string = ''
export let type: string = 'number'
export let disabled: boolean = false
export let classNames: string = ''
type InputType = {
id?: string
value: string
name: string
type?: string
disabled?: boolean
classNames?: string
onkeydown?: (event: KeyboardEvent) => void
onfocus?: () => void
}
let {
id = makeid(3),
value = $bindable(),
name,
classNames,
disabled = false,
type = 'number',
onkeydown,
onfocus,
...rest
}: InputType = $props()
let inputRef: HTMLInputElement
onMount(() => {
$effect(() => {
if (inputRef) {
inputRef.type = type
}
Expand All @@ -27,10 +42,11 @@
{disabled}
class="input-field focus:!border-[1.5px] focus:!border-teal-500 focus:outline-none {classNames}"
bind:value
on:keydown
on:focus
on:focus={() => ($focusedInputStore = inputRef)}
{...$$restProps}
{onkeydown}
onfocus={() => {
$focusedInputStore = inputRef
}}
{...rest}
/>

<style lang="postcss">
Expand Down
15 changes: 12 additions & 3 deletions src/lib/elements/Modal.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@
import { makeid, receive, send } from '$lib/utils/tools'
import Icon from '@iconify/svelte'
export let show = false
interface Props {
show?: boolean
children?: import('svelte').Snippet
}
let { show = $bindable(false), children }: Props = $props()
const id = makeid(6)
</script>

Expand All @@ -14,10 +19,14 @@
>
<button
class="absolute top-0 right-0 p-[3px] rounded-full w-fit"
on:click|stopPropagation|preventDefault={() => (show = false)}
onclick={(e) => {
e.preventDefault()
e.stopPropagation()
show = false
}}
>
<Icon icon="majesticons:multiply" width="20px" />
</button>
<slot />
{@render children?.()}
</div>
</div>
51 changes: 36 additions & 15 deletions src/lib/elements/PaperItem.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,40 +3,61 @@
import Input from './Input.svelte'
import { receive, send } from '$lib/utils/tools'
import { fields, placeholders } from '$lib/utils/constants'
import { createEventDispatcher } from 'svelte'
import type { Paper } from '$lib/utils/services'
export let paper: Paper
export let index: number
export let totalPaper: number
export let perPaperResult: Map<string, number>
let {
paper = $bindable(),
index,
totalPaper,
perPaperResult,
onkeydown,
onremove
}: {
paper: Paper
index: number
totalPaper: number
perPaperResult: Map<string, number>
onkeydown: (event: KeyboardEvent) => void
onremove: () => void
} = $props()
const dispatch = createEventDispatcher()
$effect(() => {
console.log(paper)
})
</script>

<div
id={paper.id}
id={paper?.id}
class="flex flex-row items-center justify-between rounded"
in:receive={{ key: paper.id, duration: 250 }}
out:send={{ key: paper.id, duration: 250 }}
in:receive={{ key: paper?.id, duration: 250 }}
out:send={{ key: paper?.id, duration: 250 }}
>
<div class="flex flex-row gap-[3px] items-center overflow-x-auto">
<button
disabled={totalPaper == 1 && index == 0}
class="border border-gray-400 rounded-md text-red-600 p-1 w-fit disabled:border-gray-200 disabled:cursor-not-allowed disabled:text-opacity-45"
on:click={() => dispatch('remove')}
onclick={() => onremove()}
>
<Icon icon="ph:trash-light" width="16px" />
</button>
{#each fields as field}
<Input name={field} bind:value={paper[field]} placeholder={placeholders[field]} on:keydown />
{/each}
{#if paper}
{#each fields as field}
<Input
name={field}
bind:value={paper[field]}
placeholder={placeholders[field]}
{onkeydown}
/>
{/each}
{/if}
</div>
<div class="flex flex-grow justify-center px-1">
<p
class="{perPaperResult.get(paper.id) ? 'font-semibold' : 'font-light text-gray-400'} pr-[2px]"
class="{perPaperResult.get(paper?.id)
? 'font-semibold'
: 'font-light text-gray-400'} pr-[2px]"
>
= {perPaperResult.get(paper.id)?.toFixed(2) || 'total'}
= {perPaperResult.get(paper?.id)?.toFixed(2) || 'total'}
</p>
</div>
</div>
4 changes: 2 additions & 2 deletions src/lib/elements/Result.svelte
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<script lang="ts">
import { get40Percent } from '$lib/utils/services'
export let total: number = 0
let { total = 0 }: { total: number } = $props()
$: _40Percent = get40Percent(total)
const _40Percent = $derived(get40Percent(total))
</script>

<div class="flex flex-col gap-1 w-full border shadow-md rounded py-1 px-2">
Expand Down
1 change: 1 addition & 0 deletions src/lib/elements/SingleLine.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<div class="w-full bg-gradient-to-r from-transparent via-slate-600/10 to-transparent p-[1px]"></div>
Loading

0 comments on commit 4a24b0d

Please sign in to comment.