Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -45,19 +45,31 @@ export interface SearchParamsOptions {
/**
* The name of the parameter used to store compressed data when compression is enabled.
* You can customize this to avoid conflicts with your schema parameters.
* For example, if your schema already uses '_data', you might want to use '_compressed' or another unique name.
*
* For example, if your schema already uses '_data', you might want to use '_compressed'
* or another unique name.
*
* @default '_data'
*/
compressedParamName?: string;

/**
* Controls whether to update the URL when parameters change.
* If true (default), changes to parameters will update the URL.
* If false, parameters will only be stored in memory without updating the URL.
* Note: When false, compress option will be ignored.
* If `true` (default), changes to parameters will update the URL.
* If `false`, parameters will only be stored in memory without updating the URL.
*
* Note: When `false`, compress option will be ignored.
* @default true
*/
updateURL?: boolean;

/**
* If `true`, the scroll position will be preserved when the URL is updated.
*
* If `false`, the scroll position will be reset to the top when the URL is updated.
* @default false
*/
noScroll?: boolean;
}

/**
Expand Down Expand Up @@ -320,6 +332,7 @@ class SearchParams<Schema extends StandardSchemaV1> {
compress: false,
compressedParamName: "_data",
updateURL: true,
noScroll: false,
...options,
};

Expand Down Expand Up @@ -382,6 +395,7 @@ class SearchParams<Schema extends StandardSchemaV1> {
*
* Call this when the component unmounts to prevent memory leaks from debounce timers.
*
* @example
* Example in a Svelte component with Svelte 5 runes:
* ```svelte
* <script>
Expand Down Expand Up @@ -573,7 +587,7 @@ class SearchParams<Schema extends StandardSchemaV1> {
} else {
// For URL updates, navigate to empty search
if (!BROWSER) return;
goto("?", { replaceState: true });
goto("?", { replaceState: true, noScroll: this.#options.noScroll });
}
}
}
Expand Down Expand Up @@ -623,9 +637,8 @@ class SearchParams<Schema extends StandardSchemaV1> {
const newSearchParams = this.#createSearchParams(searchParams, isInMemory);

for (const key of Object.keys(updates)) {
if (!this.has(key)) {
continue; // Skip keys not in schema
}
// Skip keys not in schema
if (!this.has(key)) continue;

const validatedValue = validatedValues[key];

Expand Down Expand Up @@ -694,7 +707,8 @@ class SearchParams<Schema extends StandardSchemaV1> {
const gotoOptions = !this.#options.pushHistory
? { replaceState: true, keepFocus: true }
: { keepFocus: true };
goto("?" + params.toString(), gotoOptions);

goto("?" + params.toString(), { ...gotoOptions, noScroll: this.#options.noScroll });
};

// If debounce is set, delay the URL update
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ interface Scenario {
route: string;
showDefaults?: boolean;
noHistory?: boolean;
noScroll?: boolean;
debounce?: boolean;
compress?: boolean;
memory?: boolean;
Expand All @@ -34,6 +35,7 @@ const scenarios: Scenario[] = [
compress: true,
},
{ name: "memory", route: "/test-search/memory", memory: true },
{ name: "no-scroll", route: "/test-search/no-scroll", noScroll: true },
];

// Consistent helper functions using getByTestId
Expand Down Expand Up @@ -151,6 +153,18 @@ test.describe("useSearchParams scenarios", () => {
await expect(pageCount(page)).toHaveText("2");
});
}

if (s.noScroll) {
test("keeping scroll position", async ({ page }) => {
// Scroll down
await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight));
const scrollY = await page.evaluate(() => window.scrollY);

// Check scroll position is maintained
const newScrollY = await page.evaluate(() => window.scrollY);
expect(newScrollY).toBe(scrollY);
});
}
});
}
});
9 changes: 9 additions & 0 deletions sites/docs/src/content/utilities/use-search-params.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,8 @@ access to URL search parameters through direct property access.
is `_data`.
- `updateURL` (boolean): When true (default), the URL is updated when parameters change. When false,
only in-memory parameters are updated.
- `noScroll` (boolean): When true, the scroll position is preserved when the URL is updated. This
prevents the page from jumping to the top on URL changes. Default is false.

Example with [Zod](https://zod.dev/):

Expand Down Expand Up @@ -390,6 +392,13 @@ interface SearchParamsOptions {
* @default true
*/
updateURL?: boolean;

/**
* If true, the page will not scroll to the top when the URL is updated.
* This is useful if you want to maintain the user's scroll position during parameter changes.
* @default false
*/
noScroll?: boolean;
}

type ReturnUseSearchParams<Schema extends StandardSchemaV1> = {
Expand Down