From 7bbd294041c69ce1982070957593c25e3093eb30 Mon Sep 17 00:00:00 2001 From: Alex Speller <1217+alexspeller@users.noreply.github.com> Date: Mon, 17 Feb 2025 12:17:53 -0100 Subject: [PATCH] Make scroll preservation optional --- .github/CONTRIBUTING.md | 10 +++++++++- packages/core/src/eventHandler.ts | 10 ++++++---- packages/core/src/page.ts | 4 ++-- packages/core/src/router.ts | 4 ++-- packages/core/src/types.ts | 7 +++++++ packages/react/src/App.ts | 2 ++ packages/svelte/src/components/App.svelte | 3 +++ packages/vue3/src/app.ts | 4 +++- 8 files changed, 34 insertions(+), 10 deletions(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index dcc0c3063..689747d43 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -64,7 +64,15 @@ php artisan inertia:start-ssr Inertia.js uses [Playwright](https://playwright.dev/) for testing. To run the tests, use the following command: ```sh -cd tests && npx playwright test +npx playwright install # install playwright with system-wide browser dependencies + +# install packages for the test app +cd tests/app +npm install + +# run tests +cd .. +npx playwright test ``` ## Publishing diff --git a/packages/core/src/eventHandler.ts b/packages/core/src/eventHandler.ts index 4b33dbc19..70dfbdd05 100644 --- a/packages/core/src/eventHandler.ts +++ b/packages/core/src/eventHandler.ts @@ -3,7 +3,7 @@ import { fireNavigateEvent } from './events' import { history } from './history' import { page as currentPage } from './page' import { Scroll } from './scroll' -import { GlobalEvent, GlobalEventNames, GlobalEventResult, InternalEvent } from './types' +import { EventHandlerInitParams, GlobalEvent, GlobalEventNames, GlobalEventResult, InternalEvent } from './types' import { hrefToUrl } from './url' class EventHandler { @@ -12,13 +12,15 @@ class EventHandler { listener: VoidFunction }[] = [] - public init() { + public init({ handleScroll }: EventHandlerInitParams) { if (typeof window !== 'undefined') { window.addEventListener('popstate', this.handlePopstateEvent.bind(this)) - window.addEventListener('scroll', debounce(Scroll.onWindowScroll.bind(Scroll), 100), true) + if (handleScroll) { + window.addEventListener('scroll', debounce(Scroll.onWindowScroll.bind(Scroll), 100), true) + } } - if (typeof document !== 'undefined') { + if (typeof document !== 'undefined' && handleScroll) { document.addEventListener('scroll', debounce(Scroll.onScroll.bind(Scroll), 100), true) } } diff --git a/packages/core/src/page.ts b/packages/core/src/page.ts index f53f23dd4..4a80793fe 100644 --- a/packages/core/src/page.ts +++ b/packages/core/src/page.ts @@ -4,12 +4,12 @@ import { history } from './history' import { Scroll } from './scroll' import { Component, + CurrentPageInitParams, Page, PageEvent, PageHandler, PageResolver, PreserveStateOption, - RouterInitParams, VisitOptions, } from './types' import { hrefToUrl, isSameUrlWithoutHash } from './url' @@ -26,7 +26,7 @@ class CurrentPage { protected isFirstPageLoad = true protected cleared = false - public init({ initialPage, swapComponent, resolveComponent }: RouterInitParams) { + public init({ initialPage, swapComponent, resolveComponent }: CurrentPageInitParams) { this.page = initialPage this.swapComponent = swapComponent this.resolveComponent = resolveComponent diff --git a/packages/core/src/router.ts b/packages/core/src/router.ts index f1f3c1cc8..6e05f136c 100644 --- a/packages/core/src/router.ts +++ b/packages/core/src/router.ts @@ -43,7 +43,7 @@ export class Router { interruptible: false, }) - public init({ initialPage, resolveComponent, swapComponent }: RouterInitParams): void { + public init({ initialPage, resolveComponent, swapComponent, handleScroll }: RouterInitParams): void { currentPage.init({ initialPage, resolveComponent, @@ -52,7 +52,7 @@ export class Router { InitialVisit.handle() - eventHandler.init() + eventHandler.init({ handleScroll }) eventHandler.on('missingHistoryItem', () => { if (typeof window !== 'undefined') { diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index 8537b269b..c7663b90b 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -239,6 +239,13 @@ export type RouterInitParams = { initialPage: Page resolveComponent: PageResolver swapComponent: PageHandler + handleScroll: boolean +} + +export type CurrentPageInitParams = Omit + +export type EventHandlerInitParams = { + handleScroll: boolean } export type PendingVisitOptions = { diff --git a/packages/react/src/App.ts b/packages/react/src/App.ts index c073d3b8a..5dc9437f2 100755 --- a/packages/react/src/App.ts +++ b/packages/react/src/App.ts @@ -10,6 +10,7 @@ export default function App({ resolveComponent, titleCallback, onHeadUpdate, + handleScroll, }) { const [current, setCurrent] = useState({ component: initialComponent || null, @@ -29,6 +30,7 @@ export default function App({ router.init({ initialPage, resolveComponent, + handleScroll, swapComponent: async ({ component, page, preserveState }) => { setCurrent((current) => ({ component, diff --git a/packages/svelte/src/components/App.svelte b/packages/svelte/src/components/App.svelte index df454db00..30225f56f 100644 --- a/packages/svelte/src/components/App.svelte +++ b/packages/svelte/src/components/App.svelte @@ -5,6 +5,7 @@ export interface InertiaAppProps { initialComponent: ResolvedComponent initialPage: Page + handleScroll: boolean resolveComponent: ComponentResolver } @@ -18,6 +19,7 @@ export let initialComponent: InertiaAppProps['initialComponent'] export let initialPage: InertiaAppProps['initialPage'] export let resolveComponent: InertiaAppProps['resolveComponent'] + export let handleScroll: InertiaAppProps['handleScroll'] let component = initialComponent let key: number | null = null @@ -32,6 +34,7 @@ router.init({ initialPage, resolveComponent, + handleScroll, swapComponent: async (args) => { component = args.component as ResolvedComponent page = args.page diff --git a/packages/vue3/src/app.ts b/packages/vue3/src/app.ts index 365465083..c78bdbabf 100755 --- a/packages/vue3/src/app.ts +++ b/packages/vue3/src/app.ts @@ -18,6 +18,7 @@ import useForm from './useForm' export interface InertiaAppProps { initialPage: Page initialComponent?: object + handleScroll?: boolean resolveComponent?: (name: string) => DefineComponent | Promise titleCallback?: (title: string) => string onHeadUpdate?: (elements: string[]) => void @@ -57,7 +58,7 @@ const App: InertiaApp = defineComponent({ default: () => () => {}, }, }, - setup({ initialPage, initialComponent, resolveComponent, titleCallback, onHeadUpdate }) { + setup({ initialPage, initialComponent, resolveComponent, titleCallback, onHeadUpdate, handleScroll }) { component.value = initialComponent ? markRaw(initialComponent) : null page.value = initialPage key.value = null @@ -69,6 +70,7 @@ const App: InertiaApp = defineComponent({ router.init({ initialPage, resolveComponent, + handleScroll, swapComponent: async (args: VuePageHandlerArgs) => { component.value = markRaw(args.component) page.value = args.page