state-in-url 2.5.2 → 3.0.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 +123 -34
- package/dist/constants/constants.mjs +1 -1
- package/dist/encodeState/encodeState.mjs +1 -1
- package/dist/encoder/encoder.mjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/next/index.mjs +1 -1
- package/dist/next/useUrlState/useUrlState.mjs +1 -1
- package/dist/parseSPObj.mjs +1 -0
- package/dist/react-router/index.mjs +1 -0
- package/dist/react-router/useUrlState/index.mjs +1 -0
- package/dist/react-router/useUrlState/useUrlState.mjs +1 -0
- package/dist/useSharedState/useSharedState.mjs +1 -1
- package/dist/useUrlStateBase/useUrlStateBase.mjs +1 -1
- package/dist/utils.mjs +1 -1
- package/package.json +154 -49
- package/dist/next/parseSPObj.mjs +0 -1
- package/dist/package.json +0 -292
- package/dist/shared/components/Button.d.ts +0 -8
- package/dist/shared/components/Field.d.ts +0 -7
- package/dist/shared/components/Input.d.ts +0 -4
- package/dist/shared/components/Refresh.d.ts +0 -3
- package/dist/shared/components/Tag.d.ts +0 -5
- package/dist/shared/components/index.d.ts +0 -4
- package/dist/shared/form.d.ts +0 -15
- package/dist/shared/index.d.ts +0 -2
- package/dist/shared/tailwind.d.ts +0 -2
- package/dist/shared/vite-config.d.ts +0 -17
- package/dist/tsconfig.tsbuildinfo +0 -1
- package/dist/urlstate/constants/constants.d.ts +0 -8
- package/dist/urlstate/constants/index.d.ts +0 -1
- package/dist/urlstate/encodeState/encodeState.d.ts +0 -32
- package/dist/urlstate/encodeState/index.d.ts +0 -1
- package/dist/urlstate/encoder/encoder.d.ts +0 -34
- package/dist/urlstate/encoder/index.d.ts +0 -1
- package/dist/urlstate/index.d.ts +0 -9
- package/dist/urlstate/next/index.d.ts +0 -2
- package/dist/urlstate/next/parseSPObj.d.ts +0 -9
- package/dist/urlstate/next/useUrlState/index.d.ts +0 -1
- package/dist/urlstate/next/useUrlState/useUrlState.d.ts +0 -63
- package/dist/urlstate/subscribers.d.ts +0 -11
- package/dist/urlstate/useInsertionEffect.d.ts +0 -2
- package/dist/urlstate/useSharedState/index.d.ts +0 -1
- package/dist/urlstate/useSharedState/useSharedState.d.ts +0 -24
- package/dist/urlstate/useUrlEncode/index.d.ts +0 -1
- package/dist/urlstate/useUrlEncode/useUrlEncode.d.ts +0 -45
- package/dist/urlstate/useUrlStateBase/index.d.ts +0 -1
- package/dist/urlstate/useUrlStateBase/useUrlStateBase.d.ts +0 -39
- package/dist/urlstate/utils.d.ts +0 -26
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@ English | [한국어](./README.KO.md) | [简体中文](./README.CN.md)
|
|
|
3
3
|
<div align="center">
|
|
4
4
|
<img src="/assets/Logo_big.png?raw=true" alt="state-in-url logo"/>
|
|
5
5
|
|
|
6
|
-
<div>Easily share state between unrelated React components, with IDE autocomplete and TS validation. Without any hasssle or boilerplate. </div>
|
|
6
|
+
<div>Easily share complex state between unrelated React components, with IDE autocomplete and TS validation. Without any hasssle or boilerplate. </div>
|
|
7
7
|
</div>
|
|
8
8
|
|
|
9
9
|
<div align="center">
|
|
@@ -13,6 +13,7 @@ English | [한국어](./README.KO.md) | [简体中文](./README.CN.md)
|
|
|
13
13
|

|
|
14
14
|
[](https://app.codacy.com/gh/asmyshlyaev177/state-in-url/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)
|
|
15
15
|
[](https://github.com/asmyshlyaev177/state-in-url/)
|
|
16
|
+
[]([https://github.com/semantic-release/semantic-release](https://github.com/asmyshlyaev177/state-in-url))
|
|
16
17
|

|
|
17
18
|
</div>
|
|
18
19
|
|
|
@@ -22,7 +23,6 @@ English | [한국어](./README.KO.md) | [简体中文](./README.CN.md)
|
|
|
22
23
|
|
|
23
24
|

|
|
24
25
|
|
|
25
|
-
|
|
26
26
|
<a href="https://state-in-url-asmyshlyaev177.vercel.app/" target="_blank">DEMO</a> |
|
|
27
27
|
<a href="https://state-in-url.netlify.app/" target="_blank">DEMO2</a> |
|
|
28
28
|
<a href ="https://codesandbox.io/p/github/asmyshlyaev177/state-in-url/main?layout=%257B%2522sidebarPanel%2522%253A%2522EXPLORER%2522%252C%2522rootPanelGroup%2522%253A%257B%2522direction%2522%253A%2522horizontal%2522%252C%2522contentType%2522%253A%2522UNKNOWN%2522%252C%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522id%2522%253A%2522ROOT_LAYOUT%2522%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522contentType%2522%253A%2522UNKNOWN%2522%252C%2522direction%2522%253A%2522vertical%2522%252C%2522id%2522%253A%2522clyk5bd9y00062v6jspcfrkx7%2522%252C%2522sizes%2522%253A%255B100%252C0%255D%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522contentType%2522%253A%2522EDITOR%2522%252C%2522direction%2522%253A%2522horizontal%2522%252C%2522id%2522%253A%2522EDITOR%2522%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL%2522%252C%2522contentType%2522%253A%2522EDITOR%2522%252C%2522id%2522%253A%2522clyk5bd9x00022v6jyg71cr9e%2522%257D%255D%257D%252C%257B%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522contentType%2522%253A%2522SHELLS%2522%252C%2522direction%2522%253A%2522horizontal%2522%252C%2522id%2522%253A%2522SHELLS%2522%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL%2522%252C%2522contentType%2522%253A%2522SHELLS%2522%252C%2522id%2522%253A%2522clyk5bd9x00042v6jsos2y043%2522%257D%255D%257D%255D%257D%252C%257B%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522contentType%2522%253A%2522DEVTOOLS%2522%252C%2522direction%2522%253A%2522vertical%2522%252C%2522id%2522%253A%2522DEVTOOLS%2522%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL%2522%252C%2522contentType%2522%253A%2522DEVTOOLS%2522%252C%2522id%2522%253A%2522clyk5bd9x00052v6j5r632b12%2522%257D%255D%257D%255D%252C%2522sizes%2522%253A%255B50%252C50%255D%257D%252C%2522tabbedPanels%2522%253A%257B%2522clyk5bd9x00022v6jyg71cr9e%2522%253A%257B%2522tabs%2522%253A%255B%257B%2522id%2522%253A%2522clyk5bd9w00012v6j83rq3bvo%2522%252C%2522mode%2522%253A%2522permanent%2522%252C%2522type%2522%253A%2522FILE%2522%252C%2522filepath%2522%253A%2522%252FREADME.md%2522%252C%2522state%2522%253A%2522IDLE%2522%257D%255D%252C%2522id%2522%253A%2522clyk5bd9x00022v6jyg71cr9e%2522%252C%2522activeTabId%2522%253A%2522clyk5bd9w00012v6j83rq3bvo%2522%257D%252C%2522clyk5bd9x00052v6j5r632b12%2522%253A%257B%2522id%2522%253A%2522clyk5bd9x00052v6j5r632b12%2522%252C%2522activeTabId%2522%253A%2522clyk5bdjx000b2v6jfc8ae464%2522%252C%2522tabs%2522%253A%255B%257B%2522type%2522%253A%2522SETUP_TASKS%2522%252C%2522id%2522%253A%2522clyk5bdjx000b2v6jfc8ae464%2522%252C%2522mode%2522%253A%2522permanent%2522%257D%252C%257B%2522type%2522%253A%2522UNASSIGNED_PORT%2522%252C%2522port%2522%253A2222%252C%2522id%2522%253A%2522clyk5cjbo004d2v6j3u55k74g%2522%252C%2522mode%2522%253A%2522permanent%2522%257D%252C%257B%2522type%2522%253A%2522ENV_SETUP%2522%252C%2522id%2522%253A%2522clyk5h8dp000r2v6j0r7kc7qq%2522%252C%2522mode%2522%253A%2522permanent%2522%257D%255D%257D%252C%2522clyk5bd9x00042v6jsos2y043%2522%253A%257B%2522id%2522%253A%2522clyk5bd9x00042v6jsos2y043%2522%252C%2522activeTabId%2522%253A%2522clyk5cbuv001q2v6joegrxxv6%2522%252C%2522tabs%2522%253A%255B%257B%2522id%2522%253A%2522clyk5bd9x00032v6jtfhj316o%2522%252C%2522mode%2522%253A%2522permanent%2522%252C%2522type%2522%253A%2522NEW_TERMINAL%2522%257D%252C%257B%2522type%2522%253A%2522TASK_LOG%2522%252C%2522taskId%2522%253A%2522dev%2522%252C%2522id%2522%253A%2522clyk5cbuv001q2v6joegrxxv6%2522%252C%2522mode%2522%253A%2522permanent%2522%257D%252C%257B%2522type%2522%253A%2522TASK_LOG%2522%252C%2522taskId%2522%253A%2522cleanupDist%2522%252C%2522id%2522%253A%2522clyk5dgvo005i2v6jj950sxft%2522%252C%2522mode%2522%253A%2522permanent%2522%257D%255D%257D%257D%252C%2522showDevtools%2522%253Atrue%252C%2522showShells%2522%253Atrue%252C%2522showSidebar%2522%253Atrue%252C%2522sidebarPanelSize%2522%253A15%257D" target="_blank">Demo on Codesandbox</a>
|
|
@@ -44,7 +44,7 @@ Add a ⭐️ and <a href="https://github.com/asmyshlyaev177" target="_blank">fol
|
|
|
44
44
|
- 🧮 Store unsaved user forms in URL
|
|
45
45
|
- 🙃 Share the state between different components without changing url, good as alternative to signals and other state management tools
|
|
46
46
|
- 🧠 Sync data between unrelated client components
|
|
47
|
-
- 🔗 Shareable URLs with
|
|
47
|
+
- 🔗 Shareable URLs with application state
|
|
48
48
|
- 🔄 Easy state persistence across page reloads
|
|
49
49
|
|
|
50
50
|
# Features
|
|
@@ -59,20 +59,24 @@ Add a ⭐️ and <a href="https://github.com/asmyshlyaev177" target="_blank">fol
|
|
|
59
59
|
## Table of content
|
|
60
60
|
|
|
61
61
|
- [Installation](#installation)
|
|
62
|
-
- [
|
|
63
|
-
- [
|
|
64
|
-
- [
|
|
65
|
-
- [
|
|
66
|
-
- [`
|
|
67
|
-
- [
|
|
68
|
-
-
|
|
62
|
+
- [useUrlState hook](#useurlstate)
|
|
63
|
+
- - [Next.js](#useurlstate-hook-for-nextjs)
|
|
64
|
+
- - [React-Router](#useurlstate-hook-for-react-router)
|
|
65
|
+
- [Other helpers](#other-hooks-and-helpers)
|
|
66
|
+
- - [`useUrlStateBase` for other routers](#useurlstatebase-hook-for-others-routers)
|
|
67
|
+
- - [`useSharedState` hook for React.js/Next.js](#usesharedstate-hook-for-reactjs)
|
|
68
|
+
- - [`useUrlEncode` for React.js](#useurlencode-hook-for-reactjs)
|
|
69
|
+
- - [`encodeState` and `decodeState` for pure JS usage](#encodestate-and-decodestate-helpers)
|
|
70
|
+
- - [Low-level `encode` and `decode` functions](#encode-and-decode-helpers)
|
|
69
71
|
- [Best practices](#best-practices)
|
|
70
|
-
- [Gothas](#gothas)
|
|
71
|
-
- [
|
|
72
|
-
- [
|
|
73
|
-
- [
|
|
74
|
-
- [
|
|
75
|
-
- [
|
|
72
|
+
- - [Gothas](#gothas)
|
|
73
|
+
- [Other](#other)
|
|
74
|
+
- - [Roadmap](#roadmap)
|
|
75
|
+
- - [Contributing](#contribute-andor-run-locally)
|
|
76
|
+
- - [Contact & Support](#contact--support)
|
|
77
|
+
- - [Changelog](#changelog)
|
|
78
|
+
- - [License](#license)
|
|
79
|
+
- - [Inspiration](#inspiration)
|
|
76
80
|
|
|
77
81
|
## installation
|
|
78
82
|
|
|
@@ -92,12 +96,14 @@ pnpm add state-in-url
|
|
|
92
96
|
In `tsconfig.json` in `compilerOptions` set `"moduleResolution": "Bundler"`, or`"moduleResolution": "Node16"`, or `"moduleResolution": "NodeNext"`.
|
|
93
97
|
Possibly need to set `"module": "ES2022"`, or `"module": "ESNext"`
|
|
94
98
|
|
|
99
|
+
# useUrlState
|
|
100
|
+
|
|
101
|
+
`useUrlState` is a custom React hook for Next.js/React-Router applications that make communication between client components easy. It allows you to share any complex state and sync it with the URL search parameters, providing a way to persist state across page reloads and share application state via URLs.
|
|
102
|
+
|
|
95
103
|
## useUrlState hook for Next.js
|
|
96
104
|
|
|
97
105
|
[Docs](packages/urlstate/next/useUrlState#api)
|
|
98
106
|
|
|
99
|
-
`useUrlState` is a custom React hook for Next.js applications that make communication between client components easy. It allows you to share any complex state and sync it with the URL search parameters, providing a way to persist state across page reloads and share application state via URLs.
|
|
100
|
-
|
|
101
107
|
### Usage examples
|
|
102
108
|
|
|
103
109
|
#### Basic
|
|
@@ -229,7 +235,7 @@ const tags = [
|
|
|
229
235
|
];
|
|
230
236
|
```
|
|
231
237
|
|
|
232
|
-
[Demo page example code](https://github.com/asmyshlyaev177/state-in-url/blob/main/packages/example-
|
|
238
|
+
[Demo page example code](https://github.com/asmyshlyaev177/state-in-url/blob/main/packages/example-nextjs14/src/app/Form.tsx)
|
|
233
239
|
|
|
234
240
|
#### Auto sync state
|
|
235
241
|
|
|
@@ -334,6 +340,90 @@ function SettingsComponent() {
|
|
|
334
340
|
}
|
|
335
341
|
```
|
|
336
342
|
|
|
343
|
+
## useUrlState hook for React-Router
|
|
344
|
+
|
|
345
|
+
API is same as for Next.js version, except can pass options from [NavigateOptions](https://github.com/remix-run/react-router/blob/bc693ed9f39170bda13b9e1b282fb8e9d5925f66/packages/react-router/lib/context.ts#L99) type.
|
|
346
|
+
|
|
347
|
+
[Docs](packages/urlstate/react-router/useUrlState#api)
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
### Example
|
|
351
|
+
|
|
352
|
+
```typescript
|
|
353
|
+
export const form: Form = {
|
|
354
|
+
name: '',
|
|
355
|
+
age: undefined,
|
|
356
|
+
'agree to terms': false,
|
|
357
|
+
tags: [],
|
|
358
|
+
};
|
|
359
|
+
|
|
360
|
+
type Form = {
|
|
361
|
+
name: string;
|
|
362
|
+
age?: number;
|
|
363
|
+
'agree to terms': boolean;
|
|
364
|
+
tags: { id: string; value: { text: string; time: Date } }[];
|
|
365
|
+
};
|
|
366
|
+
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
```typescript
|
|
370
|
+
import { useUrlState } from 'state-in-url/react-router';
|
|
371
|
+
|
|
372
|
+
import { form } from './form';
|
|
373
|
+
|
|
374
|
+
function TagsComponent() {
|
|
375
|
+
const { state, updateUrl } = useUrlState({ defaultState: form });
|
|
376
|
+
|
|
377
|
+
const onChangeTags = React.useCallback(
|
|
378
|
+
(tag: (typeof tags)[number]) => {
|
|
379
|
+
updateUrl((curr) => ({
|
|
380
|
+
...curr,
|
|
381
|
+
tags: curr.tags.find((t) => t.id === tag.id)
|
|
382
|
+
? curr.tags.filter((t) => t.id !== tag.id)
|
|
383
|
+
: curr.tags.concat(tag),
|
|
384
|
+
}));
|
|
385
|
+
},
|
|
386
|
+
[updateUrl],
|
|
387
|
+
);
|
|
388
|
+
|
|
389
|
+
return (
|
|
390
|
+
<div>
|
|
391
|
+
<Field text="Tags">
|
|
392
|
+
<div className="flex flex-wrap gap-2">
|
|
393
|
+
{tags.map((tag) => (
|
|
394
|
+
<Tag
|
|
395
|
+
active={!!state.tags.find((t) => t.id === tag.id)}
|
|
396
|
+
text={tag.value.text}
|
|
397
|
+
onClick={() => onChangeTags(tag)}
|
|
398
|
+
key={tag.id}
|
|
399
|
+
/>
|
|
400
|
+
))}
|
|
401
|
+
</div>
|
|
402
|
+
</Field>
|
|
403
|
+
</div>
|
|
404
|
+
);
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
const tags = [
|
|
408
|
+
{
|
|
409
|
+
id: '1',
|
|
410
|
+
value: { text: 'React.js', time: new Date('2024-07-17T04:53:17.000Z') },
|
|
411
|
+
},
|
|
412
|
+
{
|
|
413
|
+
id: '2',
|
|
414
|
+
value: { text: 'Next.js', time: new Date('2024-07-18T04:53:17.000Z') },
|
|
415
|
+
},
|
|
416
|
+
{
|
|
417
|
+
id: '3',
|
|
418
|
+
value: { text: 'TailwindCSS', time: new Date('2024-07-19T04:53:17.000Z') },
|
|
419
|
+
},
|
|
420
|
+
];
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
[Example code](packages/example-react-router6/src/Form-for-test.tsx)
|
|
424
|
+
|
|
425
|
+
# Other hooks and helpers
|
|
426
|
+
|
|
337
427
|
## `useUrlStateBase` hook for others routers
|
|
338
428
|
|
|
339
429
|
Hooks to create your own `useUrlState` hooks with other routers, e.g. react-router or tanstack router.
|
|
@@ -369,9 +459,9 @@ function SettingsComponent() {
|
|
|
369
459
|
|
|
370
460
|
[Docs](packages/urlstate/encoder/README.md)
|
|
371
461
|
|
|
372
|
-
|
|
462
|
+
# Best Practices
|
|
373
463
|
|
|
374
|
-
- Define your state shape as a constant
|
|
464
|
+
- Define your state shape as a constant
|
|
375
465
|
- Use TypeScript for enhanced type safety and autocomplete
|
|
376
466
|
- Avoid storing sensitive information in URL parameters (SSN, API keys etc)
|
|
377
467
|
- Use `updateState` for frequent updates and `updateUrl` to sync changes to url
|
|
@@ -380,34 +470,33 @@ function SettingsComponent() {
|
|
|
380
470
|
|
|
381
471
|
## Gothas
|
|
382
472
|
|
|
383
|
-
1. Can pass only serializable values, `Function`, `BigInt` or `Symbol` won't work, probably things like `ArrayBuffer` neither.
|
|
473
|
+
1. Can pass only serializable values, `Function`, `BigInt` or `Symbol` won't work, probably things like `ArrayBuffer` neither. Everything that can be serialized to JSON will work.
|
|
384
474
|
2. Vercel servers limit size of headers (query string and other stuff) to **14KB**, so keep your URL state under ~5000 words. <https://vercel.com/docs/errors/URL_TOO_LONG>
|
|
385
|
-
3. Tested with `next.js` 14
|
|
475
|
+
3. Tested with `next.js` 14/15 with app router, no plans to support pages.
|
|
386
476
|
|
|
387
|
-
|
|
477
|
+
# Other
|
|
388
478
|
|
|
389
|
-
|
|
479
|
+
## Contribute and/or run locally
|
|
390
480
|
|
|
391
|
-
|
|
392
|
-
npm run dev
|
|
393
|
-
```
|
|
481
|
+
See [Contributing doc](CONTRIBUTING.md)
|
|
394
482
|
|
|
395
|
-
Go to [localhost:3000](http://localhost:3000)
|
|
396
483
|
|
|
397
484
|
## Roadmap
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
485
|
+
|
|
486
|
+
- [x] hook for `Next.js`
|
|
487
|
+
- [x] hook for 'react-router`
|
|
488
|
+
- [ ] hook for 'remix`
|
|
489
|
+
- [ ] hook for store state in hash ?
|
|
401
490
|
|
|
402
491
|
## Contact & Support
|
|
403
492
|
|
|
404
493
|
- Create a [GitHub issue](https://github.com/asmyshlyaev177/state-in-url/issues) for bug reports, feature requests, or questions
|
|
405
494
|
|
|
406
|
-
## [Changelog](
|
|
495
|
+
## [Changelog](CHANGELOG.md)
|
|
407
496
|
|
|
408
497
|
## License
|
|
409
498
|
|
|
410
|
-
This project is licensed under the [MIT license](
|
|
499
|
+
This project is licensed under the [MIT license](LICENSE).
|
|
411
500
|
|
|
412
501
|
## Inspiration
|
|
413
502
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const
|
|
1
|
+
const e={date:"⏲",undefined:"∙undefined"};export{e as SYMBOLS};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{encode as t,decode as
|
|
1
|
+
import{encode as t,decode as n}from"../encoder/encoder.mjs";import{getParams as o}from"../utils.mjs";function r(t){let n,o=t[0],r=1;for(;r<t.length;){const e=t[r],c=t[r+1];if(r+=2,("optionalAccess"===e||"optionalCall"===e)&&null==o)return;"access"===e||"optionalAccess"===e?(n=o,o=c(o)):"call"!==e&&"optionalCall"!==e||(o=c(((...t)=>o.call(n,...t))),n=void 0)}return o}function e(n,e,c){const s=o(c);return Object.entries(n||{}).forEach((([n,o])=>{const c=r([e,"optionalAccess",t=>t[n]]);JSON.stringify(o)!==JSON.stringify(c)&&s.set(n,t(o))})),s.toString()}function c(t,e){return{...e||{},...Object.fromEntries([...o(t).entries()].map((([t,o])=>{const c=r([e,"optionalAccess",n=>n[t]]);return[t,(s=n(o,c),i=()=>c,null!=s?s:i())];var s,i})))}}export{c as decodeState,e as encodeState};
|
package/dist/encoder/encoder.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{SYMBOLS as t}from"../constants/constants.mjs";import{typeOf as
|
|
1
|
+
import{SYMBOLS as t}from"../constants/constants.mjs";import{typeOf as n}from"../utils.mjs";function e(e){if(l(e))return e;switch(n(e)){case"function":case"symbol":return"";case"date":return r=e,t.date+new Date(r).toISOString();case"undefined":return t.undefined;default:return JSON.stringify(e).replaceAll('"',"'")}var r}function r(t,n){return a(t.replaceAll("'",'"'),n)}const o=n=>{if(n!==t.undefined)return function(t){let n,e=t[0],r=1;for(;r<t.length;){const o=t[r],s=t[r+1];if(r+=2,("optionalAccess"===o||"optionalCall"===o)&&null==e)return;"access"===o||"optionalAccess"===o?(n=e,e=s(e)):"call"!==o&&"optionalCall"!==o||(e=s(((...t)=>e.call(n,...t))),n=void 0)}return e}([n,"optionalAccess",t=>t.startsWith,"optionalCall",n=>n(t.date)])?new Date(n.slice(1)):s},s=Symbol("isError"),c=(t,n)=>{const e="string"==typeof n,r=e&&o(n);return r===s?n:e?r:n};function a(t,n){try{return JSON.parse(t,c)}catch(e){const r=o(t);return r!==s?r:n}}const i=new RegExp(`^(${t.undefined}|${t.date})`),l=t=>i.test(String(t));export{r as decode,o as decodePrimitive,e as encode,s as errorSym,a as parseJSON,c as reviver};
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export{decode,encode}from"./encoder/encoder.mjs";export{decodeState,encodeState}from"./encodeState/encodeState.mjs";export{
|
|
1
|
+
export{decode,encode}from"./encoder/encoder.mjs";export{decodeState,encodeState}from"./encodeState/encodeState.mjs";export{useUrlState}from"./next/useUrlState/useUrlState.mjs";export{useSharedState}from"./useSharedState/useSharedState.mjs";export{useUrlEncode}from"./useUrlEncode/useUrlEncode.mjs";export{useUrlStateBase}from"./useUrlStateBase/useUrlStateBase.mjs";export{isSSR,typeOf}from"./utils.mjs";
|
package/dist/next/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export{
|
|
1
|
+
export{useUrlState}from"./useUrlState/useUrlState.mjs";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{useRouter as
|
|
1
|
+
import{useRouter as t,useSearchParams as e}from"next/navigation";import a from"react";import{parseSPObj as r}from"../../parseSPObj.mjs";import{useUrlStateBase as s}from"../../useUrlStateBase/useUrlStateBase.mjs";import{filterUnknownParams as o,isSSR as m,filterUnknownParamsClient as p}from"../../utils.mjs";function u({defaultState:u,searchParams:i,...l}){const n=t(),{state:f,updateState:S,updateUrl:d,getState:j}=s(u,n,(({parse:t})=>m()?r(o(u,i),u):t(p(u)))),U=a.useCallback(((t,e)=>{const a={...c,...l,...e};d(t,a)}),[d,l]),b=e();return a.useEffect((()=>{S(o(u,r(Object.fromEntries([...b.entries()]),u)))}),[b]),{updateState:S,updateUrl:U,state:f,getState:j}}const c={replace:!0,scroll:!1};export{u as useUrlState};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{decodePrimitive as n,errorSym as t,decode as o}from"./encoder/encoder.mjs";function l(n,t){return{...t,...r(JSON.stringify(n),t)}}function r(o,l){try{return JSON.parse(o,c)}catch(r){const c=n(o);return c!==t?c:l}}const c=(n,t)=>{const l="string"==typeof t,r=l&&o(function(n){let t,o=n[0],l=1;for(;l<n.length;){const r=n[l],c=n[l+1];if(l+=2,("optionalAccess"===r||"optionalCall"===r)&&null==o)return;"access"===r||"optionalAccess"===r?(t=o,o=c(o)):"call"!==r&&"optionalCall"!==r||(o=c(((...n)=>o.call(t,...n))),t=void 0)}return o}([t,"optionalAccess",n=>n.replaceAll,"optionalCall",n=>n("'",'"')]));return n&&l?r:t};export{l as parseSPObj};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{useUrlState}from"./useUrlState/useUrlState.mjs";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{useUrlState}from"./useUrlState.mjs";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import t from"react";import{useNavigate as e,useSearchParams as r}from"react-router-dom";import{parseSPObj as a}from"../../parseSPObj.mjs";import{useUrlStateBase as s}from"../../useUrlStateBase/useUrlStateBase.mjs";import{assignValue as o,filterUnknownParams as m,filterUnknownParamsClient as p}from"../../utils.mjs";function u({defaultState:u,...l}){const f=e(),i=t.useMemo((()=>({replace:(t,e)=>f(t,{...c,...l,...e}),push:(t,e)=>f(t,{...c,...l,...e})})),[f,l]),{state:n,updateState:S,updateUrl:d,getState:j}=s(u,i,(({parse:t})=>t(p(u)))),U=t.useCallback(((t,e)=>{const r={...c,...l,...e};d(t,r)}),[l]),[b]=r();return t.useEffect((()=>{S(o(u,n,m(u,a(Object.fromEntries([...b.entries()]),u))))}),[b]),{updateState:S,updateUrl:U,state:n,getState:j}}const c={replace:!0,preventScrollReset:!0};export{u as useUrlState};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import t from"react";import{stateMap as r,subscribers as e}from"../subscribers.mjs";import{useInsertionEffect as n}from"../useInsertionEffect.mjs";import{isSSR as
|
|
1
|
+
import t from"react";import{stateMap as r,subscribers as e}from"../subscribers.mjs";import{useInsertionEffect as n}from"../useInsertionEffect.mjs";import{isSSR as c,isEqual as o}from"../utils.mjs";function u(t){let r,e=t[0],n=1;for(;n<t.length;){const c=t[n],o=t[n+1];if(n+=2,("optionalAccess"===c||"optionalCall"===c)&&null==e)return;"access"===c||"optionalAccess"===c?(r=e,e=o(e)):"call"!==c&&"optionalCall"!==c||(e=o(((...t)=>e.call(r,...t))),r=void 0)}return e}function s(s,l){const a=t.useRef(s),[i,f]=t.useState((()=>{if(c())return l?u([l,"optionalCall",t=>t()]):a.current;const t=r.get(a.current);if(t)return t;{const t=u([l,"optionalCall",t=>t()])||a.current;return r.set(a.current,t),t}})),p=t.useCallback((t=>{const n=r.get(a.current),c="function"==typeof t?t(n):{...n,...t};o(n,c)||(r.set(a.current,c),e.get(a.current).forEach((t=>{t()})))}),[]);n((()=>{const t=e.add(a.current,(()=>{f(r.get(a.current)||a.current)}));return()=>{t()}}),[]);return{state:i,getState:t.useCallback((()=>r.get(a.current)||a.current),[]),setState:p}}export{s as useSharedState};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import t from"react";import{useInsertionEffect as e}from"../useInsertionEffect.mjs";import{useSharedState as o}from"../useSharedState/useSharedState.mjs";import{useUrlEncode as n}from"../useUrlEncode/useUrlEncode.mjs";import{filterUnknownParamsClient as a}from"../utils.mjs";function s(s,c,i){const{parse:
|
|
1
|
+
import t from"react";import{useInsertionEffect as e}from"../useInsertionEffect.mjs";import{useSharedState as o}from"../useSharedState/useSharedState.mjs";import{useUrlEncode as n}from"../useUrlEncode/useUrlEncode.mjs";import{filterUnknownParamsClient as a}from"../utils.mjs";function s(s,c,i){const{parse:l,stringify:p}=n(s),{state:u,getState:m,setState:d}=o(s,(()=>function(t){let e,o=t[0],n=1;for(;n<t.length;){const a=t[n],s=t[n+1];if(n+=2,("optionalAccess"===a||"optionalCall"===a)&&null==o)return;"access"===a||"optionalAccess"===a?(e=o,o=s(o)):"call"!==a&&"optionalCall"!==a||(o=s(((...t)=>o.call(e,...t))),e=void 0)}return o}([i,"optionalCall",t=>t({parse:l})])||s));e((()=>{const t=()=>{const t=l(a(s));d(t)};return window.addEventListener(r,t),()=>{window.removeEventListener(r,t)}}),[d]);const w=t.useCallback(((t,e)=>{const o=`${window.location.pathname}${window.location.search}${window.location.hash}`,n="function"==typeof t,a=function(t){const e=Object.keys(t),o=window.location.search,n=new URLSearchParams(o),a=new URLSearchParams;return n.forEach(((t,o)=>!e.includes(o)&&a.set(o,t))),a}(s),r=n?t(m()):t?{...m(),...t}:m(),i=p(r,a);d(r);const l=`${window.location.pathname}${i.length?"?":""}${i}${window.location.hash}`;if(o!==l){const{replace:t,...o}=e||{};c[t?"replace":"push"](l,{...o})}}),[c,p,m]);return{updateState:d,updateUrl:w,state:u,getState:m}}const r="popstate";export{s as useUrlStateBase};
|
package/dist/utils.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const t=t=>{const
|
|
1
|
+
function t(t){let n,e=t[0],o=1;for(;o<t.length;){const c=t[o],r=t[o+1];if(o+=2,("optionalAccess"===c||"optionalCall"===c)&&null==e)return;"access"===c||"optionalAccess"===c?(n=e,e=r(e)):"call"!==c&&"optionalCall"!==c||(e=r(((...t)=>e.call(n,...t))),n=void 0)}return e}const n=t=>{const n=typeof t,e=null===t,o=Array.isArray(t),c=t instanceof Date;return(e?"null":c&&"date")||o&&"array"||!e&&!c&&!o&&"object"===n&&"object"||n},e=()=>"undefined"==typeof window,o=n=>new URLSearchParams("string"==typeof n?c(n):t([n,"optionalAccess",t=>t.toString,"optionalCall",t=>t()])||""),c=n=>t([n,"access",t=>t.split,"call",t=>t("?"),"optionalAccess",t=>t[1]])||n||"",r=(t,n)=>JSON.stringify(t)===JSON.stringify(n);function a(t){const n=new URLSearchParams;return i(t,[...new URLSearchParams(window.location.search).entries()]).forEach((([t,e])=>n.set(t,e))),n.toString()}function s(t,n){return Object.fromEntries(i(t,Object.entries(n||{})))}function i(t,n){const e=Object.keys(t);return n.filter((([t])=>e.includes(t))).map((([t,n])=>[t.replaceAll("+"," "),n]))}function l(t,n,e){const o=Object.assign({},t,n);return Object.entries(t).forEach((([n])=>{const c=n,r=void 0!==e[c];o[c]=r?e[c]:t[c]})),o}export{l as assignValue,s as filterUnknownParams,a as filterUnknownParamsClient,o as getParams,r as isEqual,e as isSSR,n as typeOf};
|