Skip to content

Commit

Permalink
feat: sorting search params before navigating
Browse files Browse the repository at this point in the history
  • Loading branch information
paoloricciuti committed Dec 16, 2023
1 parent be89f9b commit 6ce9e08
Show file tree
Hide file tree
Showing 7 changed files with 224 additions and 73 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ node_modules

# Local Netlify folder
.netlify
test-results
149 changes: 81 additions & 68 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ The simplest and most effective way to use this library is by importing the meth

```svelte
<script lang="ts">
import { queryParam } from "sveltekit-search-params";
import { queryParam } from 'sveltekit-search-params';
const username = queryParam("username");
const username = queryParam('username');
</script>
Your username is {$username}
Expand All @@ -62,9 +62,9 @@ Reading query parameters is cool but you know what is even cooler? Writing query

```svelte
<script lang="ts">
import { queryParam } from "sveltekit-search-params";
import { queryParam } from 'sveltekit-search-params';
const username = queryParam("username");
const username = queryParam('username');
</script>
Your username is {$username}
Expand All @@ -75,16 +75,18 @@ or if you prefer

```svelte
<script lang="ts">
import { queryParam } from "sveltekit-search-params";
import { queryParam } from 'sveltekit-search-params';
const username = queryParam("username");
const username = queryParam('username');
</script>
Your username is {$username}
<input value={$username} on:input={(e)=>{
$username = e.target.value;
}} />
<input
value={$username}
on:input={(e) => {
$username = e.target.value;
}}
/>
```

### Encoding and decoding
Expand All @@ -93,16 +95,16 @@ By default query parameters are strings but more often than not tho we are not w

```svelte
<script lang="ts">
import { queryParam } from "sveltekit-search-params";
import { queryParam } from 'sveltekit-search-params';
const count = queryParam("count", {
encode: (value: number) => value.toString(),
decode: (value: string | null) => value ? parseInt(value) : null,
});
const count = queryParam('count', {
encode: (value: number) => value.toString(),
decode: (value: string | null) => (value ? parseInt(value) : null),
});
</script>
The count is {$count}
<input bind:value={$count} type="number"/>
<input bind:value={$count} type="number" />
```

this time $count would be of type number and the deconding function it's what's used to update the url when you write to the store.
Expand All @@ -113,17 +115,17 @@ Sometimes when we want to create a new variable we like to pass a default value.

```svelte
<script lang="ts">
import { queryParam } from "sveltekit-search-params";
import { queryParam } from 'sveltekit-search-params';
const count = queryParam("count", {
encode: (value: number) => value.toString(),
decode: (value: string | null) => value ? parseInt(value) : null,
defaultValue: 10,
});
const count = queryParam('count', {
encode: (value: number) => value.toString(),
decode: (value: string | null) => (value ? parseInt(value) : null),
defaultValue: 10,
});
</script>
The count is {$count}
<input bind:value={$count} type="number"/>
<input bind:value={$count} type="number" />
```

this will make the query parameter change as soon as the page is rendered on the browser (the query parameter will change only if it's not already present and only the first time the application render).
Expand All @@ -138,13 +140,13 @@ Write an encode and decode function may seem trivial but it's tedious for sure.

```svelte
<script lang="ts">
import { ssp, queryParam } from "sveltekit-search-params";
import { ssp, queryParam } from 'sveltekit-search-params';
const count = queryParam("count", ssp.number());
const count = queryParam('count', ssp.number());
</script>
The count is {$count}
<input bind:value={$count} type="number"/>
<input bind:value={$count} type="number" />
```

this code will produce the same output as the code written above but far more readable and easier to read. You can find all the exports documented in the section [ssp - Helpers](#ssp---helpers).
Expand All @@ -153,13 +155,13 @@ You can also pass a default value to the function that will be the defaultValue

```svelte
<script lang="ts">
import { ssp, queryParam } from "sveltekit-search-params";
import { ssp, queryParam } from 'sveltekit-search-params';
const count = queryParam("count", ssp.number(10));
const count = queryParam('count', ssp.number(10));
</script>
The count is {$count}
<input bind:value={$count} type="number"/>
<input bind:value={$count} type="number" />
```

### Simple case (all parameters)
Expand All @@ -168,9 +170,9 @@ You can use the function queryParameters to get an object containing all the pre

```svelte
<script lang="ts">
import { queryParameters } from "sveltekit-search-params";
import { queryParameters } from 'sveltekit-search-params';
const store = queryParameters();
const store = queryParameters();
</script>
<pre>
Expand All @@ -195,17 +197,20 @@ Just like with the single parameter case you can just update the store and the U

```svelte
<script lang="ts">
import { queryParameters } from "sveltekit-search-params";
import { queryParameters } from 'sveltekit-search-params';
const store = queryParameters();
const store = queryParameters();
</script>
<pre>
{JSON.stringify($store, null, 2)}
</pre>
<input value={$store.username} on:input={(e)=>{
$store.username = e.target.value;
}} />
<input
value={$store.username}
on:input={(e) => {
$store.username = e.target.value;
}}
/>
```

writing in the input will update the state and the URL at the same time.
Expand All @@ -216,11 +221,11 @@ Most of the times if you need to read from query parameters you are expecting so

```svelte
<script lang="ts">
import { queryParameters } from "sveltekit-search-params";
import { queryParameters } from 'sveltekit-search-params';
const store = queryParameters({
username: true,
});
const store = queryParameters({
username: true,
});
</script>
<pre>
Expand Down Expand Up @@ -254,16 +259,17 @@ The parameter passed to `queryParameters` can aslo be used to specify the encodi

```svelte
<script lang="ts">
import { queryParameters } from "sveltekit-search-params";
const store = queryParameters({
username: true,
isCool: {
encode: (booleanValue) => booleanValue.toString(),
decode: (stringValue) => stringValue !== null && stringValue !== "false",
defautValue: true,
}
});
import { queryParameters } from 'sveltekit-search-params';
const store = queryParameters({
username: true,
isCool: {
encode: (booleanValue) => booleanValue.toString(),
decode: (stringValue) =>
stringValue !== null && stringValue !== 'false',
defautValue: true,
},
});
</script>
<pre>
Expand Down Expand Up @@ -297,12 +303,12 @@ Obviously also in this case you can use the helpers functions provided inside `s

```svelte
<script lang="ts">
import { ssp, queryParameters } from "sveltekit-search-params";
import { ssp, queryParameters } from 'sveltekit-search-params';
const store = queryParameters({
username: true,
isCool: ssp.boolean(true),
});
const store = queryParameters({
username: true,
isCool: ssp.boolean(true),
});
</script>
<pre>
Expand Down Expand Up @@ -385,25 +391,32 @@ The number of milliseconds to delay the writing of the history when the state ch

A boolean defining if the history have to be written at all. If set to false no new history entries will be written to the history stack (the URL will still update but the user will not be able to go back with the browser).

### sort

Whenever you interacts with a store it navigates for you. By default the search params are sorted to allow for better cache-ability. You can disable this behavior by passing `false` to this option. Keep in mind that this is a per-store settings. This mean that if you interact with a store that has this option set to `false` and than interact with one that has this option set to `true` (the default) the resulting URL will still have the search params sorted.

### How to use it

To set the configuration object you can pass it as a third parameter in case of `queryParam` or the second in case of `queryParameters`.

```svelte
<script lang="ts">
import { ssp, queryParameters, queryParam } from "sveltekit-search-params";
const name = queryParam("name", ssp.string(), {
debounceHistory: 500, //a new history entry will be created after 500ms of this store not changing
});
const count = queryParam("count", ssp.number(), {
debounceHistory: 1500, //a new history entry will be created after 1500ms of this store not changing
})
const store = queryParameters({
username: true,
isCool: ssp.boolean(true),
}, {
pushHistory: false, //no new history entries for this store
});
import { ssp, queryParameters, queryParam } from 'sveltekit-search-params';
const name = queryParam('name', ssp.string(), {
debounceHistory: 500, //a new history entry will be created after 500ms of this store not changing
});
const count = queryParam('count', ssp.number(), {
debounceHistory: 1500, //a new history entry will be created after 1500ms of this store not changing
});
const store = queryParameters(
{
username: true,
isCool: ssp.boolean(true),
},
{
pushHistory: false, //no new history entries for this store
},
);
</script>
```

Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,10 @@
"format": "prettier --write .",
"publish": "pnpm run build && changeset publish",
"test": "npm run test:integration && npm run test:unit",
"test:integration:ui": "playwright test --ui",
"test:integration": "playwright test",
"test:unit": "vitest"
"test:unit": "vitest",
"changeset": "changeset"
},
"devDependencies": {
"@changesets/cli": "^2.26.0",
Expand Down
19 changes: 19 additions & 0 deletions playground/src/routes/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
const bools = queryParam('bools', ssp.boolean());
const obj = queryParam('obj', ssp.object<{ str: string }>());
const arr = queryParam('arr', ssp.array<number>());
const arr_unordered = queryParam('arr-unordered', ssp.array<number>(), {
sort: false,
});
const lz = queryParam('lz', ssp.lz<string>());
</script>

Expand Down Expand Up @@ -44,6 +47,22 @@
{/each}
</ul>

<button
on:click={() => {
if (!$arr_unordered) {
$arr_unordered = [];
}
$arr_unordered.push($arr_unordered.length);
$arr_unordered = $arr_unordered;
}}
data-testid="arr-unordered-input">Add unordered array</button
>
<ul>
{#each $arr_unordered ?? [] as num}
<li data-testid="arr-unordered">{num}</li>
{/each}
</ul>

<input data-testid="lz-input" bind:value={$lz} />
<div data-testid="lz">{$lz}</div>

Expand Down
27 changes: 27 additions & 0 deletions playground/src/routes/queryparameters/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,15 @@
arr: ssp.array<number>(),
lz: ssp.lz<string>(),
});
const unordered_store = queryParameters(
{
'arr-unordered': ssp.array<number>(),
},
{
sort: false,
},
);
</script>

<input data-testid="str-input" bind:value={$store.str} />
Expand Down Expand Up @@ -46,6 +55,24 @@
{/each}
</ul>

<button
on:click={() => {
if (!$unordered_store['arr-unordered']) {
$unordered_store['arr-unordered'] = [];
}
$unordered_store['arr-unordered'].push(
$unordered_store['arr-unordered'].length,
);
$unordered_store['arr-unordered'] = $unordered_store['arr-unordered'];
}}
data-testid="arr-unordered-input">Add unordered array</button
>
<ul>
{#each $unordered_store['arr-unordered'] ?? [] as num}
<li data-testid="arr-unordered">{num}</li>
{/each}
</ul>

<input data-testid="lz-input" bind:value={$store.lz} />
<div data-testid="lz">{$store.lz}</div>

Expand Down
Loading

0 comments on commit 6ce9e08

Please sign in to comment.