Skip to content

Commit 013ddd9

Browse files
committed
Revert "Revert "Add Svelte TypeScript support (#1866)""
This reverts commit 519272b.
1 parent efc3cc8 commit 013ddd9

23 files changed

+579
-348
lines changed

.github/workflows/build.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ jobs:
88

99
strategy:
1010
matrix:
11-
adapter: ['react', 'vue2', 'vue3']
11+
adapter: ['react', 'vue2', 'vue3', 'svelte']
1212

1313
steps:
1414
- name: Checkout

packages/svelte/.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
dist
2+
types
23
node_modules
34
package-lock.json
45
yarn.lock
6+
.svelte-kit

packages/svelte/package.json

+45-7
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
"description": "The Svelte adapter for Inertia.js",
66
"contributors": [
77
"Jonathan Reinink <[email protected]>",
8-
"Pedro Borges <[email protected]>"
8+
"Pedro Borges <[email protected]>",
9+
"Dmytro Morozov <[email protected]>"
910
],
1011
"homepage": "https://inertiajs.com/",
1112
"repository": {
@@ -19,17 +20,54 @@
1920
"keywords": [
2021
"svelte"
2122
],
22-
"exports": {
23-
".": "./src/index.js",
24-
"./server": "./src/server.js"
23+
"scripts": {
24+
"build": "svelte-kit sync && svelte-package && publint",
25+
"prepublishOnly": "npm run build",
26+
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
27+
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch"
2528
},
26-
"main": "src/index.js",
29+
"files": [
30+
"dist",
31+
"!dist/**/*.test.*",
32+
"!dist/**/*.spec.*"
33+
],
2734
"peerDependencies": {
2835
"svelte": "^3.20.0 || ^4.0.0"
2936
},
37+
"devDependencies": {
38+
"@sveltejs/adapter-auto": "^3.2.0",
39+
"@sveltejs/kit": "^2.5.5",
40+
"@sveltejs/package": "^2.3.0",
41+
"@sveltejs/vite-plugin-svelte": "^3.0.2",
42+
"publint": "^0.2.7",
43+
"svelte": "^4.2.12",
44+
"svelte-check": "^3.6.8",
45+
"tslib": "^2.6.2",
46+
"typescript": "^5.4.3",
47+
"vite": "^5.2.7"
48+
},
49+
"exports": {
50+
".": {
51+
"types": "./dist/index.d.ts",
52+
"svelte": "./dist/index.js"
53+
},
54+
"./server": {
55+
"types": "./dist/server.d.ts",
56+
"svelte": "./dist/server.js"
57+
}
58+
},
59+
"import": "./dist/index.js",
60+
"types": "./dist/index.d.ts",
61+
"type": "module",
62+
"typesVersions": {
63+
">4.0": {
64+
".": [
65+
"./dist/index.d.ts"
66+
]
67+
}
68+
},
3069
"dependencies": {
3170
"@inertiajs/core": "1.2.0",
32-
"lodash.clonedeep": "^4.5.0",
33-
"lodash.isequal": "^4.5.0"
71+
"lodash": "^4.5.0"
3472
}
3573
}

packages/svelte/src/Render.svelte

-36
This file was deleted.

packages/svelte/src/createInertiaApp.js

-54
This file was deleted.

packages/svelte/src/App.svelte packages/svelte/src/lib/components/App.svelte

+7-5
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
1-
<script>
1+
<script lang="ts">
22
import Render, { h } from './Render.svelte'
3-
import store from './store'
3+
import store from '../store'
44
5-
$: child = $store.component && h($store.component.default, $store.page.props)
5+
$$props
6+
7+
$: child = $store.component && h($store.component.default, $store.page?.props)
68
$: layout = $store.component && $store.component.layout
79
$: components = layout
810
? Array.isArray(layout)
911
? layout
1012
.concat(child)
1113
.reverse()
12-
.reduce((child, layout) => h(layout, $store.page.props, [child]))
13-
: h(layout, $store.page.props, [child])
14+
.reduce((child, layout) => h(layout, $store.page?.props, [child]))
15+
: h(layout, $store.page?.props, [child])
1416
: child
1517
</script>
1618

packages/svelte/src/Link.svelte packages/svelte/src/lib/components/Link.svelte

+14-13
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
1-
<script>
1+
<script lang="ts">
2+
import type { Method, PreserveStateOption, RequestPayload } from '@inertiajs/core'
23
import { beforeUpdate } from 'svelte'
3-
import { default as inertia } from './link'
4+
import { inertia } from '../index'
45
5-
export let href
6-
export let as = 'a'
7-
export let data = {}
8-
export let method = 'get'
9-
export let replace = false
10-
export let preserveScroll = false
11-
export let preserveState = null
12-
export let only = []
13-
export let except = []
14-
export let headers = {}
15-
export let queryStringArrayFormat = 'brackets'
6+
export let href: string
7+
export let as: keyof HTMLElementTagNameMap = 'a'
8+
export let data: RequestPayload = {}
9+
export let method: Method = 'get'
10+
export let replace: boolean = false
11+
export let preserveScroll: PreserveStateOption = false
12+
export let preserveState: PreserveStateOption | null = null
13+
export let only: string[] = []
14+
export let except: string[] = []
15+
export let headers: Record<string, string> = {}
16+
export let queryStringArrayFormat: 'brackets' | 'indices' = 'brackets'
1617
1718
beforeUpdate(() => {
1819
if (as === 'a' && method.toLowerCase() !== 'get') {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<script context="module" lang="ts">
2+
import type { PageProps } from '@inertiajs/core'
3+
import type { InertiaComponentType } from '../types'
4+
5+
type RenderProps = {
6+
component: InertiaComponentType
7+
props?: PageProps
8+
children?: RenderProps[]
9+
} | null
10+
11+
export const h = (component: InertiaComponentType, props?: PageProps, children?: RenderProps[]): RenderProps => {
12+
return {
13+
component,
14+
...(props ? { props } : {}),
15+
...(children ? { children } : {}),
16+
}
17+
}
18+
</script>
19+
20+
<script lang="ts">
21+
import store from '../store'
22+
23+
export let component: InertiaComponentType
24+
export let props: PageProps = {}
25+
export let children: RenderProps[] = []
26+
27+
let prev = component
28+
let key = new Date().getTime()
29+
30+
function updateKey(component: InertiaComponentType) {
31+
if (prev !== component) {
32+
prev = component
33+
key = new Date().getTime()
34+
}
35+
}
36+
37+
$: updateKey(component)
38+
</script>
39+
40+
{#if $store.component}
41+
{#key key}
42+
<svelte:component this={component} {...props}>
43+
{#each children as child, index (component && component.length === index ? $store.key : null)}
44+
<svelte:self {...child} />
45+
{/each}
46+
</svelte:component>
47+
{/key}
48+
{/if}

packages/svelte/src/SSR.svelte packages/svelte/src/lib/components/SSR.svelte

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1-
<script>
1+
<script lang="ts">
2+
import type { Page } from '@inertiajs/core'
23
import App from './App.svelte'
3-
export let id, initialPage
4+
5+
export let id: string
6+
export let initialPage: Page
47
</script>
58

69
<div data-server-rendered="true" {id} data-page={JSON.stringify(initialPage)}>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import { router, setupProgress, type InertiaAppResponse, type Page } from '@inertiajs/core'
2+
import type { ComponentType } from 'svelte'
3+
import SvelteApp from './components/App.svelte'
4+
import SSR from './components/SSR.svelte'
5+
import store from './store'
6+
import type { ComponentResolver, InertiaComponentType } from './types'
7+
8+
interface CreateInertiaAppProps {
9+
id?: string
10+
resolve: ComponentResolver
11+
setup: (props: {
12+
el: Element
13+
// @ts-ignore
14+
App: ComponentType<SvelteApp>
15+
props: {
16+
initialPage: Page
17+
resolveComponent: ComponentResolver
18+
}
19+
}) => void | SvelteApp
20+
progress?:
21+
| false
22+
| {
23+
delay?: number
24+
color?: string
25+
includeCSS?: boolean
26+
showSpinner?: boolean
27+
}
28+
page?: Page
29+
}
30+
31+
export default async function createInertiaApp({
32+
id = 'app',
33+
resolve,
34+
setup,
35+
progress = {},
36+
page,
37+
}: CreateInertiaAppProps): InertiaAppResponse {
38+
const isServer = typeof window === 'undefined'
39+
const el = isServer ? null : document.getElementById(id)
40+
const initialPage = page || JSON.parse(el?.dataset.page ?? '{}')
41+
const resolveComponent = (name: string) => Promise.resolve(resolve(name))
42+
43+
await resolveComponent(initialPage.component).then((initialComponent) => {
44+
store.set({
45+
component: initialComponent as unknown as InertiaComponentType,
46+
page: initialPage,
47+
})
48+
})
49+
50+
if (!isServer) {
51+
if (!el) {
52+
throw new Error(`Element with ID "${id}" not found.`)
53+
}
54+
55+
router.init({
56+
initialPage,
57+
resolveComponent,
58+
swapComponent: async ({ component, page, preserveState }) => {
59+
store.update((current) => ({
60+
component: component as InertiaComponentType,
61+
page,
62+
key: preserveState ? current.key : Date.now(),
63+
}))
64+
},
65+
})
66+
67+
if (progress) {
68+
setupProgress(progress)
69+
}
70+
71+
setup({
72+
el,
73+
App: SvelteApp,
74+
props: {
75+
initialPage,
76+
resolveComponent,
77+
},
78+
})
79+
80+
return
81+
}
82+
83+
// Svelte types are written for the DOM API and not the SSR API.
84+
const { html, head, css } = (SSR as any).render({ id, initialPage })
85+
86+
return {
87+
body: html,
88+
head: [head, `<style data-vite-css>${css.code}</style>`],
89+
}
90+
}

packages/svelte/src/index.js packages/svelte/src/lib/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
export { router } from '@inertiajs/core'
2-
export { default as Link } from './Link.svelte'
2+
export { default as Link } from './components/Link.svelte'
33
export { default as createInertiaApp } from './createInertiaApp'
44
export { default as inertia } from './link'
55
export { default as page } from './page'

0 commit comments

Comments
 (0)