Skip to content

Commit

Permalink
Update Svelte adapter
Browse files Browse the repository at this point in the history
Enhance TypeScript support in Svelte 1.x using insights from the work done on 2.0.
  • Loading branch information
pedroborges committed Oct 8, 2024
1 parent 9476aa5 commit 69292ef
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 29 deletions.
10 changes: 4 additions & 6 deletions packages/svelte/src/components/App.svelte
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script lang="ts">
import type { ComponentType } from 'svelte'
import type { LayoutType } from '../types'
import type { PageProps } from '@inertiajs/core'
import type { RenderProps } from './Render.svelte'
import Render, { h } from './Render.svelte'
Expand All @@ -11,8 +11,6 @@
* Resolves the render props for the current page component, including layouts.
*/
function resolveProps({ component, page, key = null }: InertiaStore): RenderProps {
if (!component?.default || !page) return null
const child = h(component.default, page.props, [], key)
const layout = component.layout
Expand All @@ -39,16 +37,16 @@
* }
*/
function resolveLayout(
layout: ComponentType,
layout: LayoutType,
child: RenderProps,
pageProps: PageProps,
key: number | null,
): RenderProps {
if (Array.isArray(layout)) {
return layout
.concat(child)
.slice()
.reverse()
.reduce((child, layout) => h(layout, pageProps, [child], key))
.reduce((currentRender, layoutComponent) => h(layoutComponent, pageProps, [currentRender], key), child)
}
return h(layout, pageProps, child ? [child] : [], key)
Expand Down
20 changes: 9 additions & 11 deletions packages/svelte/src/components/Link.svelte
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
<script lang="ts">
import type { Method, PreserveStateOption, RequestPayload } from '@inertiajs/core'
import { beforeUpdate } from 'svelte'
import type { FormDataConvertible, Method, PreserveStateOption } from '@inertiajs/core'
import { inertia } from '../index'
export let href: string
export let as: keyof HTMLElementTagNameMap = 'a'
export let data: RequestPayload = {}
export let data: Record<string, FormDataConvertible> = {}
export let method: Method = 'get'
export let replace: boolean = false
export let preserveScroll: PreserveStateOption = false
Expand All @@ -15,13 +14,12 @@
export let headers: Record<string, string> = {}
export let queryStringArrayFormat: 'brackets' | 'indices' = 'brackets'
beforeUpdate(() => {
if (as === 'a' && method.toLowerCase() !== 'get') {
console.warn(
`Creating POST/PUT/PATCH/DELETE <a> links is discouraged as it causes "Open Link in New Tab/Window" accessibility issues.\n\nPlease specify a more appropriate element using the "as" attribute. For example:\n\n<Link href="${href}" method="${method}" as="button">...</Link>`,
)
}
})
$: asProp = method !== 'get' ? 'button' : as.toLowerCase()
$: elProps =
{
a: { href },
button: { type: 'button' },
}[asProp] || {}
</script>

<!-- svelte-ignore a11y-no-static-element-interactions -->
Expand All @@ -39,8 +37,8 @@
headers,
queryStringArrayFormat,
}}
{...as === 'a' ? { href } : {}}
{...$$restProps}
{...elProps}
on:focus
on:blur
on:click
Expand Down
31 changes: 25 additions & 6 deletions packages/svelte/src/link.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,32 @@
import { mergeDataIntoQueryString, router, shouldIntercept, type VisitOptions } from '@inertiajs/core'
import type { Action } from 'svelte/action'
import {
mergeDataIntoQueryString,
router,
shouldIntercept,
type FormDataConvertible,
type GlobalEventsMap,
type VisitOptions,
} from '@inertiajs/core'
import type { CancelTokenSource } from 'axios'
import type { ActionReturn } from 'svelte/action'

interface ActionElement extends HTMLElement {
href?: string
}

type ActionParameters = VisitOptions & { href?: string }
type ActionParameters = Omit<VisitOptions, 'data'> & {
href?: string
data?: Record<string, FormDataConvertible>
}

type SelectedEventKeys = 'start' | 'progress' | 'finish' | 'before' | 'cancel' | 'success' | 'error'
type SelectedGlobalEventsMap = Pick<GlobalEventsMap, SelectedEventKeys>
type ActionAttributes = {
[K in keyof SelectedGlobalEventsMap as `on:${K}`]?: CustomEvent<SelectedGlobalEventsMap[K]['details']>
} & {
'on:cancel-token'?: CustomEvent<CancelTokenSource>
}

const link: Action<ActionElement, ActionParameters> = (node, options = {}) => {
function link(node: ActionElement, options: ActionParameters = {}): ActionReturn<ActionParameters, ActionAttributes> {
const [href, data] = hrefAndData(options)
node.href = href
options.data = data
Expand All @@ -34,8 +53,8 @@ const link: Action<ActionElement, ActionParameters> = (node, options = {}) => {
event.preventDefault()

router.visit(node.href, {
onCancelToken: () => fireEvent('cancel-token'),
onBefore: (visit) => fireEvent('before', { detail: { visit } }),
onCancelToken: (token) => fireEvent('cancel-token', { detail: { token } }),
onBefore: (visit) => fireEvent('before', { cancelable: true, detail: { visit } }),
onStart: (visit) => fireEvent('start', { detail: { visit } }),
onProgress: (progress) => fireEvent('progress', { detail: { progress } }),
onFinish: (visit) => fireEvent('finish', { detail: { visit } }),
Expand Down
8 changes: 4 additions & 4 deletions packages/svelte/src/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ import { writable } from 'svelte/store'
import type { ResolvedComponent } from './types'

export interface InertiaStore {
component: ResolvedComponent | null
page: Page | null
component: ResolvedComponent
page: Page
key: number | null
}

const store = writable<InertiaStore>({
component: null,
page: null,
component: null as unknown as ResolvedComponent,
page: null as unknown as Page,
key: null,
})

Expand Down
6 changes: 4 additions & 2 deletions packages/svelte/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ import type { ComponentType } from 'svelte'

export type ComponentResolver = (name: string) => ResolvedComponent | Promise<ResolvedComponent>

export type LayoutType = ComponentType | ComponentType[]

export type ResolvedComponent = {
default?: ComponentType
layout?: ComponentType
default: ComponentType
layout?: LayoutType
}

0 comments on commit 69292ef

Please sign in to comment.