Skip to content

Conversation

@puRe1337
Copy link

@puRe1337 puRe1337 commented Oct 31, 2025

This PR is based on #2586.

This PR introduces official Svelte 5 support for Inertia.js by creating a new dedicated @inertiajs/svelte5 package. The implementation leverages Svelte 5's new runes syntax for improved reactivity and performance.

I converted more Components and Test Pages to Svelte 5.

There is currently only 1Test failing with the newly introduced future.preserveEqualProps Feature.

> [!CAUTION]
> tests/pages.spec.ts:10:1 › it can opt-in to preserve equal props from the previous page

I tried resolving the issue but I didn't find a solution yet. I guess it has something to do with how Svelte handles $state() internally since it creates a new Proxy object after setting. So this means checking for a === b fails in the effect. Correct me here please, if I'm wrong.

Feel free to also fork this and fix it.

Thanks to @brodienguyen for your previous work.
Also @Razunter I changed html to body as you mentioned in #2586 (comment). Didn't see any change here, tests were still passing for me.

Introduce the Svelte 5 adapter for Inertia.js, including core components, utilities, configuration, and a comprehensive test application. Update documentation and test server logic to support Svelte 5 integration.
Replaces all imports from '@inertiajs/svelte' with '@inertiajs/svelte5' across layouts, pages, and form helpers in the Svelte 5 test app. This aligns the codebase with the new package structure and ensures compatibility with the latest version.
Replace all usages of $page and @inertiajs/svelte imports with page and @inertiajs/svelte5 in test-app Svelte components. This aligns the test app with the new svelte5 API and ensures consistent usage of the page store and form helpers.
Refactored Svelte components to use $props and $state for props and state management, replacing legacy export let syntax. Updated page state management to support both runes-based and store-based approaches for backward compatibility. Adjusted test-app usage to align with new $page and mount API.
Refactors Deferred, Form, Link, and WhenVisible components to use `children` and `fallback` props instead of Svelte slots. This improves composability and aligns with a more functional component API.
Replace usage of slot-based fallback fragments with the new {#snippet fallback()} syntax in Deferred components across InstantReload, ManyGroups, Page1, and Page2 Svelte files. This aligns with updated Svelte syntax for defining fallback content.
Replace all instances of page.url with $page.url in Events.svelte to ensure correct reactive referencing of the page URL. This change improves consistency and leverages Svelte's store syntax for reactivity.
Refactor FormComponent to wrap form elements in a snippet block using the children({ isDirty }) pattern instead of let:isDirty. This improves consistency with the updated API and enhances readability.
Access pageState.props within the $effect callback to ensure proper reactivity. Assign props to a local variable and use it for loaded state calculation.
Replace $state with $derived for renderProps to ensure reactive updates. Move setPage(page) into an $effect to synchronize global page state with local changes. Cleans up redundant assignments in event handler.
Refactor Errors.svelte to wrap form content in a snippet block using children({ errors, hasErrors, setError, clearErrors }). This improves composability and makes the form logic more reusable.
Refactor Form and Link components to use direct event handler props instead of Svelte's on:event syntax. This improves compatibility with Svelte 5 and enables more flexible event handling.
Expose isDirty and setError from the Form component to consumers. Update SetDefaultsOnSuccess example to use the new children snippet API for accessing isDirty and errors.
Refactor ResetOnError and ResetOnSuccess components to use the {#snippet children({ errors })} block instead of let:errors. This aligns with updated Form API usage and improves code consistency.
Refactor ResetOnErrorFields and ResetOnSuccessFields components to use the {#snippet children({ errors })} block instead of let:errors. This aligns with updated Form API usage and improves code consistency.
Replace manual slot props with snippet block for children, improving readability and maintainability of form event state handling.
Refactor Form component usage to use 'action' instead of 'bind:action' and implement the 'children' snippet for rendering form fields. Change error message container from <p> to <div> for consistency.
Refactor EmptyAction.svelte to use the snippet block for children and remove the let:errors directive. Error messages are now rendered inside a div instead of a paragraph.
Introduce an email input field to the form and update error handling to support both name and email fields. Refactor markup to use snippet block for children and improve error display.
Update test.skip conditions to also skip tests when PACKAGE is 'svelte5', reflecting lack of support for Head and Link features in the Svelte 5 adapter.
Replaces the store-based useForm implementation with a Svelte runes-based version for improved reactivity and integration. Updates all imports and usage to reference the new useForm.svelte.ts, removes the old useForm.ts, and adjusts related components and test apps accordingly.
Update Errors.svelte, Methods.svelte, and Transform.svelte to use the direct form variable instead of the $form store syntax. This aligns with the updated FormHelper API and improves code clarity.
Update all references from $form to form in Dirty.svelte to align with Svelte's store usage best practices. This change improves code clarity and consistency.
Refactor Reset.svelte to use the snippet block for children and remove the let:errors prop from the Form component. This improves code clarity and aligns with updated Svelte syntax.
Refactor Defaults.svelte to wrap form fields in a snippet block, passing errors and isDirty to children. This improves code clarity and aligns with updated component patterns.
Refactor Form usage to wrap children in a snippet block, enabling access to isDirty, errors, and hasErrors via the snippet context instead of let directives. This aligns with updated Svelte syntax and improves code clarity.
Update the onError callback to assign errors to the local variable instead of form.errors and ensure the correct parameter is passed to user-defined onError handlers. Also, call form.defaults() after successful submission if defaults were not set in onSuccess.
Wrap defaults in $state for reactivity and update setFormData to trigger updates for each property. Refactor reset to handle specific fields more reliably and ensure correct default values are restored.
Assign id 'error_name' to the name error message div for improved testability and accessibility.
Refactor the logic for updating form defaults to handle single and multiple field updates more clearly. This change improves code readability and ensures that defaults are always cloned before modification.
@puRe1337 puRe1337 marked this pull request as draft October 31, 2025 17:22
@puRe1337 puRe1337 marked this pull request as ready for review November 4, 2025 00:41
})
const preserve = untrack(() => config.get('future.preserveEqualProps'))
// Even when `preserveEqualProps` is enabled, Svelte will wrap incoming props
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please take a look at this one.
While migrating more code to the Svelte 5 Runes style, I haven't found a cleaner solution for this case yet.
For this reason, a small workaround has been implemented. The linked comment explains the proxy behavior in more detail.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants