use-prms 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +60 -26
- package/dist/hash.cjs +57 -4
- package/dist/hash.cjs.map +1 -1
- package/dist/hash.d.cts +1 -1
- package/dist/hash.d.ts +1 -1
- package/dist/hash.js +56 -5
- package/dist/hash.js.map +1 -1
- package/dist/index.cjs +57 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +12 -1
- package/dist/index.d.ts +12 -1
- package/dist/index.js +56 -5
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,8 +1,26 @@
|
|
|
1
1
|
# use-prms
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/use-prms)
|
|
4
|
+
[](https://github.com/runsascoded/use-prms/blob/main/LICENSE)
|
|
5
|
+
[](https://bundlephobia.com/package/use-prms)
|
|
6
|
+
|
|
7
|
+
Type-safe URL-parameter (query and hash) management with minimal, human-readable encoding and decoding.
|
|
8
|
+
|
|
9
|
+
<!-- `toc` -->
|
|
10
|
+
- [Features](#features)
|
|
11
|
+
- [Installation](#install)
|
|
12
|
+
- [Quick Start](#quick-start)
|
|
13
|
+
- [Built-in Param Types](#param-types)
|
|
14
|
+
- [Custom Params](#custom)
|
|
15
|
+
- [Batch Updates](#batch)
|
|
16
|
+
- [URL Encoding](#encoding)
|
|
17
|
+
- [Framework-Agnostic Core](#core)
|
|
18
|
+
- [Hash Params](#hash)
|
|
19
|
+
- [API Reference](#api)
|
|
20
|
+
- [Examples](#examples)
|
|
21
|
+
- [License](#license)
|
|
22
|
+
|
|
23
|
+
## Features <a id="features"></a>
|
|
6
24
|
|
|
7
25
|
- 🎯 **Type-safe**: Full TypeScript support with generic `Param<T>` interface
|
|
8
26
|
- 📦 **Tiny URLs**: Smart encoding - omit defaults, use short keys, `+` for spaces
|
|
@@ -13,15 +31,17 @@ Type-safe URL query parameter management with minimal, human-readable encoding.
|
|
|
13
31
|
- 🔁 **Multi-value params**: Support for repeated keys like `?tag=a&tag=b`
|
|
14
32
|
- #️⃣ **Hash params**: Use hash fragment (`#key=value`) instead of query string
|
|
15
33
|
|
|
16
|
-
## Installation
|
|
34
|
+
## Installation <a id="install"></a>
|
|
17
35
|
|
|
18
36
|
```bash
|
|
19
37
|
npm install use-prms
|
|
20
|
-
|
|
38
|
+
```
|
|
39
|
+
Or:
|
|
40
|
+
```bash
|
|
21
41
|
pnpm add use-prms
|
|
22
42
|
```
|
|
23
43
|
|
|
24
|
-
## Quick Start
|
|
44
|
+
## Quick Start <a id="quick-start"></a>
|
|
25
45
|
|
|
26
46
|
```typescript
|
|
27
47
|
import { useUrlParam, boolParam, stringParam, intParam } from 'use-prms'
|
|
@@ -44,7 +64,7 @@ function MyComponent() {
|
|
|
44
64
|
}
|
|
45
65
|
```
|
|
46
66
|
|
|
47
|
-
## Built-in Param Types
|
|
67
|
+
## Built-in Param Types <a id="param-types"></a>
|
|
48
68
|
|
|
49
69
|
### Boolean
|
|
50
70
|
```typescript
|
|
@@ -128,7 +148,7 @@ const [page, setPage] = useUrlParam('p', paginationParam(20))
|
|
|
128
148
|
// { offset: 100, pageSize: 50 } → ?p=100+50
|
|
129
149
|
```
|
|
130
150
|
|
|
131
|
-
## Custom Params
|
|
151
|
+
## Custom Params <a id="custom"></a>
|
|
132
152
|
|
|
133
153
|
Create your own param encoders/decoders:
|
|
134
154
|
|
|
@@ -156,7 +176,7 @@ const [date, setDate] = useUrlParam('d', dateParam)
|
|
|
156
176
|
// ?d=251123 → Date(2025, 10, 23)
|
|
157
177
|
```
|
|
158
178
|
|
|
159
|
-
## Batch Updates
|
|
179
|
+
## Batch Updates <a id="batch"></a>
|
|
160
180
|
|
|
161
181
|
Use `useUrlParams()` to update multiple parameters atomically:
|
|
162
182
|
|
|
@@ -173,7 +193,7 @@ const { values, setValues } = useUrlParams({
|
|
|
173
193
|
setValues({ page: 2, size: 50 })
|
|
174
194
|
```
|
|
175
195
|
|
|
176
|
-
## URL Encoding
|
|
196
|
+
## URL Encoding <a id="encoding"></a>
|
|
177
197
|
|
|
178
198
|
- **Spaces**: Encoded as `+` (standard form-urlencoded)
|
|
179
199
|
- **Defaults**: Omitted from URL (keeps URLs minimal)
|
|
@@ -187,23 +207,23 @@ setDevices(['gym', 'bedroom'])
|
|
|
187
207
|
// URL: ?d=gym+bedroom
|
|
188
208
|
```
|
|
189
209
|
|
|
190
|
-
## Framework-Agnostic Core
|
|
210
|
+
## Framework-Agnostic Core <a id="core"></a>
|
|
191
211
|
|
|
192
212
|
Use the core utilities without React:
|
|
193
213
|
|
|
194
214
|
```typescript
|
|
195
|
-
import { boolParam,
|
|
215
|
+
import { boolParam, serializeMultiParams, parseMultiParams } from 'use-prms'
|
|
196
216
|
|
|
197
217
|
// Encode
|
|
198
|
-
const params = { z: boolParam.encode(true), d: 'gym' }
|
|
199
|
-
const search =
|
|
218
|
+
const params = { z: [boolParam.encode(true) ?? ''], d: ['gym'] }
|
|
219
|
+
const search = serializeMultiParams(params) // "z&d=gym"
|
|
200
220
|
|
|
201
221
|
// Decode
|
|
202
|
-
const parsed =
|
|
203
|
-
const zoom = boolParam.decode(parsed.z) // true
|
|
222
|
+
const parsed = parseMultiParams(window.location.search)
|
|
223
|
+
const zoom = boolParam.decode(parsed.z?.[0]) // true
|
|
204
224
|
```
|
|
205
225
|
|
|
206
|
-
## Hash Params
|
|
226
|
+
## Hash Params <a id="hash"></a>
|
|
207
227
|
|
|
208
228
|
Use hash fragment (`#key=value`) instead of query string (`?key=value`):
|
|
209
229
|
|
|
@@ -217,7 +237,7 @@ const [zoom, setZoom] = useUrlParam('z', boolParam)
|
|
|
217
237
|
|
|
218
238
|
Same API, different URL location. Useful when query strings conflict with server routing or you want params to survive page reloads without server involvement.
|
|
219
239
|
|
|
220
|
-
## API Reference
|
|
240
|
+
## API Reference <a id="api"></a>
|
|
221
241
|
|
|
222
242
|
### `useUrlParam<T>(key: string, param: Param<T>, push?: boolean)`
|
|
223
243
|
|
|
@@ -301,20 +321,34 @@ type MultiParam<T> = {
|
|
|
301
321
|
- `getCurrentParams()`: Get current URL params (browser only)
|
|
302
322
|
- `updateUrl(params, push?)`: Update URL without reloading (browser only)
|
|
303
323
|
|
|
304
|
-
## Examples
|
|
324
|
+
## Examples <a id="examples"></a>
|
|
305
325
|
|
|
306
326
|
Projects using `use-prms`:
|
|
307
327
|
|
|
308
|
-
- [runsascoded
|
|
328
|
+
- **[awair.runsascoded.com]** – Air quality dashboard ([GitHub][awair-gh], [usage][awair-search])
|
|
329
|
+
|
|
330
|
+
Example: [`?d=+br&y=thZ&t=-3d`][awair-example]
|
|
331
|
+
- `d=+br`: devices (leading space = "include default")
|
|
332
|
+
- `y=thZ`: Y-axes config
|
|
333
|
+
- `t=-3d`: time range
|
|
309
334
|
|
|
310
|
-
|
|
311
|
-
- `d=+br`: show default device + "bedroom" (`+` encodes space, leading space means "include default")
|
|
312
|
-
- `y=thZ`: left axis = temp (`t`), right axis = humidity (`h`), Y-axes don't start from zero (`Z`)
|
|
313
|
-
- `t=-3d`: time range = last 3 days
|
|
335
|
+
- **[ctbk.dev]** – Citi Bike trip data explorer ([GitHub][ctbk-gh], [usage][ctbk-search])
|
|
314
336
|
|
|
315
|
-
[
|
|
337
|
+
- **[kbd.rbw.sh]** – Keyboard shortcut manager demo site ([GitHub][use-kbd-gh], [usage][use-kbd-search])
|
|
338
|
+
|
|
339
|
+
[awair.runsascoded.com]: https://awair.runsascoded.com
|
|
340
|
+
[awair-gh]: https://github.com/runsascoded/awair
|
|
341
|
+
[awair-search]: https://github.com/search?q=repo%3Arunsascoded%2Fawair+use-prms&type=code
|
|
316
342
|
[awair-example]: https://awair.runsascoded.com/?d=+br&y=thZ&t=-3d
|
|
317
343
|
|
|
318
|
-
|
|
344
|
+
[ctbk.dev]: https://ctbk.dev
|
|
345
|
+
[ctbk-gh]: https://github.com/hudcostreets/ctbk.dev
|
|
346
|
+
[ctbk-search]: https://github.com/search?q=repo%3Ahudcostreets%2Fctbk.dev+use-prms&type=code
|
|
347
|
+
|
|
348
|
+
[kbd.rbw.sh]: https://kbd.rbw.sh
|
|
349
|
+
[use-kbd-gh]: https://github.com/runsascoded/use-kbd
|
|
350
|
+
[use-kbd-search]: https://github.com/search?q=repo%3Arunsascoded%2Fuse-kbd+use-prms&type=code
|
|
351
|
+
|
|
352
|
+
## License <a id="license"></a>
|
|
319
353
|
|
|
320
354
|
MIT
|
package/dist/hash.cjs
CHANGED
|
@@ -30,6 +30,25 @@ function serializeMultiParams(params) {
|
|
|
30
30
|
}
|
|
31
31
|
return result;
|
|
32
32
|
}
|
|
33
|
+
var LOCATION_CHANGE_EVENT = "use-prms:locationchange";
|
|
34
|
+
var historyPatched = false;
|
|
35
|
+
function patchHistoryApi() {
|
|
36
|
+
if (typeof window === "undefined" || historyPatched) return;
|
|
37
|
+
historyPatched = true;
|
|
38
|
+
const originalPushState = history.pushState.bind(history);
|
|
39
|
+
const originalReplaceState = history.replaceState.bind(history);
|
|
40
|
+
history.pushState = function(state, title, url) {
|
|
41
|
+
originalPushState(state, title, url);
|
|
42
|
+
window.dispatchEvent(new CustomEvent(LOCATION_CHANGE_EVENT));
|
|
43
|
+
window.dispatchEvent(new PopStateEvent("popstate", { state }));
|
|
44
|
+
};
|
|
45
|
+
history.replaceState = function(state, title, url) {
|
|
46
|
+
originalReplaceState(state, title, url);
|
|
47
|
+
window.dispatchEvent(new CustomEvent(LOCATION_CHANGE_EVENT));
|
|
48
|
+
window.dispatchEvent(new PopStateEvent("popstate", { state }));
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
patchHistoryApi();
|
|
33
52
|
var queryStrategy = {
|
|
34
53
|
getRaw() {
|
|
35
54
|
if (typeof window === "undefined") return "";
|
|
@@ -47,7 +66,11 @@ var queryStrategy = {
|
|
|
47
66
|
if (typeof window === "undefined") return () => {
|
|
48
67
|
};
|
|
49
68
|
window.addEventListener("popstate", callback);
|
|
50
|
-
|
|
69
|
+
window.addEventListener(LOCATION_CHANGE_EVENT, callback);
|
|
70
|
+
return () => {
|
|
71
|
+
window.removeEventListener("popstate", callback);
|
|
72
|
+
window.removeEventListener(LOCATION_CHANGE_EVENT, callback);
|
|
73
|
+
};
|
|
51
74
|
}
|
|
52
75
|
};
|
|
53
76
|
var hashStrategy = {
|
|
@@ -70,12 +93,28 @@ var hashStrategy = {
|
|
|
70
93
|
};
|
|
71
94
|
window.addEventListener("hashchange", callback);
|
|
72
95
|
window.addEventListener("popstate", callback);
|
|
96
|
+
window.addEventListener(LOCATION_CHANGE_EVENT, callback);
|
|
73
97
|
return () => {
|
|
74
98
|
window.removeEventListener("hashchange", callback);
|
|
75
99
|
window.removeEventListener("popstate", callback);
|
|
100
|
+
window.removeEventListener(LOCATION_CHANGE_EVENT, callback);
|
|
76
101
|
};
|
|
77
102
|
}
|
|
78
103
|
};
|
|
104
|
+
function notifyLocationChange() {
|
|
105
|
+
if (typeof window === "undefined") return;
|
|
106
|
+
window.dispatchEvent(new CustomEvent(LOCATION_CHANGE_EVENT));
|
|
107
|
+
}
|
|
108
|
+
function clearParams(strategy = "query") {
|
|
109
|
+
if (typeof window === "undefined") return;
|
|
110
|
+
const url = new URL(window.location.href);
|
|
111
|
+
if (strategy === "hash") {
|
|
112
|
+
url.hash = "";
|
|
113
|
+
} else {
|
|
114
|
+
url.search = "";
|
|
115
|
+
}
|
|
116
|
+
window.history.replaceState({}, "", url.toString());
|
|
117
|
+
}
|
|
79
118
|
var defaultStrategy = queryStrategy;
|
|
80
119
|
function getDefaultStrategy() {
|
|
81
120
|
return defaultStrategy;
|
|
@@ -104,17 +143,29 @@ var boolParam = {
|
|
|
104
143
|
function intParam(init) {
|
|
105
144
|
return {
|
|
106
145
|
encode: (value) => value === init ? void 0 : value.toString(),
|
|
107
|
-
decode: (encoded) =>
|
|
146
|
+
decode: (encoded) => {
|
|
147
|
+
if (encoded === void 0 || encoded === "") return init;
|
|
148
|
+
const parsed = parseInt(encoded, 10);
|
|
149
|
+
return isNaN(parsed) ? init : parsed;
|
|
150
|
+
}
|
|
108
151
|
};
|
|
109
152
|
}
|
|
110
153
|
var optIntParam = {
|
|
111
154
|
encode: (value) => value === null ? void 0 : value.toString(),
|
|
112
|
-
decode: (encoded) =>
|
|
155
|
+
decode: (encoded) => {
|
|
156
|
+
if (encoded === void 0 || encoded === "") return null;
|
|
157
|
+
const parsed = parseInt(encoded, 10);
|
|
158
|
+
return isNaN(parsed) ? null : parsed;
|
|
159
|
+
}
|
|
113
160
|
};
|
|
114
161
|
function floatParam(init) {
|
|
115
162
|
return {
|
|
116
163
|
encode: (value) => value === init ? void 0 : value.toString(),
|
|
117
|
-
decode: (encoded) =>
|
|
164
|
+
decode: (encoded) => {
|
|
165
|
+
if (encoded === void 0 || encoded === "") return init;
|
|
166
|
+
const parsed = parseFloat(encoded);
|
|
167
|
+
return isNaN(parsed) ? init : parsed;
|
|
168
|
+
}
|
|
118
169
|
};
|
|
119
170
|
}
|
|
120
171
|
function enumParam(init, values) {
|
|
@@ -473,6 +524,7 @@ function updateUrl(params, push = false) {
|
|
|
473
524
|
setDefaultStrategy(hashStrategy);
|
|
474
525
|
|
|
475
526
|
exports.boolParam = boolParam;
|
|
527
|
+
exports.clearParams = clearParams;
|
|
476
528
|
exports.codeParam = codeParam;
|
|
477
529
|
exports.codesParam = codesParam;
|
|
478
530
|
exports.defStringParam = defStringParam;
|
|
@@ -485,6 +537,7 @@ exports.intParam = intParam;
|
|
|
485
537
|
exports.multiFloatParam = multiFloatParam;
|
|
486
538
|
exports.multiIntParam = multiIntParam;
|
|
487
539
|
exports.multiStringParam = multiStringParam;
|
|
540
|
+
exports.notifyLocationChange = notifyLocationChange;
|
|
488
541
|
exports.numberArrayParam = numberArrayParam;
|
|
489
542
|
exports.optIntParam = optIntParam;
|
|
490
543
|
exports.paginationParam = paginationParam;
|
package/dist/hash.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core.ts","../src/params.ts","../src/multiParams.ts","../src/useUrlParam.ts","../src/index.ts","../src/hash.ts"],"names":["useRef","useSyncExternalStore","useCallback","encoded"],"mappings":"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","file":"hash.cjs","sourcesContent":["/**\n * Core multi-value operations and location strategies\n */\n\n/**\n * Multi-value encoded representation\n * An array of strings representing multiple values for a single URL parameter key\n */\nexport type MultiEncoded = string[]\n\n/**\n * Location strategy interface for abstracting URL storage location\n * (query string vs hash fragment)\n */\nexport interface LocationStrategy {\n /** Get raw string from location (for caching comparison) */\n getRaw(): string\n /** Parse current location to multi-value params */\n parse(): Record<string, MultiEncoded>\n /** Build URL string with updated params */\n buildUrl(base: URL, params: Record<string, MultiEncoded>): string\n /** Subscribe to location changes, returns unsubscribe function */\n subscribe(callback: () => void): () => void\n}\n\n/**\n * Parse URL string to multi-value params\n * Each key maps to an array of all values for that key\n */\nexport function parseMultiParams(source: string | URLSearchParams): Record<string, MultiEncoded> {\n const searchParams = typeof source === 'string'\n ? new URLSearchParams(source)\n : source\n\n const result: Record<string, MultiEncoded> = {}\n const keys = new Set(searchParams.keys())\n\n for (const key of keys) {\n result[key] = searchParams.getAll(key)\n }\n\n return result\n}\n\n/**\n * Serialize multi-value params to URL string format\n * Repeated keys are serialized as separate entries: key=a&key=b\n */\nexport function serializeMultiParams(params: Record<string, MultiEncoded>): string {\n const searchParams = new URLSearchParams()\n\n for (const [key, values] of Object.entries(params)) {\n for (const value of values) {\n if (value === '') {\n // Valueless params handled separately\n continue\n }\n searchParams.append(key, value)\n }\n }\n\n let result = searchParams.toString()\n\n // Handle valueless params (empty string values) manually\n const valuelessKeys = Object.entries(params)\n .filter(([_, values]) => values.includes(''))\n .map(([key, _]) => encodeURIComponent(key))\n\n if (valuelessKeys.length > 0) {\n const valuelessPart = valuelessKeys.join('&')\n result = result ? `${result}&${valuelessPart}` : valuelessPart\n }\n\n return result\n}\n\n/**\n * Query string location strategy\n * Reads/writes to window.location.search\n */\nexport const queryStrategy: LocationStrategy = {\n getRaw(): string {\n if (typeof window === 'undefined') return ''\n return window.location.search\n },\n\n parse(): Record<string, MultiEncoded> {\n if (typeof window === 'undefined') return {}\n return parseMultiParams(window.location.search)\n },\n\n buildUrl(base: URL, params: Record<string, MultiEncoded>): string {\n base.search = serializeMultiParams(params)\n return base.toString()\n },\n\n subscribe(callback: () => void): () => void {\n if (typeof window === 'undefined') return () => {}\n window.addEventListener('popstate', callback)\n return () => window.removeEventListener('popstate', callback)\n },\n}\n\n/**\n * Hash fragment location strategy\n * Reads/writes to window.location.hash\n * Hash is parsed as URLSearchParams format: #key=value&key2=value2\n */\nexport const hashStrategy: LocationStrategy = {\n getRaw(): string {\n if (typeof window === 'undefined') return ''\n return window.location.hash\n },\n\n parse(): Record<string, MultiEncoded> {\n if (typeof window === 'undefined') return {}\n const hash = window.location.hash\n // Remove leading # if present\n const hashString = hash.startsWith('#') ? hash.slice(1) : hash\n return parseMultiParams(hashString)\n },\n\n buildUrl(base: URL, params: Record<string, MultiEncoded>): string {\n base.hash = serializeMultiParams(params)\n return base.toString()\n },\n\n subscribe(callback: () => void): () => void {\n if (typeof window === 'undefined') return () => {}\n // Listen to both hashchange and popstate for hash navigation\n window.addEventListener('hashchange', callback)\n window.addEventListener('popstate', callback)\n return () => {\n window.removeEventListener('hashchange', callback)\n window.removeEventListener('popstate', callback)\n }\n },\n}\n\n// Default strategy (can be changed by entry points like hash.ts)\nlet defaultStrategy: LocationStrategy = queryStrategy\n\n/**\n * Get the current default location strategy\n */\nexport function getDefaultStrategy(): LocationStrategy {\n return defaultStrategy\n}\n\n/**\n * Set the default location strategy\n * Called by entry points (e.g., hash.ts sets this to hashStrategy)\n */\nexport function setDefaultStrategy(strategy: LocationStrategy): void {\n defaultStrategy = strategy\n}\n","/**\n * Built-in parameter types with smart defaults and minimal encoding\n */\n\nimport type { Encoded, Param } from './index.js'\n\n/**\n * Optional string parameter.\n * - undefined → not present\n * - empty string → ?key=\n * - non-empty → ?key=value\n */\nexport function stringParam(init?: string): Param<string | undefined> {\n return {\n encode: (value) => value === init ? undefined : value,\n decode: (encoded) => encoded === undefined ? init : encoded,\n }\n}\n\n/**\n * Required string parameter with default.\n * Omitted from URL when equal to default.\n */\nexport function defStringParam(init: string): Param<string> {\n return {\n encode: (value) => value === init ? undefined : value,\n decode: (encoded) => encoded ?? init,\n }\n}\n\n/**\n * Boolean parameter.\n * - true → ?key (valueless)\n * - false → not present\n */\nexport const boolParam: Param<boolean> = {\n encode: (value) => value ? '' : undefined,\n decode: (encoded) => encoded !== undefined,\n}\n\n/**\n * Integer parameter with default.\n * Omitted from URL when equal to default.\n */\nexport function intParam(init: number): Param<number> {\n return {\n encode: (value) => value === init ? undefined : value.toString(),\n decode: (encoded) => encoded !== undefined ? parseInt(encoded, 10) : init,\n }\n}\n\n/**\n * Optional integer parameter.\n * - null → not present\n * - number → ?key=123\n */\nexport const optIntParam: Param<number | null> = {\n encode: (value) => value === null ? undefined : value.toString(),\n decode: (encoded) => encoded !== undefined ? parseInt(encoded, 10) : null,\n}\n\n/**\n * Float parameter with default.\n * Omitted from URL when equal to default.\n */\nexport function floatParam(init: number): Param<number> {\n return {\n encode: (value) => value === init ? undefined : value.toString(),\n decode: (encoded) => encoded !== undefined ? parseFloat(encoded) : init,\n }\n}\n\n/**\n * Enum parameter with validation.\n * Omitted from URL when equal to default.\n * Invalid values fall back to default with console warning.\n */\nexport function enumParam<T extends string>(\n init: T,\n values: readonly T[]\n): Param<T> {\n const validSet = new Set(values)\n\n return {\n encode: (value) => {\n if (!validSet.has(value)) {\n console.warn(`Invalid enum value: ${value}, expected one of ${values.join(', ')}`)\n return undefined\n }\n return value === init ? undefined : value\n },\n decode: (encoded) => {\n if (encoded === undefined) return init\n if (!validSet.has(encoded as T)) {\n console.warn(`Invalid enum value: ${encoded}, expected one of ${values.join(', ')}. Using default: ${init}`)\n return init\n }\n return encoded as T\n },\n }\n}\n\n/**\n * String array parameter with delimiter.\n * Omitted from URL when equal to default.\n * Empty array encodes as empty string (?key=)\n */\nexport function stringsParam(\n init: string[] = [],\n delimiter = ' '\n): Param<string[]> {\n const initEncoded = init.join(delimiter)\n\n return {\n encode: (values) => {\n const encoded = values.join(delimiter)\n if (encoded === initEncoded) return undefined\n return encoded\n },\n decode: (encoded) => {\n if (encoded === undefined) return init\n if (encoded === '') return []\n return encoded.split(delimiter)\n },\n }\n}\n\n/**\n * Number array parameter.\n * Omitted from URL when equal to default.\n * Uses comma delimiter.\n */\nexport function numberArrayParam(init: number[] = []): Param<number[]> {\n const isEqual = (a: number[], b: number[]) =>\n a.length === b.length && a.every((v, i) => v === b[i])\n\n return {\n encode: (values) => {\n if (isEqual(values, init)) return undefined\n return values.map(v => v.toString()).join(',')\n },\n decode: (encoded) => {\n if (encoded === undefined) return init\n if (encoded === '') return []\n return encoded.split(',').map(v => parseFloat(v))\n },\n }\n}\n\n/**\n * Pagination parameter combining offset and page size.\n * Uses space (which encodes as + in URLs) as delimiter.\n *\n * Encoding rules:\n * - offset=0, pageSize=default → not present (undefined)\n * - offset=0, pageSize=custom → \" pageSize\" (e.g., \" 20\" → +20 in URL)\n * - offset>0, pageSize=default → \"offset\" (e.g., \"100\")\n * - offset>0, pageSize=custom → \"offset pageSize\" (e.g., \"100 20\" → 100+20 in URL)\n *\n * @param defaultPageSize - The default page size (omitted from URL when used)\n * @param validPageSizes - Optional array of valid page sizes for validation\n */\nexport type Pagination = { offset: number; pageSize: number }\n\nexport function paginationParam(\n defaultPageSize: number,\n validPageSizes?: readonly number[],\n): Param<Pagination> {\n return {\n encode: ({ offset, pageSize }) => {\n if (offset === 0 && pageSize === defaultPageSize) return undefined\n if (offset === 0) return ` ${pageSize}` // Space prefix → +pageSize in URL\n if (pageSize === defaultPageSize) return String(offset)\n return `${offset} ${pageSize}` // Space encodes as + in URL\n },\n decode: (encoded) => {\n if (!encoded) return { offset: 0, pageSize: defaultPageSize }\n const parts = encoded.split(' ') // URL + decodes to space\n // Handle \" pageSize\" case (offset 0 with custom page size)\n const offset = parts[0] === '' ? 0 : parseInt(parts[0], 10) || 0\n let pageSize = parts[1] ? parseInt(parts[1], 10) : defaultPageSize\n // Validate page size if validation array provided\n if (validPageSizes && !validPageSizes.includes(pageSize)) {\n pageSize = defaultPageSize\n }\n return { offset, pageSize }\n },\n }\n}\n\n/**\n * Code mapping for enum values - maps full values to short codes for compact URLs.\n * Can be specified as:\n * - Array of [value, code] tuples: [['Rides', 'r'], ['Minutes', 'm']]\n * - Object mapping values to codes: { Rides: 'r', Minutes: 'm' }\n */\nexport type CodeMap<T extends string> = [T, string][] | Record<T, string>\n\nfunction normalizeCodeMap<T extends string>(codeMap: CodeMap<T>): [T, string][] {\n if (Array.isArray(codeMap)) return codeMap\n return Object.entries(codeMap) as [T, string][]\n}\n\n/**\n * Single-value enum parameter with short code mapping.\n * Maps full enum values to abbreviated codes for compact URLs.\n * Omitted from URL when equal to default.\n *\n * @example\n * // ?y=r for \"Rides\", ?y=m for \"Minutes\", omitted for default \"Rides\"\n * codeParam('Rides', [['Rides', 'r'], ['Minutes', 'm']])\n * // or with object syntax:\n * codeParam('Rides', { Rides: 'r', Minutes: 'm' })\n */\nexport function codeParam<T extends string>(\n init: T,\n codeMap: CodeMap<T>,\n): Param<T> {\n const entries = normalizeCodeMap(codeMap)\n const valueToCode = new Map(entries)\n const codeToValue = new Map(entries.map(([v, c]) => [c, v]))\n\n return {\n encode: (value) => {\n if (value === init) return undefined\n return valueToCode.get(value) ?? value\n },\n decode: (encoded) => {\n if (encoded === undefined) return init\n return codeToValue.get(encoded) ?? init\n },\n }\n}\n\n/**\n * Multi-value parameter with short code mapping.\n * Maps full values to abbreviated codes for compact URLs.\n * Omitted from URL when all values are selected.\n *\n * @param allValues - Array of all possible values (used to detect \"all selected\")\n * @param codeMap - Mapping from values to short codes\n * @param separator - Delimiter between codes (default: '' for most compact URLs)\n *\n * @example\n * // Regions: ?r=nj for NYC+JC, ?r=njh or omitted for all three\n * codesParam(['NYC', 'JC', 'HOB'], [['NYC', 'n'], ['JC', 'j'], ['HOB', 'h']])\n * // or with object syntax and custom separator:\n * codesParam(['NYC', 'JC', 'HOB'], { NYC: 'n', JC: 'j', HOB: 'h' }, ',')\n */\nexport function codesParam<T extends string>(\n allValues: readonly T[],\n codeMap: CodeMap<T>,\n separator: string = '',\n): Param<T[]> {\n const entries = normalizeCodeMap(codeMap)\n const valueToCode = new Map(entries)\n const codeToValue = new Map(entries.map(([v, c]) => [c, v]))\n\n return {\n encode: (values) => {\n // Omit when all values selected\n if (values.length === allValues.length && allValues.every(v => values.includes(v))) {\n return undefined\n }\n return values.map(v => valueToCode.get(v) ?? v).join(separator)\n },\n decode: (encoded) => {\n if (encoded === undefined) return [...allValues]\n if (encoded === '') return []\n const codes = separator ? encoded.split(separator) : encoded.split('')\n return codes.map(c => codeToValue.get(c)).filter((v): v is T => v !== undefined)\n },\n }\n}\n","/**\n * Multi-value parameter types for handling repeated URL params\n * e.g., ?tag=a&tag=b&tag=c\n */\n\nimport type { MultiEncoded } from './core.js'\n\n/**\n * A bidirectional converter between a typed value and its multi-value URL representation.\n * Similar to Param<T> but works with string[] instead of string | undefined.\n */\nexport type MultiParam<T> = {\n encode: (value: T) => MultiEncoded\n decode: (encoded: MultiEncoded) => T\n}\n\n/**\n * Multi-value string array parameter.\n * Each string becomes a separate URL param with the same key.\n *\n * @example\n * // ?tag=a&tag=b&tag=c → ['a', 'b', 'c']\n * const [tags, setTags] = useMultiUrlParam('tag', multiStringParam())\n */\nexport function multiStringParam(init: string[] = []): MultiParam<string[]> {\n return {\n encode: (values) => {\n if (values.length === 0 && init.length === 0) return []\n if (arraysEqual(values, init)) return []\n return values\n },\n decode: (encoded) => {\n if (encoded.length === 0) return init\n return encoded\n },\n }\n}\n\n/**\n * Multi-value integer array parameter.\n * Each number becomes a separate URL param with the same key.\n *\n * @example\n * // ?id=1&id=2&id=3 → [1, 2, 3]\n * const [ids, setIds] = useMultiUrlParam('id', multiIntParam())\n */\nexport function multiIntParam(init: number[] = []): MultiParam<number[]> {\n return {\n encode: (values) => {\n if (values.length === 0 && init.length === 0) return []\n if (arraysEqual(values, init)) return []\n return values.map(v => v.toString())\n },\n decode: (encoded) => {\n if (encoded.length === 0) return init\n return encoded.map(v => parseInt(v, 10))\n },\n }\n}\n\n/**\n * Multi-value float array parameter.\n * Each number becomes a separate URL param with the same key.\n *\n * @example\n * // ?val=1.5&val=2.7 → [1.5, 2.7]\n * const [vals, setVals] = useMultiUrlParam('val', multiFloatParam())\n */\nexport function multiFloatParam(init: number[] = []): MultiParam<number[]> {\n return {\n encode: (values) => {\n if (values.length === 0 && init.length === 0) return []\n if (arraysEqual(values, init)) return []\n return values.map(v => v.toString())\n },\n decode: (encoded) => {\n if (encoded.length === 0) return init\n return encoded.map(v => parseFloat(v))\n },\n }\n}\n\n/** Helper to compare arrays for equality */\nfunction arraysEqual<T>(a: T[], b: T[]): boolean {\n return a.length === b.length && a.every((v, i) => v === b[i])\n}\n","/**\n * React hooks for managing URL parameters\n */\n\nimport { useCallback, useRef, useSyncExternalStore } from 'react'\nimport type { Param } from './index.js'\nimport type { LocationStrategy, MultiEncoded } from './core.js'\nimport { getDefaultStrategy, serializeMultiParams } from './core.js'\nimport type { MultiParam } from './multiParams.js'\n\n/**\n * Cached snapshot to prevent infinite loops in useSyncExternalStore\n * Keyed by strategy (so query and hash don't share cache)\n */\nconst snapshotCache = new WeakMap<LocationStrategy, {\n raw: string\n snapshot: Record<string, MultiEncoded>\n}>()\n\n/**\n * Get URL snapshot for a given strategy\n * Returns cached snapshot if URL hasn't changed\n */\nfunction getSnapshot(strategy: LocationStrategy): Record<string, MultiEncoded> {\n const raw = strategy.getRaw()\n const cached = snapshotCache.get(strategy)\n\n if (cached && cached.raw === raw) {\n return cached.snapshot\n }\n\n const snapshot = strategy.parse()\n snapshotCache.set(strategy, { raw, snapshot })\n return snapshot\n}\n\n/**\n * Server-side snapshot (always empty)\n */\nfunction getServerSnapshot(): Record<string, MultiEncoded> {\n return {}\n}\n\n/**\n * Convert single-value Encoded to multi-value MultiEncoded\n */\nfunction singleToMulti(encoded: string | undefined): MultiEncoded {\n if (encoded === undefined) return []\n return [encoded]\n}\n\n/**\n * Convert multi-value MultiEncoded to single-value Encoded\n */\nfunction multiToSingle(multi: MultiEncoded): string | undefined {\n if (multi.length === 0) return undefined\n return multi[0]\n}\n\n/**\n * React hook for managing a single URL query parameter.\n *\n * @param key - Query parameter key\n * @param param - Param encoder/decoder\n * @param push - Use pushState (true) or replaceState (false) when updating\n * @returns Tuple of [value, setValue]\n *\n * @example\n * ```tsx\n * const [zoom, setZoom] = useUrlParam('z', boolParam)\n * const [device, setDevice] = useUrlParam('d', stringParam('default'))\n * ```\n */\nexport function useUrlParam<T>(\n key: string,\n param: Param<T>,\n push = false\n): [T, (value: T) => void] {\n const strategy = getDefaultStrategy()\n\n // Use ref to avoid recreating setValue when param changes\n const paramRef = useRef(param)\n paramRef.current = param\n\n // Subscribe to URL changes\n const urlParams = useSyncExternalStore(\n (cb) => strategy.subscribe(cb),\n () => getSnapshot(strategy),\n getServerSnapshot\n )\n\n // Memoize decoded value based on encoded string AND param identity\n // Re-decode if either the URL param string changes OR the param object changes\n // (e.g., deviceIdsParam depends on devices array which loads asynchronously)\n const encoded = multiToSingle(urlParams[key] ?? [])\n const cacheRef = useRef<{ encoded: typeof encoded; param: Param<T>; decoded: T } | null>(null)\n\n if (cacheRef.current === null || cacheRef.current.encoded !== encoded || cacheRef.current.param !== param) {\n cacheRef.current = { encoded, param, decoded: param.decode(encoded) }\n }\n const value = cacheRef.current.decoded\n\n // Update URL when value changes\n const setValue = useCallback(\n (newValue: T) => {\n if (typeof window === 'undefined') return\n\n const currentParams = strategy.parse()\n const encoded = paramRef.current.encode(newValue)\n\n // Update this parameter (single → multi)\n if (encoded === undefined) {\n delete currentParams[key]\n } else {\n currentParams[key] = [encoded]\n }\n\n // Build and update URL\n const url = new URL(window.location.href)\n const newUrl = strategy.buildUrl(url, currentParams)\n\n const method = push ? 'pushState' : 'replaceState'\n window.history[method]({}, '', newUrl)\n\n // Trigger events to notify other hooks\n window.dispatchEvent(new PopStateEvent('popstate'))\n },\n [key, push, strategy]\n )\n\n return [value, setValue]\n}\n\n/**\n * React hook for managing multiple URL query parameters together.\n * Updates are batched into a single history entry.\n *\n * @param params - Object mapping keys to Param types\n * @param push - Use pushState (true) or replaceState (false) when updating\n * @returns Object with decoded values and update function\n *\n * @example\n * ```tsx\n * const { values, setValues } = useUrlParams({\n * zoom: boolParam,\n * device: stringParam('default'),\n * count: intParam(10)\n * })\n *\n * // Update multiple params at once\n * setValues({ zoom: true, count: 20 })\n * ```\n */\nexport function useUrlParams<P extends Record<string, Param<any>>>(\n params: P,\n push = false\n): {\n values: { [K in keyof P]: P[K] extends Param<infer T> ? T : never }\n setValues: (updates: Partial<{ [K in keyof P]: P[K] extends Param<infer T> ? T : never }>) => void\n} {\n const strategy = getDefaultStrategy()\n\n // Subscribe to URL changes\n const urlParams = useSyncExternalStore(\n (cb) => strategy.subscribe(cb),\n () => getSnapshot(strategy),\n getServerSnapshot\n )\n\n // Decode all values from URL\n const values = Object.fromEntries(\n Object.entries(params).map(([key, param]) => [\n key,\n param.decode(multiToSingle(urlParams[key] ?? []))\n ])\n ) as { [K in keyof P]: P[K] extends Param<infer T> ? T : never }\n\n // Update multiple parameters at once\n const setValues = useCallback(\n (updates: Partial<{ [K in keyof P]: P[K] extends Param<infer T> ? T : never }>) => {\n if (typeof window === 'undefined') return\n\n const currentParams = strategy.parse()\n\n // Apply all updates\n for (const [key, value] of Object.entries(updates)) {\n const param = params[key]\n if (!param) continue\n\n const encoded = param.encode(value)\n if (encoded === undefined) {\n delete currentParams[key]\n } else {\n currentParams[key] = [encoded]\n }\n }\n\n // Build and update URL once\n const url = new URL(window.location.href)\n const newUrl = strategy.buildUrl(url, currentParams)\n\n const method = push ? 'pushState' : 'replaceState'\n window.history[method]({}, '', newUrl)\n\n // Trigger events to notify other hooks\n window.dispatchEvent(new PopStateEvent('popstate'))\n },\n [params, push, strategy]\n )\n\n return { values, setValues }\n}\n\n/**\n * React hook for managing a single multi-value URL parameter.\n * Supports repeated params like ?tag=a&tag=b&tag=c\n *\n * @param key - Query parameter key\n * @param param - MultiParam encoder/decoder\n * @param push - Use pushState (true) or replaceState (false) when updating\n * @returns Tuple of [value, setValue]\n *\n * @example\n * ```tsx\n * const [tags, setTags] = useMultiUrlParam('tag', multiStringParam())\n * // URL: ?tag=a&tag=b → tags = ['a', 'b']\n * ```\n */\nexport function useMultiUrlParam<T>(\n key: string,\n param: MultiParam<T>,\n push = false\n): [T, (value: T) => void] {\n const strategy = getDefaultStrategy()\n\n // Use ref to avoid recreating setValue when param changes\n const paramRef = useRef(param)\n paramRef.current = param\n\n // Subscribe to URL changes\n const urlParams = useSyncExternalStore(\n (cb) => strategy.subscribe(cb),\n () => getSnapshot(strategy),\n getServerSnapshot\n )\n\n // Decode current value from URL\n const value = param.decode(urlParams[key] ?? [])\n\n // Update URL when value changes\n const setValue = useCallback(\n (newValue: T) => {\n if (typeof window === 'undefined') return\n\n const currentParams = strategy.parse()\n const encoded = paramRef.current.encode(newValue)\n\n // Update this parameter\n if (encoded.length === 0) {\n delete currentParams[key]\n } else {\n currentParams[key] = encoded\n }\n\n // Build and update URL\n const url = new URL(window.location.href)\n const newUrl = strategy.buildUrl(url, currentParams)\n\n const method = push ? 'pushState' : 'replaceState'\n window.history[method]({}, '', newUrl)\n\n // Trigger events to notify other hooks\n window.dispatchEvent(new PopStateEvent('popstate'))\n },\n [key, push, strategy]\n )\n\n return [value, setValue]\n}\n\n/**\n * React hook for managing multiple multi-value URL parameters together.\n * Updates are batched into a single history entry.\n *\n * @param params - Object mapping keys to MultiParam types\n * @param push - Use pushState (true) or replaceState (false) when updating\n * @returns Object with decoded values and update function\n *\n * @example\n * ```tsx\n * const { values, setValues } = useMultiUrlParams({\n * tags: multiStringParam(),\n * ids: multiIntParam()\n * })\n *\n * // Update multiple multi-value params at once\n * setValues({ tags: ['a', 'b'], ids: [1, 2, 3] })\n * ```\n */\nexport function useMultiUrlParams<P extends Record<string, MultiParam<any>>>(\n params: P,\n push = false\n): {\n values: { [K in keyof P]: P[K] extends MultiParam<infer T> ? T : never }\n setValues: (updates: Partial<{ [K in keyof P]: P[K] extends MultiParam<infer T> ? T : never }>) => void\n} {\n const strategy = getDefaultStrategy()\n\n // Subscribe to URL changes\n const urlParams = useSyncExternalStore(\n (cb) => strategy.subscribe(cb),\n () => getSnapshot(strategy),\n getServerSnapshot\n )\n\n // Decode all values from URL\n const values = Object.fromEntries(\n Object.entries(params).map(([key, param]) => [\n key,\n param.decode(urlParams[key] ?? [])\n ])\n ) as { [K in keyof P]: P[K] extends MultiParam<infer T> ? T : never }\n\n // Update multiple parameters at once\n const setValues = useCallback(\n (updates: Partial<{ [K in keyof P]: P[K] extends MultiParam<infer T> ? T : never }>) => {\n if (typeof window === 'undefined') return\n\n const currentParams = strategy.parse()\n\n // Apply all updates\n for (const [key, value] of Object.entries(updates)) {\n const param = params[key]\n if (!param) continue\n\n const encoded = param.encode(value)\n if (encoded.length === 0) {\n delete currentParams[key]\n } else {\n currentParams[key] = encoded\n }\n }\n\n // Build and update URL once\n const url = new URL(window.location.href)\n const newUrl = strategy.buildUrl(url, currentParams)\n\n const method = push ? 'pushState' : 'replaceState'\n window.history[method]({}, '', newUrl)\n\n // Trigger events to notify other hooks\n window.dispatchEvent(new PopStateEvent('popstate'))\n },\n [params, push, strategy]\n )\n\n return { values, setValues }\n}\n","/**\n * Core types and utilities for URL parameter management\n */\n\n// Re-export core types and strategies\nexport type { MultiEncoded, LocationStrategy } from './core.js'\nexport {\n parseMultiParams,\n serializeMultiParams,\n queryStrategy,\n hashStrategy,\n getDefaultStrategy,\n setDefaultStrategy,\n} from './core.js'\n\n/**\n * Encodes a value to a URL query parameter string.\n * - undefined: parameter not present in URL\n * - \"\": valueless parameter (e.g., ?z)\n * - string: parameter with value (e.g., ?z=foo)\n */\nexport type Encoded = string | undefined\n\n/**\n * A bidirectional converter between a typed value and its URL representation.\n */\nexport type Param<T> = {\n encode: (value: T) => Encoded\n decode: (encoded: Encoded) => T\n}\n\n/**\n * Serialize query parameters to URL string.\n * Uses URLSearchParams for proper form-urlencoded format (space → +)\n * Handles valueless params (empty string → ?key without =) manually\n *\n * @deprecated For multi-value support, use serializeMultiParams instead\n */\nexport function serializeParams(params: Record<string, Encoded>): string {\n const searchParams = new URLSearchParams()\n\n for (const [key, value] of Object.entries(params)) {\n if (value === undefined) {\n // Skip undefined values\n continue\n } else if (value === '') {\n // Valueless param: ?key without =\n // URLSearchParams doesn't support this, so we'll handle manually\n continue\n } else {\n searchParams.set(key, value)\n }\n }\n\n let result = searchParams.toString()\n\n // Handle valueless params manually\n const valuelessKeys = Object.entries(params)\n .filter(([_, value]) => value === '')\n .map(([key, _]) => encodeURIComponent(key))\n\n if (valuelessKeys.length > 0) {\n const valuelessPart = valuelessKeys.join('&')\n result = result ? `${result}&${valuelessPart}` : valuelessPart\n }\n\n return result\n}\n\n/**\n * Parse query parameters from URL string or URLSearchParams.\n * Note: URLSearchParams treats ?z and ?z= identically (both as empty string).\n * Note: For repeated params, only the first value is returned.\n *\n * @deprecated For multi-value support, use parseMultiParams instead\n */\nexport function parseParams(source: string | URLSearchParams): Record<string, Encoded> {\n const searchParams = typeof source === 'string'\n ? new URLSearchParams(source)\n : source\n\n const result: Record<string, Encoded> = {}\n\n for (const [key, value] of searchParams.entries()) {\n // Only take first value for each key (backward compat)\n if (!(key in result)) {\n result[key] = value\n }\n }\n\n return result\n}\n\n/**\n * Get current URL query parameters (browser only)\n */\nexport function getCurrentParams(): Record<string, Encoded> {\n if (typeof window === 'undefined') return {}\n return parseParams(window.location.search)\n}\n\n/**\n * Update URL without reloading (browser only)\n * @param params - New query parameters\n * @param push - Use pushState (true) or replaceState (false)\n */\nexport function updateUrl(params: Record<string, Encoded>, push = false): void {\n if (typeof window === 'undefined') return\n\n const url = new URL(window.location.href)\n const search = serializeParams(params)\n url.search = search\n\n const method = push ? 'pushState' : 'replaceState'\n window.history[method]({}, '', url.toString())\n}\n\nexport * from './params.js'\nexport * from './multiParams.js'\nexport * from './useUrlParam.js'\n","/**\n * Hash params entry point\n *\n * This module sets the default location strategy to hash (window.location.hash)\n * and re-exports everything from the main module.\n *\n * Usage:\n * ```typescript\n * // Instead of:\n * import { useUrlParam, stringParam } from 'use-prms'\n *\n * // Use:\n * import { useUrlParam, stringParam } from 'use-prms/hash'\n *\n * // Same API, but reads/writes to URL hash instead of query string\n * // e.g., #name=foo instead of ?name=foo\n * ```\n */\n\nimport { setDefaultStrategy, hashStrategy } from './core.js'\n\n// Set hash as the default strategy for this entry point\nsetDefaultStrategy(hashStrategy)\n\n// Re-export everything from main module\nexport * from './index.js'\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/core.ts","../src/params.ts","../src/multiParams.ts","../src/useUrlParam.ts","../src/index.ts","../src/hash.ts"],"names":["useRef","useSyncExternalStore","useCallback","encoded"],"mappings":"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","file":"hash.cjs","sourcesContent":["/**\n * Core multi-value operations and location strategies\n */\n\n/**\n * Multi-value encoded representation\n * An array of strings representing multiple values for a single URL parameter key\n */\nexport type MultiEncoded = string[]\n\n/**\n * Location strategy interface for abstracting URL storage location\n * (query string vs hash fragment)\n */\nexport interface LocationStrategy {\n /** Get raw string from location (for caching comparison) */\n getRaw(): string\n /** Parse current location to multi-value params */\n parse(): Record<string, MultiEncoded>\n /** Build URL string with updated params */\n buildUrl(base: URL, params: Record<string, MultiEncoded>): string\n /** Subscribe to location changes, returns unsubscribe function */\n subscribe(callback: () => void): () => void\n}\n\n/**\n * Parse URL string to multi-value params\n * Each key maps to an array of all values for that key\n */\nexport function parseMultiParams(source: string | URLSearchParams): Record<string, MultiEncoded> {\n const searchParams = typeof source === 'string'\n ? new URLSearchParams(source)\n : source\n\n const result: Record<string, MultiEncoded> = {}\n const keys = new Set(searchParams.keys())\n\n for (const key of keys) {\n result[key] = searchParams.getAll(key)\n }\n\n return result\n}\n\n/**\n * Serialize multi-value params to URL string format\n * Repeated keys are serialized as separate entries: key=a&key=b\n */\nexport function serializeMultiParams(params: Record<string, MultiEncoded>): string {\n const searchParams = new URLSearchParams()\n\n for (const [key, values] of Object.entries(params)) {\n for (const value of values) {\n if (value === '') {\n // Valueless params handled separately\n continue\n }\n searchParams.append(key, value)\n }\n }\n\n let result = searchParams.toString()\n\n // Handle valueless params (empty string values) manually\n const valuelessKeys = Object.entries(params)\n .filter(([_, values]) => values.includes(''))\n .map(([key, _]) => encodeURIComponent(key))\n\n if (valuelessKeys.length > 0) {\n const valuelessPart = valuelessKeys.join('&')\n result = result ? `${result}&${valuelessPart}` : valuelessPart\n }\n\n return result\n}\n\n/**\n * Custom event name for location changes triggered by History API\n */\nconst LOCATION_CHANGE_EVENT = 'use-prms:locationchange'\n\n/**\n * Patch History API to dispatch events on pushState/replaceState\n * This enables automatic reactivity to all programmatic URL changes\n */\nlet historyPatched = false\nfunction patchHistoryApi(): void {\n if (typeof window === 'undefined' || historyPatched) return\n historyPatched = true\n\n const originalPushState = history.pushState.bind(history)\n const originalReplaceState = history.replaceState.bind(history)\n\n history.pushState = function(state, title, url) {\n originalPushState(state, title, url)\n window.dispatchEvent(new CustomEvent(LOCATION_CHANGE_EVENT))\n // Also dispatch popstate for React Router and other libraries that listen to it\n window.dispatchEvent(new PopStateEvent('popstate', { state }))\n }\n\n history.replaceState = function(state, title, url) {\n originalReplaceState(state, title, url)\n window.dispatchEvent(new CustomEvent(LOCATION_CHANGE_EVENT))\n // Also dispatch popstate for React Router and other libraries that listen to it\n window.dispatchEvent(new PopStateEvent('popstate', { state }))\n }\n}\n\n// Patch on module load\npatchHistoryApi()\n\n/**\n * Query string location strategy\n * Reads/writes to window.location.search\n */\nexport const queryStrategy: LocationStrategy = {\n getRaw(): string {\n if (typeof window === 'undefined') return ''\n return window.location.search\n },\n\n parse(): Record<string, MultiEncoded> {\n if (typeof window === 'undefined') return {}\n return parseMultiParams(window.location.search)\n },\n\n buildUrl(base: URL, params: Record<string, MultiEncoded>): string {\n base.search = serializeMultiParams(params)\n return base.toString()\n },\n\n subscribe(callback: () => void): () => void {\n if (typeof window === 'undefined') return () => {}\n window.addEventListener('popstate', callback)\n window.addEventListener(LOCATION_CHANGE_EVENT, callback)\n return () => {\n window.removeEventListener('popstate', callback)\n window.removeEventListener(LOCATION_CHANGE_EVENT, callback)\n }\n },\n}\n\n/**\n * Hash fragment location strategy\n * Reads/writes to window.location.hash\n * Hash is parsed as URLSearchParams format: #key=value&key2=value2\n */\nexport const hashStrategy: LocationStrategy = {\n getRaw(): string {\n if (typeof window === 'undefined') return ''\n return window.location.hash\n },\n\n parse(): Record<string, MultiEncoded> {\n if (typeof window === 'undefined') return {}\n const hash = window.location.hash\n // Remove leading # if present\n const hashString = hash.startsWith('#') ? hash.slice(1) : hash\n return parseMultiParams(hashString)\n },\n\n buildUrl(base: URL, params: Record<string, MultiEncoded>): string {\n base.hash = serializeMultiParams(params)\n return base.toString()\n },\n\n subscribe(callback: () => void): () => void {\n if (typeof window === 'undefined') return () => {}\n // Listen to hashchange, popstate, and our custom event for all navigation types\n window.addEventListener('hashchange', callback)\n window.addEventListener('popstate', callback)\n window.addEventListener(LOCATION_CHANGE_EVENT, callback)\n return () => {\n window.removeEventListener('hashchange', callback)\n window.removeEventListener('popstate', callback)\n window.removeEventListener(LOCATION_CHANGE_EVENT, callback)\n }\n },\n}\n\n/**\n * Notify all use-prms hooks that the URL has changed.\n * Note: With the History API patch, this is rarely needed since pushState/replaceState\n * automatically trigger notifications. Use this for edge cases like direct location assignment.\n */\nexport function notifyLocationChange(): void {\n if (typeof window === 'undefined') return\n window.dispatchEvent(new CustomEvent(LOCATION_CHANGE_EVENT))\n}\n\n/**\n * Clear all URL params.\n * @param strategy - Which location to clear (query or hash), defaults to query\n */\nexport function clearParams(strategy: 'query' | 'hash' = 'query'): void {\n if (typeof window === 'undefined') return\n const url = new URL(window.location.href)\n if (strategy === 'hash') {\n url.hash = ''\n } else {\n url.search = ''\n }\n // replaceState triggers our custom event automatically via the patch\n window.history.replaceState({}, '', url.toString())\n}\n\n// Default strategy (can be changed by entry points like hash.ts)\nlet defaultStrategy: LocationStrategy = queryStrategy\n\n/**\n * Get the current default location strategy\n */\nexport function getDefaultStrategy(): LocationStrategy {\n return defaultStrategy\n}\n\n/**\n * Set the default location strategy\n * Called by entry points (e.g., hash.ts sets this to hashStrategy)\n */\nexport function setDefaultStrategy(strategy: LocationStrategy): void {\n defaultStrategy = strategy\n}\n","/**\n * Built-in parameter types with smart defaults and minimal encoding\n */\n\nimport type { Encoded, Param } from './index.js'\n\n/**\n * Optional string parameter.\n * - undefined → not present\n * - empty string → ?key=\n * - non-empty → ?key=value\n */\nexport function stringParam(init?: string): Param<string | undefined> {\n return {\n encode: (value) => value === init ? undefined : value,\n decode: (encoded) => encoded === undefined ? init : encoded,\n }\n}\n\n/**\n * Required string parameter with default.\n * Omitted from URL when equal to default.\n */\nexport function defStringParam(init: string): Param<string> {\n return {\n encode: (value) => value === init ? undefined : value,\n decode: (encoded) => encoded ?? init,\n }\n}\n\n/**\n * Boolean parameter.\n * - true → ?key (valueless)\n * - false → not present\n */\nexport const boolParam: Param<boolean> = {\n encode: (value) => value ? '' : undefined,\n decode: (encoded) => encoded !== undefined,\n}\n\n/**\n * Integer parameter with default.\n * Omitted from URL when equal to default.\n */\nexport function intParam(init: number): Param<number> {\n return {\n encode: (value) => value === init ? undefined : value.toString(),\n decode: (encoded) => {\n if (encoded === undefined || encoded === '') return init\n const parsed = parseInt(encoded, 10)\n return isNaN(parsed) ? init : parsed\n },\n }\n}\n\n/**\n * Optional integer parameter.\n * - null → not present\n * - number → ?key=123\n */\nexport const optIntParam: Param<number | null> = {\n encode: (value) => value === null ? undefined : value.toString(),\n decode: (encoded) => {\n if (encoded === undefined || encoded === '') return null\n const parsed = parseInt(encoded, 10)\n return isNaN(parsed) ? null : parsed\n },\n}\n\n/**\n * Float parameter with default.\n * Omitted from URL when equal to default.\n */\nexport function floatParam(init: number): Param<number> {\n return {\n encode: (value) => value === init ? undefined : value.toString(),\n decode: (encoded) => {\n if (encoded === undefined || encoded === '') return init\n const parsed = parseFloat(encoded)\n return isNaN(parsed) ? init : parsed\n },\n }\n}\n\n/**\n * Enum parameter with validation.\n * Omitted from URL when equal to default.\n * Invalid values fall back to default with console warning.\n */\nexport function enumParam<T extends string>(\n init: T,\n values: readonly T[]\n): Param<T> {\n const validSet = new Set(values)\n\n return {\n encode: (value) => {\n if (!validSet.has(value)) {\n console.warn(`Invalid enum value: ${value}, expected one of ${values.join(', ')}`)\n return undefined\n }\n return value === init ? undefined : value\n },\n decode: (encoded) => {\n if (encoded === undefined) return init\n if (!validSet.has(encoded as T)) {\n console.warn(`Invalid enum value: ${encoded}, expected one of ${values.join(', ')}. Using default: ${init}`)\n return init\n }\n return encoded as T\n },\n }\n}\n\n/**\n * String array parameter with delimiter.\n * Omitted from URL when equal to default.\n * Empty array encodes as empty string (?key=)\n */\nexport function stringsParam(\n init: string[] = [],\n delimiter = ' '\n): Param<string[]> {\n const initEncoded = init.join(delimiter)\n\n return {\n encode: (values) => {\n const encoded = values.join(delimiter)\n if (encoded === initEncoded) return undefined\n return encoded\n },\n decode: (encoded) => {\n if (encoded === undefined) return init\n if (encoded === '') return []\n return encoded.split(delimiter)\n },\n }\n}\n\n/**\n * Number array parameter.\n * Omitted from URL when equal to default.\n * Uses comma delimiter.\n */\nexport function numberArrayParam(init: number[] = []): Param<number[]> {\n const isEqual = (a: number[], b: number[]) =>\n a.length === b.length && a.every((v, i) => v === b[i])\n\n return {\n encode: (values) => {\n if (isEqual(values, init)) return undefined\n return values.map(v => v.toString()).join(',')\n },\n decode: (encoded) => {\n if (encoded === undefined) return init\n if (encoded === '') return []\n return encoded.split(',').map(v => parseFloat(v))\n },\n }\n}\n\n/**\n * Pagination parameter combining offset and page size.\n * Uses space (which encodes as + in URLs) as delimiter.\n *\n * Encoding rules:\n * - offset=0, pageSize=default → not present (undefined)\n * - offset=0, pageSize=custom → \" pageSize\" (e.g., \" 20\" → +20 in URL)\n * - offset>0, pageSize=default → \"offset\" (e.g., \"100\")\n * - offset>0, pageSize=custom → \"offset pageSize\" (e.g., \"100 20\" → 100+20 in URL)\n *\n * @param defaultPageSize - The default page size (omitted from URL when used)\n * @param validPageSizes - Optional array of valid page sizes for validation\n */\nexport type Pagination = { offset: number; pageSize: number }\n\nexport function paginationParam(\n defaultPageSize: number,\n validPageSizes?: readonly number[],\n): Param<Pagination> {\n return {\n encode: ({ offset, pageSize }) => {\n if (offset === 0 && pageSize === defaultPageSize) return undefined\n if (offset === 0) return ` ${pageSize}` // Space prefix → +pageSize in URL\n if (pageSize === defaultPageSize) return String(offset)\n return `${offset} ${pageSize}` // Space encodes as + in URL\n },\n decode: (encoded) => {\n if (!encoded) return { offset: 0, pageSize: defaultPageSize }\n const parts = encoded.split(' ') // URL + decodes to space\n // Handle \" pageSize\" case (offset 0 with custom page size)\n const offset = parts[0] === '' ? 0 : parseInt(parts[0], 10) || 0\n let pageSize = parts[1] ? parseInt(parts[1], 10) : defaultPageSize\n // Validate page size if validation array provided\n if (validPageSizes && !validPageSizes.includes(pageSize)) {\n pageSize = defaultPageSize\n }\n return { offset, pageSize }\n },\n }\n}\n\n/**\n * Code mapping for enum values - maps full values to short codes for compact URLs.\n * Can be specified as:\n * - Array of [value, code] tuples: [['Rides', 'r'], ['Minutes', 'm']]\n * - Object mapping values to codes: { Rides: 'r', Minutes: 'm' }\n */\nexport type CodeMap<T extends string> = [T, string][] | Record<T, string>\n\nfunction normalizeCodeMap<T extends string>(codeMap: CodeMap<T>): [T, string][] {\n if (Array.isArray(codeMap)) return codeMap\n return Object.entries(codeMap) as [T, string][]\n}\n\n/**\n * Single-value enum parameter with short code mapping.\n * Maps full enum values to abbreviated codes for compact URLs.\n * Omitted from URL when equal to default.\n *\n * @example\n * // ?y=r for \"Rides\", ?y=m for \"Minutes\", omitted for default \"Rides\"\n * codeParam('Rides', [['Rides', 'r'], ['Minutes', 'm']])\n * // or with object syntax:\n * codeParam('Rides', { Rides: 'r', Minutes: 'm' })\n */\nexport function codeParam<T extends string>(\n init: T,\n codeMap: CodeMap<T>,\n): Param<T> {\n const entries = normalizeCodeMap(codeMap)\n const valueToCode = new Map(entries)\n const codeToValue = new Map(entries.map(([v, c]) => [c, v]))\n\n return {\n encode: (value) => {\n if (value === init) return undefined\n return valueToCode.get(value) ?? value\n },\n decode: (encoded) => {\n if (encoded === undefined) return init\n return codeToValue.get(encoded) ?? init\n },\n }\n}\n\n/**\n * Multi-value parameter with short code mapping.\n * Maps full values to abbreviated codes for compact URLs.\n * Omitted from URL when all values are selected.\n *\n * @param allValues - Array of all possible values (used to detect \"all selected\")\n * @param codeMap - Mapping from values to short codes\n * @param separator - Delimiter between codes (default: '' for most compact URLs)\n *\n * @example\n * // Regions: ?r=nj for NYC+JC, ?r=njh or omitted for all three\n * codesParam(['NYC', 'JC', 'HOB'], [['NYC', 'n'], ['JC', 'j'], ['HOB', 'h']])\n * // or with object syntax and custom separator:\n * codesParam(['NYC', 'JC', 'HOB'], { NYC: 'n', JC: 'j', HOB: 'h' }, ',')\n */\nexport function codesParam<T extends string>(\n allValues: readonly T[],\n codeMap: CodeMap<T>,\n separator: string = '',\n): Param<T[]> {\n const entries = normalizeCodeMap(codeMap)\n const valueToCode = new Map(entries)\n const codeToValue = new Map(entries.map(([v, c]) => [c, v]))\n\n return {\n encode: (values) => {\n // Omit when all values selected\n if (values.length === allValues.length && allValues.every(v => values.includes(v))) {\n return undefined\n }\n return values.map(v => valueToCode.get(v) ?? v).join(separator)\n },\n decode: (encoded) => {\n if (encoded === undefined) return [...allValues]\n if (encoded === '') return []\n const codes = separator ? encoded.split(separator) : encoded.split('')\n return codes.map(c => codeToValue.get(c)).filter((v): v is T => v !== undefined)\n },\n }\n}\n","/**\n * Multi-value parameter types for handling repeated URL params\n * e.g., ?tag=a&tag=b&tag=c\n */\n\nimport type { MultiEncoded } from './core.js'\n\n/**\n * A bidirectional converter between a typed value and its multi-value URL representation.\n * Similar to Param<T> but works with string[] instead of string | undefined.\n */\nexport type MultiParam<T> = {\n encode: (value: T) => MultiEncoded\n decode: (encoded: MultiEncoded) => T\n}\n\n/**\n * Multi-value string array parameter.\n * Each string becomes a separate URL param with the same key.\n *\n * @example\n * // ?tag=a&tag=b&tag=c → ['a', 'b', 'c']\n * const [tags, setTags] = useMultiUrlParam('tag', multiStringParam())\n */\nexport function multiStringParam(init: string[] = []): MultiParam<string[]> {\n return {\n encode: (values) => {\n if (values.length === 0 && init.length === 0) return []\n if (arraysEqual(values, init)) return []\n return values\n },\n decode: (encoded) => {\n if (encoded.length === 0) return init\n return encoded\n },\n }\n}\n\n/**\n * Multi-value integer array parameter.\n * Each number becomes a separate URL param with the same key.\n *\n * @example\n * // ?id=1&id=2&id=3 → [1, 2, 3]\n * const [ids, setIds] = useMultiUrlParam('id', multiIntParam())\n */\nexport function multiIntParam(init: number[] = []): MultiParam<number[]> {\n return {\n encode: (values) => {\n if (values.length === 0 && init.length === 0) return []\n if (arraysEqual(values, init)) return []\n return values.map(v => v.toString())\n },\n decode: (encoded) => {\n if (encoded.length === 0) return init\n return encoded.map(v => parseInt(v, 10))\n },\n }\n}\n\n/**\n * Multi-value float array parameter.\n * Each number becomes a separate URL param with the same key.\n *\n * @example\n * // ?val=1.5&val=2.7 → [1.5, 2.7]\n * const [vals, setVals] = useMultiUrlParam('val', multiFloatParam())\n */\nexport function multiFloatParam(init: number[] = []): MultiParam<number[]> {\n return {\n encode: (values) => {\n if (values.length === 0 && init.length === 0) return []\n if (arraysEqual(values, init)) return []\n return values.map(v => v.toString())\n },\n decode: (encoded) => {\n if (encoded.length === 0) return init\n return encoded.map(v => parseFloat(v))\n },\n }\n}\n\n/** Helper to compare arrays for equality */\nfunction arraysEqual<T>(a: T[], b: T[]): boolean {\n return a.length === b.length && a.every((v, i) => v === b[i])\n}\n","/**\n * React hooks for managing URL parameters\n */\n\nimport { useCallback, useRef, useSyncExternalStore } from 'react'\nimport type { Param } from './index.js'\nimport type { LocationStrategy, MultiEncoded } from './core.js'\nimport { getDefaultStrategy, serializeMultiParams } from './core.js'\nimport type { MultiParam } from './multiParams.js'\n\n/**\n * Cached snapshot to prevent infinite loops in useSyncExternalStore\n * Keyed by strategy (so query and hash don't share cache)\n */\nconst snapshotCache = new WeakMap<LocationStrategy, {\n raw: string\n snapshot: Record<string, MultiEncoded>\n}>()\n\n/**\n * Get URL snapshot for a given strategy\n * Returns cached snapshot if URL hasn't changed\n */\nfunction getSnapshot(strategy: LocationStrategy): Record<string, MultiEncoded> {\n const raw = strategy.getRaw()\n const cached = snapshotCache.get(strategy)\n\n if (cached && cached.raw === raw) {\n return cached.snapshot\n }\n\n const snapshot = strategy.parse()\n snapshotCache.set(strategy, { raw, snapshot })\n return snapshot\n}\n\n/**\n * Server-side snapshot (always empty)\n */\nfunction getServerSnapshot(): Record<string, MultiEncoded> {\n return {}\n}\n\n/**\n * Convert single-value Encoded to multi-value MultiEncoded\n */\nfunction singleToMulti(encoded: string | undefined): MultiEncoded {\n if (encoded === undefined) return []\n return [encoded]\n}\n\n/**\n * Convert multi-value MultiEncoded to single-value Encoded\n */\nfunction multiToSingle(multi: MultiEncoded): string | undefined {\n if (multi.length === 0) return undefined\n return multi[0]\n}\n\n/**\n * React hook for managing a single URL query parameter.\n *\n * @param key - Query parameter key\n * @param param - Param encoder/decoder\n * @param push - Use pushState (true) or replaceState (false) when updating\n * @returns Tuple of [value, setValue]\n *\n * @example\n * ```tsx\n * const [zoom, setZoom] = useUrlParam('z', boolParam)\n * const [device, setDevice] = useUrlParam('d', stringParam('default'))\n * ```\n */\nexport function useUrlParam<T>(\n key: string,\n param: Param<T>,\n push = false\n): [T, (value: T) => void] {\n const strategy = getDefaultStrategy()\n\n // Use ref to avoid recreating setValue when param changes\n const paramRef = useRef(param)\n paramRef.current = param\n\n // Subscribe to URL changes\n const urlParams = useSyncExternalStore(\n (cb) => strategy.subscribe(cb),\n () => getSnapshot(strategy),\n getServerSnapshot\n )\n\n // Memoize decoded value based on encoded string AND param identity\n // Re-decode if either the URL param string changes OR the param object changes\n // (e.g., deviceIdsParam depends on devices array which loads asynchronously)\n const encoded = multiToSingle(urlParams[key] ?? [])\n const cacheRef = useRef<{ encoded: typeof encoded; param: Param<T>; decoded: T } | null>(null)\n\n if (cacheRef.current === null || cacheRef.current.encoded !== encoded || cacheRef.current.param !== param) {\n cacheRef.current = { encoded, param, decoded: param.decode(encoded) }\n }\n const value = cacheRef.current.decoded\n\n // Update URL when value changes\n const setValue = useCallback(\n (newValue: T) => {\n if (typeof window === 'undefined') return\n\n const currentParams = strategy.parse()\n const encoded = paramRef.current.encode(newValue)\n\n // Update this parameter (single → multi)\n if (encoded === undefined) {\n delete currentParams[key]\n } else {\n currentParams[key] = [encoded]\n }\n\n // Build and update URL\n const url = new URL(window.location.href)\n const newUrl = strategy.buildUrl(url, currentParams)\n\n const method = push ? 'pushState' : 'replaceState'\n window.history[method]({}, '', newUrl)\n\n // Trigger events to notify other hooks\n window.dispatchEvent(new PopStateEvent('popstate'))\n },\n [key, push, strategy]\n )\n\n return [value, setValue]\n}\n\n/**\n * React hook for managing multiple URL query parameters together.\n * Updates are batched into a single history entry.\n *\n * @param params - Object mapping keys to Param types\n * @param push - Use pushState (true) or replaceState (false) when updating\n * @returns Object with decoded values and update function\n *\n * @example\n * ```tsx\n * const { values, setValues } = useUrlParams({\n * zoom: boolParam,\n * device: stringParam('default'),\n * count: intParam(10)\n * })\n *\n * // Update multiple params at once\n * setValues({ zoom: true, count: 20 })\n * ```\n */\nexport function useUrlParams<P extends Record<string, Param<any>>>(\n params: P,\n push = false\n): {\n values: { [K in keyof P]: P[K] extends Param<infer T> ? T : never }\n setValues: (updates: Partial<{ [K in keyof P]: P[K] extends Param<infer T> ? T : never }>) => void\n} {\n const strategy = getDefaultStrategy()\n\n // Subscribe to URL changes\n const urlParams = useSyncExternalStore(\n (cb) => strategy.subscribe(cb),\n () => getSnapshot(strategy),\n getServerSnapshot\n )\n\n // Decode all values from URL\n const values = Object.fromEntries(\n Object.entries(params).map(([key, param]) => [\n key,\n param.decode(multiToSingle(urlParams[key] ?? []))\n ])\n ) as { [K in keyof P]: P[K] extends Param<infer T> ? T : never }\n\n // Update multiple parameters at once\n const setValues = useCallback(\n (updates: Partial<{ [K in keyof P]: P[K] extends Param<infer T> ? T : never }>) => {\n if (typeof window === 'undefined') return\n\n const currentParams = strategy.parse()\n\n // Apply all updates\n for (const [key, value] of Object.entries(updates)) {\n const param = params[key]\n if (!param) continue\n\n const encoded = param.encode(value)\n if (encoded === undefined) {\n delete currentParams[key]\n } else {\n currentParams[key] = [encoded]\n }\n }\n\n // Build and update URL once\n const url = new URL(window.location.href)\n const newUrl = strategy.buildUrl(url, currentParams)\n\n const method = push ? 'pushState' : 'replaceState'\n window.history[method]({}, '', newUrl)\n\n // Trigger events to notify other hooks\n window.dispatchEvent(new PopStateEvent('popstate'))\n },\n [params, push, strategy]\n )\n\n return { values, setValues }\n}\n\n/**\n * React hook for managing a single multi-value URL parameter.\n * Supports repeated params like ?tag=a&tag=b&tag=c\n *\n * @param key - Query parameter key\n * @param param - MultiParam encoder/decoder\n * @param push - Use pushState (true) or replaceState (false) when updating\n * @returns Tuple of [value, setValue]\n *\n * @example\n * ```tsx\n * const [tags, setTags] = useMultiUrlParam('tag', multiStringParam())\n * // URL: ?tag=a&tag=b → tags = ['a', 'b']\n * ```\n */\nexport function useMultiUrlParam<T>(\n key: string,\n param: MultiParam<T>,\n push = false\n): [T, (value: T) => void] {\n const strategy = getDefaultStrategy()\n\n // Use ref to avoid recreating setValue when param changes\n const paramRef = useRef(param)\n paramRef.current = param\n\n // Subscribe to URL changes\n const urlParams = useSyncExternalStore(\n (cb) => strategy.subscribe(cb),\n () => getSnapshot(strategy),\n getServerSnapshot\n )\n\n // Decode current value from URL\n const value = param.decode(urlParams[key] ?? [])\n\n // Update URL when value changes\n const setValue = useCallback(\n (newValue: T) => {\n if (typeof window === 'undefined') return\n\n const currentParams = strategy.parse()\n const encoded = paramRef.current.encode(newValue)\n\n // Update this parameter\n if (encoded.length === 0) {\n delete currentParams[key]\n } else {\n currentParams[key] = encoded\n }\n\n // Build and update URL\n const url = new URL(window.location.href)\n const newUrl = strategy.buildUrl(url, currentParams)\n\n const method = push ? 'pushState' : 'replaceState'\n window.history[method]({}, '', newUrl)\n\n // Trigger events to notify other hooks\n window.dispatchEvent(new PopStateEvent('popstate'))\n },\n [key, push, strategy]\n )\n\n return [value, setValue]\n}\n\n/**\n * React hook for managing multiple multi-value URL parameters together.\n * Updates are batched into a single history entry.\n *\n * @param params - Object mapping keys to MultiParam types\n * @param push - Use pushState (true) or replaceState (false) when updating\n * @returns Object with decoded values and update function\n *\n * @example\n * ```tsx\n * const { values, setValues } = useMultiUrlParams({\n * tags: multiStringParam(),\n * ids: multiIntParam()\n * })\n *\n * // Update multiple multi-value params at once\n * setValues({ tags: ['a', 'b'], ids: [1, 2, 3] })\n * ```\n */\nexport function useMultiUrlParams<P extends Record<string, MultiParam<any>>>(\n params: P,\n push = false\n): {\n values: { [K in keyof P]: P[K] extends MultiParam<infer T> ? T : never }\n setValues: (updates: Partial<{ [K in keyof P]: P[K] extends MultiParam<infer T> ? T : never }>) => void\n} {\n const strategy = getDefaultStrategy()\n\n // Subscribe to URL changes\n const urlParams = useSyncExternalStore(\n (cb) => strategy.subscribe(cb),\n () => getSnapshot(strategy),\n getServerSnapshot\n )\n\n // Decode all values from URL\n const values = Object.fromEntries(\n Object.entries(params).map(([key, param]) => [\n key,\n param.decode(urlParams[key] ?? [])\n ])\n ) as { [K in keyof P]: P[K] extends MultiParam<infer T> ? T : never }\n\n // Update multiple parameters at once\n const setValues = useCallback(\n (updates: Partial<{ [K in keyof P]: P[K] extends MultiParam<infer T> ? T : never }>) => {\n if (typeof window === 'undefined') return\n\n const currentParams = strategy.parse()\n\n // Apply all updates\n for (const [key, value] of Object.entries(updates)) {\n const param = params[key]\n if (!param) continue\n\n const encoded = param.encode(value)\n if (encoded.length === 0) {\n delete currentParams[key]\n } else {\n currentParams[key] = encoded\n }\n }\n\n // Build and update URL once\n const url = new URL(window.location.href)\n const newUrl = strategy.buildUrl(url, currentParams)\n\n const method = push ? 'pushState' : 'replaceState'\n window.history[method]({}, '', newUrl)\n\n // Trigger events to notify other hooks\n window.dispatchEvent(new PopStateEvent('popstate'))\n },\n [params, push, strategy]\n )\n\n return { values, setValues }\n}\n","/**\n * Core types and utilities for URL parameter management\n */\n\n// Re-export core types and strategies\nexport type { MultiEncoded, LocationStrategy } from './core.js'\nexport {\n parseMultiParams,\n serializeMultiParams,\n queryStrategy,\n hashStrategy,\n getDefaultStrategy,\n setDefaultStrategy,\n notifyLocationChange,\n clearParams,\n} from './core.js'\n\n/**\n * Encodes a value to a URL query parameter string.\n * - undefined: parameter not present in URL\n * - \"\": valueless parameter (e.g., ?z)\n * - string: parameter with value (e.g., ?z=foo)\n */\nexport type Encoded = string | undefined\n\n/**\n * A bidirectional converter between a typed value and its URL representation.\n */\nexport type Param<T> = {\n encode: (value: T) => Encoded\n decode: (encoded: Encoded) => T\n}\n\n/**\n * Serialize query parameters to URL string.\n * Uses URLSearchParams for proper form-urlencoded format (space → +)\n * Handles valueless params (empty string → ?key without =) manually\n *\n * @deprecated For multi-value support, use serializeMultiParams instead\n */\nexport function serializeParams(params: Record<string, Encoded>): string {\n const searchParams = new URLSearchParams()\n\n for (const [key, value] of Object.entries(params)) {\n if (value === undefined) {\n // Skip undefined values\n continue\n } else if (value === '') {\n // Valueless param: ?key without =\n // URLSearchParams doesn't support this, so we'll handle manually\n continue\n } else {\n searchParams.set(key, value)\n }\n }\n\n let result = searchParams.toString()\n\n // Handle valueless params manually\n const valuelessKeys = Object.entries(params)\n .filter(([_, value]) => value === '')\n .map(([key, _]) => encodeURIComponent(key))\n\n if (valuelessKeys.length > 0) {\n const valuelessPart = valuelessKeys.join('&')\n result = result ? `${result}&${valuelessPart}` : valuelessPart\n }\n\n return result\n}\n\n/**\n * Parse query parameters from URL string or URLSearchParams.\n * Note: URLSearchParams treats ?z and ?z= identically (both as empty string).\n * Note: For repeated params, only the first value is returned.\n *\n * @deprecated For multi-value support, use parseMultiParams instead\n */\nexport function parseParams(source: string | URLSearchParams): Record<string, Encoded> {\n const searchParams = typeof source === 'string'\n ? new URLSearchParams(source)\n : source\n\n const result: Record<string, Encoded> = {}\n\n for (const [key, value] of searchParams.entries()) {\n // Only take first value for each key (backward compat)\n if (!(key in result)) {\n result[key] = value\n }\n }\n\n return result\n}\n\n/**\n * Get current URL query parameters (browser only)\n */\nexport function getCurrentParams(): Record<string, Encoded> {\n if (typeof window === 'undefined') return {}\n return parseParams(window.location.search)\n}\n\n/**\n * Update URL without reloading (browser only)\n * @param params - New query parameters\n * @param push - Use pushState (true) or replaceState (false)\n */\nexport function updateUrl(params: Record<string, Encoded>, push = false): void {\n if (typeof window === 'undefined') return\n\n const url = new URL(window.location.href)\n const search = serializeParams(params)\n url.search = search\n\n const method = push ? 'pushState' : 'replaceState'\n window.history[method]({}, '', url.toString())\n}\n\nexport * from './params.js'\nexport * from './multiParams.js'\nexport * from './useUrlParam.js'\n","/**\n * Hash params entry point\n *\n * This module sets the default location strategy to hash (window.location.hash)\n * and re-exports everything from the main module.\n *\n * Usage:\n * ```typescript\n * // Instead of:\n * import { useUrlParam, stringParam } from 'use-prms'\n *\n * // Use:\n * import { useUrlParam, stringParam } from 'use-prms/hash'\n *\n * // Same API, but reads/writes to URL hash instead of query string\n * // e.g., #name=foo instead of ?name=foo\n * ```\n */\n\nimport { setDefaultStrategy, hashStrategy } from './core.js'\n\n// Set hash as the default strategy for this entry point\nsetDefaultStrategy(hashStrategy)\n\n// Re-export everything from main module\nexport * from './index.js'\n"]}
|
package/dist/hash.d.cts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { CodeMap, Encoded, LocationStrategy, MultiEncoded, MultiParam, Pagination, Param, boolParam, codeParam, codesParam, defStringParam, enumParam, floatParam, getCurrentParams, getDefaultStrategy, hashStrategy, intParam, multiFloatParam, multiIntParam, multiStringParam, numberArrayParam, optIntParam, paginationParam, parseMultiParams, parseParams, queryStrategy, serializeMultiParams, serializeParams, setDefaultStrategy, stringParam, stringsParam, updateUrl, useMultiUrlParam, useMultiUrlParams, useUrlParam, useUrlParams } from './index.cjs';
|
|
1
|
+
export { CodeMap, Encoded, LocationStrategy, MultiEncoded, MultiParam, Pagination, Param, boolParam, clearParams, codeParam, codesParam, defStringParam, enumParam, floatParam, getCurrentParams, getDefaultStrategy, hashStrategy, intParam, multiFloatParam, multiIntParam, multiStringParam, notifyLocationChange, numberArrayParam, optIntParam, paginationParam, parseMultiParams, parseParams, queryStrategy, serializeMultiParams, serializeParams, setDefaultStrategy, stringParam, stringsParam, updateUrl, useMultiUrlParam, useMultiUrlParams, useUrlParam, useUrlParams } from './index.cjs';
|
package/dist/hash.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { CodeMap, Encoded, LocationStrategy, MultiEncoded, MultiParam, Pagination, Param, boolParam, codeParam, codesParam, defStringParam, enumParam, floatParam, getCurrentParams, getDefaultStrategy, hashStrategy, intParam, multiFloatParam, multiIntParam, multiStringParam, numberArrayParam, optIntParam, paginationParam, parseMultiParams, parseParams, queryStrategy, serializeMultiParams, serializeParams, setDefaultStrategy, stringParam, stringsParam, updateUrl, useMultiUrlParam, useMultiUrlParams, useUrlParam, useUrlParams } from './index.js';
|
|
1
|
+
export { CodeMap, Encoded, LocationStrategy, MultiEncoded, MultiParam, Pagination, Param, boolParam, clearParams, codeParam, codesParam, defStringParam, enumParam, floatParam, getCurrentParams, getDefaultStrategy, hashStrategy, intParam, multiFloatParam, multiIntParam, multiStringParam, notifyLocationChange, numberArrayParam, optIntParam, paginationParam, parseMultiParams, parseParams, queryStrategy, serializeMultiParams, serializeParams, setDefaultStrategy, stringParam, stringsParam, updateUrl, useMultiUrlParam, useMultiUrlParams, useUrlParam, useUrlParams } from './index.js';
|