vue-router-query-sync 1.0.1 → 2.0.0-alpha.2
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 +80 -170
- package/dist/defineCodec.d.ts +3 -0
- package/dist/defineCodec.d.ts.map +1 -0
- package/dist/index.d.ts +4 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +185 -69
- package/dist/internal/batch.d.ts +10 -0
- package/dist/internal/batch.d.ts.map +1 -0
- package/dist/internal/equal.d.ts +2 -0
- package/dist/internal/equal.d.ts.map +1 -0
- package/dist/internal/field.d.ts +5 -0
- package/dist/internal/field.d.ts.map +1 -0
- package/dist/internal/normalize.d.ts +3 -0
- package/dist/internal/normalize.d.ts.map +1 -0
- package/dist/param.d.ts +39 -0
- package/dist/param.d.ts.map +1 -0
- package/dist/types.d.ts +23 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/useQueryFilters.d.ts +3 -0
- package/dist/useQueryFilters.d.ts.map +1 -0
- package/package.json +17 -13
- package/dist/composables/useQuerySync.d.ts +0 -17
- package/dist/composables/useQuerySync.d.ts.map +0 -1
- package/dist/index.js +0 -1
- package/dist/router.d.ts +0 -4
- package/dist/router.d.ts.map +0 -1
- package/dist/types/index.d.ts +0 -6
- package/dist/types/index.d.ts.map +0 -1
- package/dist/utils/replaceRouterQueue.d.ts +0 -2
- package/dist/utils/replaceRouterQueue.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -1,213 +1,123 @@
|
|
|
1
1
|
# vue-router-query-sync
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> Draft docs for `2.0.0-alpha.0`. API only — no tests, migration guide or final docs yet.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
A reactive, typed view of the Vue Router query string. The URL (`route.query`) is the
|
|
6
|
+
single source of truth: reads parse `route.query`, writes navigate the router. The library
|
|
7
|
+
holds no state of its own and never throws because of URL contents.
|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
+
- Vue 3 + Vue Router 4 (peer dependencies).
|
|
10
|
+
- Codecs + defaults per param; defaults never appear in the URL.
|
|
11
|
+
- Arrays use native repeated keys (`?a=1&a=2`).
|
|
12
|
+
- Batched navigation: several writes in one tick collapse into one `push`/`replace`.
|
|
13
|
+
- SSR-safe: router is read via `useRouter()`/`useRoute()`, no global/module state.
|
|
9
14
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
## ✨ What is this?
|
|
13
|
-
|
|
14
|
-
`vue-router-query-sync` is a tiny, fully-typed Vue 3 utility that keeps your reactive state
|
|
15
|
-
(Pinia store fields or local refs) in sync with the current URL query string — both ways.
|
|
16
|
-
|
|
17
|
-
- Changes in your store update the URL query.
|
|
18
|
-
- Changes in the URL query update your store.
|
|
19
|
-
- Batched updates prevent excessive `router.replace` calls.
|
|
20
|
-
|
|
21
|
-
---
|
|
22
|
-
|
|
23
|
-
## 💡 Why use this plugin?
|
|
24
|
-
|
|
25
|
-
- 🔄 Keeps your app state and URL perfectly in sync — no more manual watchers or `router.replace` logic.
|
|
26
|
-
- 🧠 Works with **Pinia**, **local refs**, or any reactive source.
|
|
27
|
-
- 🧩 Handles multiple query keys and isolated contexts safely.
|
|
28
|
-
- ⚙️ Fully typed with TypeScript and designed for Vue 3’s Composition API.
|
|
29
|
-
- 🚀 Tiny footprint — optimized for production.
|
|
30
|
-
|
|
31
|
-
## ✅ Requirements
|
|
32
|
-
|
|
33
|
-
- Vue 3
|
|
34
|
-
- Vue Router 4
|
|
35
|
-
|
|
36
|
-
---
|
|
37
|
-
|
|
38
|
-
## 🚀 Installation
|
|
15
|
+
## Install
|
|
39
16
|
|
|
40
17
|
```bash
|
|
41
18
|
npm install vue-router-query-sync
|
|
42
|
-
# or
|
|
43
|
-
yarn add vue-router-query-sync
|
|
44
|
-
# or
|
|
45
|
-
pnpm add vue-router-query-sync
|
|
46
19
|
```
|
|
47
20
|
|
|
48
|
-
|
|
21
|
+
## `useQueryFilters(schema)`
|
|
49
22
|
|
|
50
|
-
|
|
23
|
+
Returns `{ filters, patch, reset }`. `filters` is a reactive object of schema fields only
|
|
24
|
+
(no methods on it); access fields without `.value`. The type is inferred from the schema.
|
|
51
25
|
|
|
52
26
|
```ts
|
|
53
|
-
|
|
54
|
-
import { createApp } from 'vue'
|
|
55
|
-
import { createRouter, createWebHistory } from 'vue-router'
|
|
56
|
-
import routerQuerySync from 'vue-router-query-sync'
|
|
57
|
-
import App from './App.vue'
|
|
58
|
-
|
|
59
|
-
const router = createRouter({
|
|
60
|
-
history: createWebHistory(),
|
|
61
|
-
routes: []
|
|
62
|
-
})
|
|
27
|
+
import { useQueryFilters, param } from 'vue-router-query-sync'
|
|
63
28
|
|
|
64
|
-
|
|
65
|
-
.use(router)
|
|
66
|
-
.use(routerQuerySync, { router })
|
|
67
|
-
.mount('#app')
|
|
68
|
-
```
|
|
29
|
+
enum SortType { Popular = 'popular', New = 'new' }
|
|
69
30
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
#### Sync a value with a query param named `tab`:
|
|
77
|
-
|
|
78
|
-
- Visiting `?tab=favorite` sets `tab.value = 'favorite'`.
|
|
79
|
-
- Changing `tab.value = 'all'` updates the URL to `?tab=all`.
|
|
80
|
-
|
|
81
|
-
```ts
|
|
82
|
-
import { useQuerySync } from 'vue-router-query-sync'
|
|
83
|
-
|
|
84
|
-
const tab = ref<'favorite' | 'all'>('all')
|
|
31
|
+
const { filters, patch, reset } = useQueryFilters({
|
|
32
|
+
sort: param.enum(SortType, { default: SortType.Popular, history: 'push' }),
|
|
33
|
+
brands: param.stringArray(), // default: []
|
|
34
|
+
page: param.number({ default: 1 }),
|
|
35
|
+
from: param.custom(dateCodec), // default: null
|
|
36
|
+
})
|
|
85
37
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
)
|
|
38
|
+
filters.sort = SortType.New // write -> router navigation
|
|
39
|
+
filters.brands // read -> parses route.query (or pending write)
|
|
40
|
+
patch({ brands: ['lg'], page: 2 }) // several fields, ONE navigation
|
|
41
|
+
reset() // all fields back to defaults (keys removed)
|
|
91
42
|
```
|
|
92
43
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
-
|
|
97
|
-
-
|
|
44
|
+
- **Read**: pending write (same tick) → else `route.query[key]` → `deserialize` → on
|
|
45
|
+
`undefined`/throw → `default`. Reading a field right after writing it returns the new value.
|
|
46
|
+
- **Write**: `serialize` → if `null` or equal to `serialize(default)` → the key is removed.
|
|
47
|
+
- Query keys not described in the schema are left untouched.
|
|
48
|
+
- Destructuring `filters` loses reactivity — use Vue's `toRefs(filters)`.
|
|
98
49
|
|
|
99
|
-
|
|
100
|
-
import { useQuerySync } from 'vue-router-query-sync'
|
|
101
|
-
|
|
102
|
-
const brands = [
|
|
103
|
-
{ value: 'lg', label: 'LG' },
|
|
104
|
-
{ value: 'samsung', label: 'Samsung' }
|
|
105
|
-
]
|
|
106
|
-
|
|
107
|
-
const selectedBrands = ref<string[]>([])
|
|
108
|
-
|
|
109
|
-
useQuerySync(
|
|
110
|
-
'brands',
|
|
111
|
-
() => {
|
|
112
|
-
return selectedBrands.value.length > 0 ? selectedBrands.value.join('%') : null
|
|
113
|
-
},
|
|
114
|
-
(val) => {
|
|
115
|
-
if (typeof val === 'string' && val) {
|
|
116
|
-
selectedBrands.value = val.includes('%') ? val.split('%') : [val]
|
|
117
|
-
} else {
|
|
118
|
-
selectedBrands.value = []
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
)
|
|
122
|
-
```
|
|
123
|
-
---
|
|
50
|
+
### Single parameter
|
|
124
51
|
|
|
125
|
-
|
|
52
|
+
There is no separate single-param helper: use a one-key schema and `toRef`.
|
|
126
53
|
|
|
127
54
|
```ts
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
get: () => T | null,
|
|
131
|
-
set: (val: T) => void,
|
|
132
|
-
options?: QuerySyncOptions
|
|
133
|
-
): void
|
|
134
|
-
|
|
135
|
-
type QuerySyncOptions = {
|
|
136
|
-
deps?: Ref<unknown>[]
|
|
137
|
-
context?: string
|
|
138
|
-
}
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
- **key**: Query parameter name, e.g., `'tab'`.
|
|
142
|
-
- **get**: Function returning the current value from your store/ref. Return `null` to indicate “no value”.
|
|
143
|
-
- **set**: Function that writes the value to your store/ref.
|
|
144
|
-
- **options.deps**: Array of refs. If provided, the initial sync runs after any of these deps change (useful when state is populated asynchronously).
|
|
145
|
-
- **options.context**: If the same query key may be used multiple times on the same page, provide a unique context to avoid collisions. The actual query key becomes `${context}_${key}`.
|
|
146
|
-
|
|
147
|
-
---
|
|
148
|
-
|
|
149
|
-
## ❗ Important
|
|
150
|
-
|
|
151
|
-
If a page can have multiple components with the same query key, pass a unique `context` to avoid conflicts.
|
|
152
|
-
The real key used in the URL will be `${context}_${key}`. Otherwise, use unique keys per component.
|
|
55
|
+
import { toRef } from 'vue'
|
|
56
|
+
import { useQueryFilters, param } from 'vue-router-query-sync'
|
|
153
57
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
If two widgets on the same page need a `tab` param, use unique contexts:
|
|
159
|
-
|
|
160
|
-
```ts
|
|
161
|
-
useQuerySync('tab', () => usersStore.tab, (v) => (usersStore.tab = v), { context: 'users' })
|
|
162
|
-
useQuerySync('tab', () => ordersStore.tab, (v) => (ordersStore.tab = v), { context: 'orders' })
|
|
163
|
-
// URL keys will be: users_tab and orders_tab
|
|
58
|
+
const { filters } = useQueryFilters({ tab: param.enum(['all', 'favorite'] as const) })
|
|
59
|
+
const tab = toRef(filters, 'tab') // WritableComputedRef<'all' | 'favorite' | null>
|
|
60
|
+
tab.value = 'favorite'
|
|
164
61
|
```
|
|
165
62
|
|
|
166
|
-
|
|
63
|
+
## `param`
|
|
167
64
|
|
|
168
|
-
|
|
65
|
+
All options are shared: `{ default?: T; history?: 'push' | 'replace' }` (`history` defaults to
|
|
66
|
+
`'replace'`). Passing `default` narrows the field type from `T | null` to `T`.
|
|
169
67
|
|
|
170
|
-
|
|
68
|
+
| Factory | Field type | Notes |
|
|
69
|
+
| --- | --- | --- |
|
|
70
|
+
| `param.string(options?)` | `string \| null` | |
|
|
71
|
+
| `param.number(options?)` | `number \| null` | |
|
|
72
|
+
| `param.boolean(options?)` | `boolean \| null` | URL is `'true'` / `'false'` |
|
|
73
|
+
| `param.stringArray(options?)` | `string[]` | repeated keys; default always `[]` |
|
|
74
|
+
| `param.enum(input, options?)` | member of `input` | see below |
|
|
75
|
+
| `param.custom(codec, options?)` | `T` from codec | default `null` if unset |
|
|
171
76
|
|
|
172
|
-
|
|
173
|
-
|
|
77
|
+
`param.enum` accepts either a readonly string array or a TS enum object (string or numeric).
|
|
78
|
+
Numeric enums have their reverse mapping filtered out and URL strings are coerced to numbers.
|
|
79
|
+
A value outside the set becomes `undefined` → `default` (behaviour mirrors `z.enum`).
|
|
174
80
|
|
|
175
|
-
|
|
81
|
+
## Codecs
|
|
176
82
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
```
|
|
180
|
-
|
|
181
|
-
---
|
|
83
|
+
```ts
|
|
84
|
+
import { defineCodec, type QueryCodec } from 'vue-router-query-sync'
|
|
182
85
|
|
|
183
|
-
|
|
86
|
+
interface QueryCodec<T> {
|
|
87
|
+
serialize(value: T): string | string[] | null // null = remove key
|
|
88
|
+
deserialize(raw: string | string[]): T | undefined // undefined = use default
|
|
89
|
+
}
|
|
184
90
|
|
|
185
|
-
|
|
186
|
-
|
|
91
|
+
const dateCodec = defineCodec<Date | null>({
|
|
92
|
+
serialize: (d) => (d ? d.toISOString().slice(0, 10) : null),
|
|
93
|
+
deserialize: (raw) => {
|
|
94
|
+
const t = Date.parse(Array.isArray(raw) ? raw[0] : raw)
|
|
95
|
+
return Number.isNaN(t) ? undefined : new Date(t)
|
|
96
|
+
},
|
|
97
|
+
})
|
|
187
98
|
```
|
|
188
99
|
|
|
189
|
-
|
|
190
|
-
- **useQuerySync**: The composable described above.
|
|
191
|
-
- **replaceRouterQueue**: Internal helper that batches query updates (exported in case you need manual batching).
|
|
192
|
-
|
|
193
|
-
Note: `setRouter/getRouter` are internal; prefer using the plugin install.
|
|
100
|
+
`defineCodec` is an identity helper for type inference. All built-in `param.*` types are codecs.
|
|
194
101
|
|
|
195
|
-
|
|
102
|
+
## Batching & history
|
|
196
103
|
|
|
197
|
-
|
|
104
|
+
All writes in the same tick — field assignments, `patch`, `reset` — accumulate into one
|
|
105
|
+
pending batch (kept per router instance) and are applied as a **single** navigation via
|
|
106
|
+
`queueMicrotask`. The batch is layered over the last *scheduled* state, so reads within the
|
|
107
|
+
same tick see pending writes. If any changed param in the batch has `history: 'push'`, the
|
|
108
|
+
whole batch uses `router.push`; otherwise `router.replace`. Query keys are sorted for a
|
|
109
|
+
deterministic URL.
|
|
198
110
|
|
|
199
|
-
|
|
111
|
+
## Playground
|
|
200
112
|
|
|
201
|
-
```
|
|
202
|
-
|
|
113
|
+
```bash
|
|
114
|
+
npm run dev
|
|
203
115
|
```
|
|
204
116
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
117
|
+
A catalog page exercises every param type plus `reset`/`patch`, and a second route shows the
|
|
118
|
+
single-parameter pattern (`toRef` over a one-key schema). The current `route.query` is
|
|
119
|
+
rendered on screen.
|
|
208
120
|
|
|
209
|
-
##
|
|
121
|
+
## License
|
|
210
122
|
|
|
211
123
|
MIT © Ivan Chikachev
|
|
212
|
-
|
|
213
|
-
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defineCodec.d.ts","sourceRoot":"","sources":["../src/defineCodec.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAGzC,wBAAgB,WAAW,CAAC,CAAC,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAElE"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,13 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
export
|
|
4
|
-
export
|
|
5
|
-
export * from './router';
|
|
6
|
-
export * from './types/index';
|
|
7
|
-
declare const _default: {
|
|
8
|
-
install(app: App, options: {
|
|
9
|
-
router: Router;
|
|
10
|
-
}): void;
|
|
11
|
-
};
|
|
12
|
-
export default _default;
|
|
1
|
+
export { useQueryFilters } from './useQueryFilters';
|
|
2
|
+
export { param } from './param';
|
|
3
|
+
export { defineCodec } from './defineCodec';
|
|
4
|
+
export type { QueryCodec, ParamOptions, Param, FilterSchema, InferFilters, UseQueryFiltersReturn } from './types';
|
|
13
5
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACnD,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAC/B,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAC3C,YAAY,EACV,UAAU,EACV,YAAY,EACZ,KAAK,EACL,YAAY,EACZ,YAAY,EACZ,qBAAqB,EACtB,MAAM,SAAS,CAAA"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,77 +1,193 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
function
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
}
|
|
36
|
-
function B(e, t, s, c = {}) {
|
|
37
|
-
const o = S().currentRoute, { deps: m = [], context: q } = c, r = q ? `${q}_${e}` : e, d = (u, i = !1) => {
|
|
38
|
-
if (typeof u == "string") {
|
|
39
|
-
const n = N(u);
|
|
40
|
-
if (i || n !== t()) {
|
|
41
|
-
s(n);
|
|
42
|
-
const p = t();
|
|
43
|
-
p !== n && p !== null && l(r, p);
|
|
44
|
-
}
|
|
45
|
-
} else if (u === void 0) {
|
|
46
|
-
const n = t();
|
|
47
|
-
n !== null && l(r, n);
|
|
48
|
-
}
|
|
49
|
-
}, h = (u) => {
|
|
50
|
-
const i = o.value.query[r];
|
|
51
|
-
if (u === null)
|
|
52
|
-
i !== void 0 && l(r, null);
|
|
53
|
-
else {
|
|
54
|
-
const n = String(u);
|
|
55
|
-
i !== n && l(r, u);
|
|
1
|
+
import { reactive as A, computed as N } from "vue";
|
|
2
|
+
import { useRoute as v, useRouter as S } from "vue-router";
|
|
3
|
+
function g(e) {
|
|
4
|
+
if (e != null)
|
|
5
|
+
return Array.isArray(e) ? e.filter((r) => r !== null) : e;
|
|
6
|
+
}
|
|
7
|
+
function o(e, r) {
|
|
8
|
+
return e === r ? !0 : Array.isArray(e) && Array.isArray(r) ? e.length !== r.length ? !1 : e.every((t, u) => t === r[u]) : !1;
|
|
9
|
+
}
|
|
10
|
+
const h = /* @__PURE__ */ new WeakMap();
|
|
11
|
+
function m(e) {
|
|
12
|
+
let r = h.get(e);
|
|
13
|
+
return r || (r = {
|
|
14
|
+
patch: A(/* @__PURE__ */ new Map()),
|
|
15
|
+
usePush: !1,
|
|
16
|
+
scheduled: !1
|
|
17
|
+
}, h.set(e, r)), r;
|
|
18
|
+
}
|
|
19
|
+
function P(e, r) {
|
|
20
|
+
const t = m(e);
|
|
21
|
+
return t.patch.has(r) ? { pending: !0, value: t.patch.get(r) ?? null } : { pending: !1, value: null };
|
|
22
|
+
}
|
|
23
|
+
function z(e, r, t, u) {
|
|
24
|
+
const l = m(e);
|
|
25
|
+
l.patch.set(r, t), u === "push" && (l.usePush = !0), l.scheduled || (l.scheduled = !0, queueMicrotask(() => q(e)));
|
|
26
|
+
}
|
|
27
|
+
function j(e, r) {
|
|
28
|
+
const t = Object.keys(e), u = Object.keys(r);
|
|
29
|
+
if (t.length !== u.length)
|
|
30
|
+
return !1;
|
|
31
|
+
const l = (n, c) => {
|
|
32
|
+
if (Array.isArray(n) || Array.isArray(c)) {
|
|
33
|
+
const a = Array.isArray(n) ? n : [n], s = Array.isArray(c) ? c : [c];
|
|
34
|
+
return a.length === s.length && a.every((i, f) => String(i) === String(s[f]));
|
|
56
35
|
}
|
|
36
|
+
return String(n) === String(c);
|
|
57
37
|
};
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
38
|
+
return t.every((n) => n in r && l(e[n], r[n]));
|
|
39
|
+
}
|
|
40
|
+
function q(e) {
|
|
41
|
+
const r = h.get(e);
|
|
42
|
+
if (!r)
|
|
43
|
+
return;
|
|
44
|
+
if (r.scheduled = !1, r.patch.size === 0) {
|
|
45
|
+
r.usePush = !1;
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const t = r.usePush;
|
|
49
|
+
r.usePush = !1;
|
|
50
|
+
const u = e.currentRoute.value.query, l = {};
|
|
51
|
+
for (const [i, f] of Object.entries(u))
|
|
52
|
+
f !== null && (l[i] = Array.isArray(f) ? f.filter((b) => b !== null) : f);
|
|
53
|
+
const n = new Map(r.patch);
|
|
54
|
+
n.forEach((i, f) => {
|
|
55
|
+
i === null ? delete l[f] : l[f] = i;
|
|
65
56
|
});
|
|
57
|
+
const c = {};
|
|
58
|
+
for (const i of Object.keys(l).sort())
|
|
59
|
+
c[i] = l[i];
|
|
60
|
+
const a = () => {
|
|
61
|
+
n.forEach((i, f) => {
|
|
62
|
+
r.patch.get(f) === i && r.patch.delete(f);
|
|
63
|
+
});
|
|
64
|
+
};
|
|
65
|
+
if (j(u, c)) {
|
|
66
|
+
a();
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
(t ? e.push({ query: c }) : e.replace({ query: c })).then(a, a);
|
|
66
70
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
71
|
+
function O(e, r, t, u) {
|
|
72
|
+
const l = P(r, t);
|
|
73
|
+
let n;
|
|
74
|
+
if (l.pending) {
|
|
75
|
+
if (l.value === null)
|
|
76
|
+
return u.default;
|
|
77
|
+
n = g(l.value);
|
|
78
|
+
} else
|
|
79
|
+
n = g(e.query[t]);
|
|
80
|
+
if (n === void 0)
|
|
81
|
+
return u.default;
|
|
82
|
+
try {
|
|
83
|
+
const c = u.codec.deserialize(n);
|
|
84
|
+
return c === void 0 ? u.default : c;
|
|
85
|
+
} catch {
|
|
86
|
+
return u.default;
|
|
70
87
|
}
|
|
88
|
+
}
|
|
89
|
+
function y(e, r, t, u) {
|
|
90
|
+
const l = t.codec.serialize(u), n = t.codec.serialize(t.default);
|
|
91
|
+
l === null || o(l, n) ? z(e, r, null, t.history) : z(e, r, l, t.history);
|
|
92
|
+
}
|
|
93
|
+
function k(e, r, t, u) {
|
|
94
|
+
let l = !1, n, c;
|
|
95
|
+
return N({
|
|
96
|
+
get: () => {
|
|
97
|
+
const a = O(e, r, t, u), s = u.codec.serialize(a);
|
|
98
|
+
return l && o(s, c) ? n : (l = !0, n = a, c = s, a);
|
|
99
|
+
},
|
|
100
|
+
set: (a) => y(r, t, u, a)
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
function W(e) {
|
|
104
|
+
const r = v(), t = S(), u = Object.keys(e), l = {};
|
|
105
|
+
for (const s of u)
|
|
106
|
+
l[s] = k(r, t, s, e[s]);
|
|
107
|
+
return { filters: A(l), patch: (s) => {
|
|
108
|
+
for (const i of Object.keys(s))
|
|
109
|
+
i in e && y(t, i, e[i], s[i]);
|
|
110
|
+
}, reset: () => {
|
|
111
|
+
for (const s of u)
|
|
112
|
+
y(t, s, e[s], e[s].default);
|
|
113
|
+
} };
|
|
114
|
+
}
|
|
115
|
+
function d(e) {
|
|
116
|
+
return Array.isArray(e) ? e[0] ?? "" : e;
|
|
117
|
+
}
|
|
118
|
+
function w(e) {
|
|
119
|
+
return { codec: {
|
|
120
|
+
serialize: (t) => t === null || t === "" ? null : t,
|
|
121
|
+
deserialize: (t) => d(t)
|
|
122
|
+
}, default: (e == null ? void 0 : e.default) ?? null, history: (e == null ? void 0 : e.history) ?? "replace" };
|
|
123
|
+
}
|
|
124
|
+
function F(e) {
|
|
125
|
+
return { codec: {
|
|
126
|
+
serialize: (t) => t === null ? null : String(t),
|
|
127
|
+
deserialize: (t) => {
|
|
128
|
+
const u = d(t), l = Number(u);
|
|
129
|
+
return u === "" || Number.isNaN(l) ? void 0 : l;
|
|
130
|
+
}
|
|
131
|
+
}, default: (e == null ? void 0 : e.default) ?? null, history: (e == null ? void 0 : e.history) ?? "replace" };
|
|
132
|
+
}
|
|
133
|
+
function M(e) {
|
|
134
|
+
return { codec: {
|
|
135
|
+
serialize: (t) => t === null ? null : t ? "true" : "false",
|
|
136
|
+
deserialize: (t) => {
|
|
137
|
+
const u = d(t);
|
|
138
|
+
if (u === "true")
|
|
139
|
+
return !0;
|
|
140
|
+
if (u === "false")
|
|
141
|
+
return !1;
|
|
142
|
+
}
|
|
143
|
+
}, default: (e == null ? void 0 : e.default) ?? null, history: (e == null ? void 0 : e.history) ?? "replace" };
|
|
144
|
+
}
|
|
145
|
+
function R(e) {
|
|
146
|
+
return { codec: {
|
|
147
|
+
serialize: (t) => t.length === 0 ? null : [...t],
|
|
148
|
+
deserialize: (t) => Array.isArray(t) ? [...t] : [t]
|
|
149
|
+
}, default: (e == null ? void 0 : e.default) ?? [], history: (e == null ? void 0 : e.history) ?? "replace" };
|
|
150
|
+
}
|
|
151
|
+
function E(e) {
|
|
152
|
+
return Object.entries(e).filter(([r]) => Number.isNaN(Number(r))).map(([, r]) => r);
|
|
153
|
+
}
|
|
154
|
+
function C(e, r) {
|
|
155
|
+
const t = Array.isArray(e) ? [...e] : E(e), u = new Set(t);
|
|
156
|
+
return { codec: {
|
|
157
|
+
serialize: (n) => n === null ? null : String(n),
|
|
158
|
+
deserialize: (n) => {
|
|
159
|
+
const c = d(n);
|
|
160
|
+
if (u.has(c))
|
|
161
|
+
return c;
|
|
162
|
+
const a = Number(c);
|
|
163
|
+
if (c !== "" && !Number.isNaN(a) && u.has(a))
|
|
164
|
+
return a;
|
|
165
|
+
}
|
|
166
|
+
}, default: (r == null ? void 0 : r.default) ?? null, history: (r == null ? void 0 : r.history) ?? "replace" };
|
|
167
|
+
}
|
|
168
|
+
function K(e, r) {
|
|
169
|
+
return {
|
|
170
|
+
codec: {
|
|
171
|
+
serialize: (u) => u === null ? null : e.serialize(u),
|
|
172
|
+
deserialize: (u) => e.deserialize(u)
|
|
173
|
+
},
|
|
174
|
+
default: (r == null ? void 0 : r.default) ?? null,
|
|
175
|
+
history: (r == null ? void 0 : r.history) ?? "replace"
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
const B = {
|
|
179
|
+
string: w,
|
|
180
|
+
number: F,
|
|
181
|
+
boolean: M,
|
|
182
|
+
stringArray: R,
|
|
183
|
+
enum: C,
|
|
184
|
+
custom: K
|
|
71
185
|
};
|
|
186
|
+
function D(e) {
|
|
187
|
+
return e;
|
|
188
|
+
}
|
|
72
189
|
export {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
B as useQuerySync
|
|
190
|
+
D as defineCodec,
|
|
191
|
+
B as param,
|
|
192
|
+
W as useQueryFilters
|
|
77
193
|
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Router } from 'vue-router';
|
|
2
|
+
type Serialized = string | string[];
|
|
3
|
+
export interface PendingRead {
|
|
4
|
+
pending: boolean;
|
|
5
|
+
value: Serialized | null;
|
|
6
|
+
}
|
|
7
|
+
export declare function readPending(router: Router, key: string): PendingRead;
|
|
8
|
+
export declare function scheduleWrite(router: Router, key: string, value: Serialized | null, history: 'push' | 'replace'): void;
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=batch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"batch.d.ts","sourceRoot":"","sources":["../../src/internal/batch.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAmC,MAAM,EAAE,MAAM,YAAY,CAAA;AAEzE,KAAK,UAAU,GAAG,MAAM,GAAG,MAAM,EAAE,CAAA;AA2BnC,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAA;IAChB,KAAK,EAAE,UAAU,GAAG,IAAI,CAAA;CACzB;AAGD,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,WAAW,CAMpE;AAGD,wBAAgB,aAAa,CAC3B,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,UAAU,GAAG,IAAI,EACxB,OAAO,EAAE,MAAM,GAAG,SAAS,GAC1B,IAAI,CAUN"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"equal.d.ts","sourceRoot":"","sources":["../../src/internal/equal.ts"],"names":[],"mappings":"AACA,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,GAAG,OAAO,CAWjG"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { RouteLocationNormalizedLoaded, Router } from 'vue-router';
|
|
2
|
+
import { Param } from '../types';
|
|
3
|
+
export declare function readField<Out>(route: RouteLocationNormalizedLoaded, router: Router, key: string, p: Param<Out>): Out;
|
|
4
|
+
export declare function writeField<Out>(router: Router, key: string, p: Param<Out>, value: Out): void;
|
|
5
|
+
//# sourceMappingURL=field.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"field.d.ts","sourceRoot":"","sources":["../../src/internal/field.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AACvE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,UAAU,CAAA;AAOrC,wBAAgB,SAAS,CAAC,GAAG,EAC3B,KAAK,EAAE,6BAA6B,EACpC,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,EACX,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,GACZ,GAAG,CAoBL;AAGD,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,GAAG,GAAG,IAAI,CAQ5F"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../../src/internal/normalize.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAG/C,wBAAgB,YAAY,CAAC,KAAK,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAQxF"}
|
package/dist/param.d.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Param, ParamOptions, QueryCodec } from './types';
|
|
2
|
+
declare function string(): Param<string | null>;
|
|
3
|
+
declare function string(options: ParamOptions<string> & {
|
|
4
|
+
default: string;
|
|
5
|
+
}): Param<string>;
|
|
6
|
+
declare function string(options?: ParamOptions<string>): Param<string | null>;
|
|
7
|
+
declare function number(): Param<number | null>;
|
|
8
|
+
declare function number(options: ParamOptions<number> & {
|
|
9
|
+
default: number;
|
|
10
|
+
}): Param<number>;
|
|
11
|
+
declare function number(options?: ParamOptions<number>): Param<number | null>;
|
|
12
|
+
declare function boolean(): Param<boolean | null>;
|
|
13
|
+
declare function boolean(options: ParamOptions<boolean> & {
|
|
14
|
+
default: boolean;
|
|
15
|
+
}): Param<boolean>;
|
|
16
|
+
declare function boolean(options?: ParamOptions<boolean>): Param<boolean | null>;
|
|
17
|
+
declare function stringArray(options?: ParamOptions<string[]>): Param<string[]>;
|
|
18
|
+
declare function enumParam<const T extends readonly string[]>(values: T, options: ParamOptions<T[number]> & {
|
|
19
|
+
default: T[number];
|
|
20
|
+
}): Param<T[number]>;
|
|
21
|
+
declare function enumParam<const T extends readonly string[]>(values: T, options?: ParamOptions<T[number]>): Param<T[number] | null>;
|
|
22
|
+
declare function enumParam<T extends Record<string, string | number>>(enumObj: T, options: ParamOptions<T[keyof T]> & {
|
|
23
|
+
default: T[keyof T];
|
|
24
|
+
}): Param<T[keyof T]>;
|
|
25
|
+
declare function enumParam<T extends Record<string, string | number>>(enumObj: T, options?: ParamOptions<T[keyof T]>): Param<T[keyof T] | null>;
|
|
26
|
+
declare function custom<T>(codec: QueryCodec<T>, options: ParamOptions<T> & {
|
|
27
|
+
default: T;
|
|
28
|
+
}): Param<T>;
|
|
29
|
+
declare function custom<T>(codec: QueryCodec<T>, options?: ParamOptions<T>): Param<T | null>;
|
|
30
|
+
export declare const param: {
|
|
31
|
+
string: typeof string;
|
|
32
|
+
number: typeof number;
|
|
33
|
+
boolean: typeof boolean;
|
|
34
|
+
stringArray: typeof stringArray;
|
|
35
|
+
enum: typeof enumParam;
|
|
36
|
+
custom: typeof custom;
|
|
37
|
+
};
|
|
38
|
+
export {};
|
|
39
|
+
//# sourceMappingURL=param.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"param.d.ts","sourceRoot":"","sources":["../src/param.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface QueryCodec<T> {
|
|
2
|
+
serialize(value: T): string | string[] | null;
|
|
3
|
+
deserialize(raw: string | string[]): T | undefined;
|
|
4
|
+
}
|
|
5
|
+
export type ParamOptions<T> = {
|
|
6
|
+
default?: T;
|
|
7
|
+
history?: 'push' | 'replace';
|
|
8
|
+
};
|
|
9
|
+
export interface Param<Out> {
|
|
10
|
+
codec: QueryCodec<Out>;
|
|
11
|
+
default: Out;
|
|
12
|
+
history: 'push' | 'replace';
|
|
13
|
+
}
|
|
14
|
+
export type FilterSchema = Record<string, Param<unknown>>;
|
|
15
|
+
export type InferFilters<S extends FilterSchema> = {
|
|
16
|
+
[K in keyof S]: S[K] extends Param<infer O> ? O : never;
|
|
17
|
+
};
|
|
18
|
+
export interface UseQueryFiltersReturn<S extends FilterSchema> {
|
|
19
|
+
filters: InferFilters<S>;
|
|
20
|
+
patch(partial: Partial<InferFilters<S>>): void;
|
|
21
|
+
reset(): void;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AACA,MAAM,WAAW,UAAU,CAAC,CAAC;IAE3B,SAAS,CAAC,KAAK,EAAE,CAAC,GAAG,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,CAAA;IAE7C,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,CAAA;CACnD;AAGD,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI;IAC5B,OAAO,CAAC,EAAE,CAAC,CAAA;IACX,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAC7B,CAAA;AAGD,MAAM,WAAW,KAAK,CAAC,GAAG;IACxB,KAAK,EAAE,UAAU,CAAC,GAAG,CAAC,CAAA;IACtB,OAAO,EAAE,GAAG,CAAA;IACZ,OAAO,EAAE,MAAM,GAAG,SAAS,CAAA;CAC5B;AAGD,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CAAA;AAGzD,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,YAAY,IAAI;KAChD,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK;CACxD,CAAA;AAGD,MAAM,WAAW,qBAAqB,CAAC,CAAC,SAAS,YAAY;IAC3D,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,CAAA;IACxB,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAA;IAC9C,KAAK,IAAI,IAAI,CAAA;CACd"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useQueryFilters.d.ts","sourceRoot":"","sources":["../src/useQueryFilters.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,YAAY,EAAuB,qBAAqB,EAAE,MAAM,SAAS,CAAA;AAiCvF,wBAAgB,eAAe,CAAC,CAAC,SAAS,YAAY,EAAE,MAAM,EAAE,CAAC,GAAG,qBAAqB,CAAC,CAAC,CAAC,CA0B3F"}
|
package/package.json
CHANGED
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vue-router-query-sync",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "
|
|
5
|
-
"
|
|
6
|
-
"module": "dist/index.mjs",
|
|
7
|
-
"types": "dist/index.d.ts",
|
|
3
|
+
"version": "2.0.0-alpha.2",
|
|
4
|
+
"description": "Reactive, typed view of Vue Router query params with codecs and defaults",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"module": "./dist/index.mjs",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
8
|
"scripts": {
|
|
9
|
-
"
|
|
9
|
+
"dev": "vite --config vite.dev.config.ts",
|
|
10
|
+
"build": "vite build",
|
|
11
|
+
"typecheck": "tsc --noEmit",
|
|
12
|
+
"lint": "eslint ."
|
|
10
13
|
},
|
|
11
14
|
"exports": {
|
|
12
15
|
".": {
|
|
13
16
|
"types": "./dist/index.d.ts",
|
|
14
|
-
"import": "./dist/index.mjs"
|
|
15
|
-
"require": "./dist/index.js"
|
|
17
|
+
"import": "./dist/index.mjs"
|
|
16
18
|
}
|
|
17
19
|
},
|
|
18
20
|
"files": [
|
|
@@ -35,7 +37,7 @@
|
|
|
35
37
|
"license": "MIT",
|
|
36
38
|
"repository": {
|
|
37
39
|
"type": "git",
|
|
38
|
-
"url": "https://github.com/Ivan-Chikachev/vue-router-query-sync"
|
|
40
|
+
"url": "git+https://github.com/Ivan-Chikachev/vue-router-query-sync.git"
|
|
39
41
|
},
|
|
40
42
|
"peerDependencies": {
|
|
41
43
|
"vue": "^3.3.13",
|
|
@@ -43,16 +45,18 @@
|
|
|
43
45
|
},
|
|
44
46
|
"devDependencies": {
|
|
45
47
|
"vite-plugin-dts": "^4.5.4",
|
|
48
|
+
"@eslint/js": "^9.36.0",
|
|
46
49
|
"@types/node": "^20.1.0",
|
|
47
|
-
"@typescript-eslint/eslint-plugin": "^8.4.0",
|
|
48
50
|
"@vitejs/plugin-vue": "^5.2.3",
|
|
49
|
-
"
|
|
50
|
-
"eslint": "^8.57.0",
|
|
51
|
+
"eslint": "^9.36.0",
|
|
51
52
|
"eslint-config-prettier": "^9.1.0",
|
|
52
53
|
"eslint-plugin-import": "^2.30.0",
|
|
53
54
|
"eslint-plugin-prettier": "^5.2.1",
|
|
54
|
-
"eslint-plugin-vue": "^9.
|
|
55
|
+
"eslint-plugin-vue": "^9.33.0",
|
|
56
|
+
"globals": "^15.15.0",
|
|
57
|
+
"prettier": "^3.6.2",
|
|
55
58
|
"typescript": "^5.2.0",
|
|
59
|
+
"typescript-eslint": "^8.45.0",
|
|
56
60
|
"vite": "^6.3.6"
|
|
57
61
|
}
|
|
58
62
|
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { QuerySyncOptions } from '../types';
|
|
2
|
-
/**
|
|
3
|
-
* Synchronizes a store value with a query parameter in the URL.
|
|
4
|
-
*
|
|
5
|
-
* @param key - The name of the query parameter, e.g. "tab".
|
|
6
|
-
* @param get - A function that returns the current value from the store.
|
|
7
|
-
* @param set - A function that updates the value in the store.
|
|
8
|
-
* @param options.deps - A list of reactive dependencies that must change before synchronization occurs.
|
|
9
|
-
* @param options.context - A unique context identifier, required when multiple instances use the same query key on the same page.
|
|
10
|
-
*
|
|
11
|
-
* ⚠️ Important:
|
|
12
|
-
* If multiple components on the same page use the same query key,
|
|
13
|
-
* you must provide a unique `context` to prevent conflicts.
|
|
14
|
-
* Alternatively, always use unique query keys (for example, instead of "page", use "usersPage").
|
|
15
|
-
*/
|
|
16
|
-
export declare function useQuerySync<T extends string | number>(key: string, get: () => T | null, set: (val: T) => void, options?: QuerySyncOptions): void;
|
|
17
|
-
//# sourceMappingURL=useQuerySync.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useQuerySync.d.ts","sourceRoot":"","sources":["../../src/composables/useQuerySync.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAgB1C;;;;;;;;;;;;;GAaG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EACpD,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,CAAC,GAAG,IAAI,EACnB,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,IAAI,EACrB,OAAO,GAAE,gBAAqB,QAiE/B"}
|
package/dist/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
(function(u,n){typeof exports=="object"&&typeof module<"u"?n(exports,require("vue")):typeof define=="function"&&define.amd?define(["exports","vue"],n):(u=typeof globalThis<"u"?globalThis:u||self,n(u.VueRouterQuerySync={},u.Vue))})(this,(function(u,n){"use strict";let p=null;function m(e){p=e}function Q(){if(!p)throw new Error("[vue-router-query-sync] Router instance not set. Call setRouter(router) before using composables.");return p}let c={};const f=new Set;let R=!1;function l(e,t){const a=Q();t===null?e in c||f.add(e):(c[e]=t,f.delete(e)),R||(R=!0,queueMicrotask(()=>{const d={...a.currentRoute.value.query};f.forEach(i=>{delete d[i]});const q={...d,...c};a.replace({query:q}),c={},f.clear(),R=!1}))}function g(e){if(e==="")return e;const t=Number(e);return isNaN(t)?e:t}function T(e,t,a,d={}){const i=Q().currentRoute,{deps:v=[],context:b}=d,r=b?`${b}_${e}`:e,S=(o,y=!1)=>{if(typeof o=="string"){const s=g(o);if(y||s!==t()){a(s);const h=t();h!==s&&h!==null&&l(r,h)}}else if(o===void 0){const s=t();s!==null&&l(r,s)}},M=o=>{const y=i.value.query[r];if(o===null)y!==void 0&&l(r,null);else{const s=String(o);y!==s&&l(r,o)}};n.onBeforeMount(()=>{v.length>0?n.watch(v,()=>S(i.value.query[r])):S(i.value.query[r])}),n.watch(t,M),n.watch(()=>i.value.query[r],o=>S(o)),n.onBeforeUnmount(()=>{l(r,null)})}const w={install(e,t){m(t.router)}};u.default=w,u.getRouter=Q,u.setRouter=m,u.useQuerySync=T,Object.defineProperties(u,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})}));
|
package/dist/router.d.ts
DELETED
package/dist/router.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAIxC,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,QAEvC;AAED,wBAAgB,SAAS,IAAI,MAAM,CAOlC"}
|
package/dist/types/index.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAA;AAEzB,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC,EAAE,CAAA;IACrB,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB,CAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"replaceRouterQueue.d.ts","sourceRoot":"","sources":["../../src/utils/replaceRouterQueue.ts"],"names":[],"mappings":"AAMA,MAAM,CAAC,OAAO,UAAU,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,QAiCpF"}
|