@tanstack/router-core 0.0.1-beta.19 → 0.0.1-beta.191

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.
Files changed (82) hide show
  1. package/LICENSE +21 -0
  2. package/build/cjs/defer.js +39 -0
  3. package/build/cjs/defer.js.map +1 -0
  4. package/build/cjs/fileRoute.js +29 -0
  5. package/build/cjs/fileRoute.js.map +1 -0
  6. package/build/cjs/history.js +228 -0
  7. package/build/cjs/history.js.map +1 -0
  8. package/build/cjs/index.js +86 -0
  9. package/build/cjs/{packages/router-core/src/index.js.map → index.js.map} +1 -1
  10. package/build/cjs/{packages/router-core/src/path.js → path.js} +45 -56
  11. package/build/cjs/path.js.map +1 -0
  12. package/build/cjs/{packages/router-core/src/qss.js → qss.js} +10 -16
  13. package/build/cjs/qss.js.map +1 -0
  14. package/build/cjs/route.js +114 -0
  15. package/build/cjs/route.js.map +1 -0
  16. package/build/cjs/router.js +1267 -0
  17. package/build/cjs/router.js.map +1 -0
  18. package/build/cjs/scroll-restoration.js +139 -0
  19. package/build/cjs/scroll-restoration.js.map +1 -0
  20. package/build/cjs/{packages/router-core/src/searchParams.js → searchParams.js} +32 -19
  21. package/build/cjs/searchParams.js.map +1 -0
  22. package/build/cjs/{packages/router-core/src/utils.js → utils.js} +69 -64
  23. package/build/cjs/utils.js.map +1 -0
  24. package/build/esm/index.js +1746 -2121
  25. package/build/esm/index.js.map +1 -1
  26. package/build/stats-html.html +59 -49
  27. package/build/stats-react.json +197 -211
  28. package/build/types/defer.d.ts +19 -0
  29. package/build/types/fileRoute.d.ts +35 -0
  30. package/build/types/history.d.ts +36 -0
  31. package/build/types/index.d.ts +13 -609
  32. package/build/types/link.d.ts +96 -0
  33. package/build/types/path.d.ts +16 -0
  34. package/build/types/qss.d.ts +2 -0
  35. package/build/types/route.d.ts +251 -0
  36. package/build/types/routeInfo.d.ts +22 -0
  37. package/build/types/router.d.ts +260 -0
  38. package/build/types/scroll-restoration.d.ts +6 -0
  39. package/build/types/searchParams.d.ts +5 -0
  40. package/build/types/utils.d.ts +44 -0
  41. package/build/umd/index.development.js +1978 -2243
  42. package/build/umd/index.development.js.map +1 -1
  43. package/build/umd/index.production.js +13 -2
  44. package/build/umd/index.production.js.map +1 -1
  45. package/package.json +11 -7
  46. package/src/defer.ts +55 -0
  47. package/src/fileRoute.ts +161 -0
  48. package/src/history.ts +300 -0
  49. package/src/index.ts +5 -10
  50. package/src/link.ts +136 -125
  51. package/src/path.ts +37 -17
  52. package/src/qss.ts +1 -2
  53. package/src/route.ts +948 -218
  54. package/src/routeInfo.ts +45 -211
  55. package/src/router.ts +1778 -1075
  56. package/src/scroll-restoration.ts +179 -0
  57. package/src/searchParams.ts +31 -9
  58. package/src/utils.ts +84 -49
  59. package/build/cjs/_virtual/_rollupPluginBabelHelpers.js +0 -33
  60. package/build/cjs/_virtual/_rollupPluginBabelHelpers.js.map +0 -1
  61. package/build/cjs/node_modules/@babel/runtime/helpers/esm/extends.js +0 -33
  62. package/build/cjs/node_modules/@babel/runtime/helpers/esm/extends.js.map +0 -1
  63. package/build/cjs/node_modules/history/index.js +0 -815
  64. package/build/cjs/node_modules/history/index.js.map +0 -1
  65. package/build/cjs/node_modules/tiny-invariant/dist/esm/tiny-invariant.js +0 -30
  66. package/build/cjs/node_modules/tiny-invariant/dist/esm/tiny-invariant.js.map +0 -1
  67. package/build/cjs/packages/router-core/src/index.js +0 -58
  68. package/build/cjs/packages/router-core/src/path.js.map +0 -1
  69. package/build/cjs/packages/router-core/src/qss.js.map +0 -1
  70. package/build/cjs/packages/router-core/src/route.js +0 -147
  71. package/build/cjs/packages/router-core/src/route.js.map +0 -1
  72. package/build/cjs/packages/router-core/src/routeConfig.js +0 -69
  73. package/build/cjs/packages/router-core/src/routeConfig.js.map +0 -1
  74. package/build/cjs/packages/router-core/src/routeMatch.js +0 -220
  75. package/build/cjs/packages/router-core/src/routeMatch.js.map +0 -1
  76. package/build/cjs/packages/router-core/src/router.js +0 -870
  77. package/build/cjs/packages/router-core/src/router.js.map +0 -1
  78. package/build/cjs/packages/router-core/src/searchParams.js.map +0 -1
  79. package/build/cjs/packages/router-core/src/utils.js.map +0 -1
  80. package/src/frameworks.ts +0 -11
  81. package/src/routeConfig.ts +0 -511
  82. package/src/routeMatch.ts +0 -312
package/src/link.ts CHANGED
@@ -1,11 +1,15 @@
1
- import { AnyPathParams } from './routeConfig'
1
+ import { Trim } from './fileRoute'
2
+ import { AnyRoute } from './route'
3
+ import { AllParams, RouteByPath, RouteIds, RoutePaths } from './routeInfo'
4
+ import { LocationState, ParsedLocation } from './router'
2
5
  import {
3
- AnyAllRouteInfo,
4
- DefaultAllRouteInfo,
5
- RouteInfoByPath,
6
- } from './routeInfo'
7
- import { Location, LocationState } from './router'
8
- import { Expand, NoInfer, PickAsRequired, PickRequired, Updater } from './utils'
6
+ Expand,
7
+ NoInfer,
8
+ NonNullableUpdater,
9
+ PickRequired,
10
+ UnionToIntersection,
11
+ Updater,
12
+ } from './utils'
9
13
 
10
14
  export type LinkInfo =
11
15
  | {
@@ -14,20 +18,17 @@ export type LinkInfo =
14
18
  }
15
19
  | {
16
20
  type: 'internal'
17
- next: Location
21
+ next: ParsedLocation
18
22
  handleFocus: (e: any) => void
19
23
  handleClick: (e: any) => void
20
24
  handleEnter: (e: any) => void
21
25
  handleLeave: (e: any) => void
26
+ handleTouchStart: (e: any) => void
22
27
  isActive: boolean
23
28
  disabled?: boolean
24
29
  }
25
30
 
26
- type StartsWith<A, B> = A extends `${B extends string ? B : never}${infer _}`
27
- ? true
28
- : false
29
-
30
- type CleanPath<T extends string> = T extends `${infer L}//${infer R}`
31
+ export type CleanPath<T extends string> = T extends `${infer L}//${infer R}`
31
32
  ? CleanPath<`${CleanPath<L>}/${CleanPath<R>}`>
32
33
  : T extends `${infer L}//`
33
34
  ? `${CleanPath<L>}/`
@@ -57,20 +58,20 @@ export type Split<S, TIncludeTrailingSlash = true> = S extends unknown
57
58
  : never
58
59
  : never
59
60
 
60
- export type ParsePathParams<T extends string> = Split<T>[number] extends infer U
61
- ? U extends `:${infer V}`
62
- ? V
63
- : never
64
- : never
61
+ export type ParsePathParams<T extends string> = keyof {
62
+ [K in Trim<Split<T>[number], '_'> as K extends `$${infer L}` ? L : never]: K
63
+ }
65
64
 
66
- type Join<T> = T extends []
65
+ export type Join<T, Delimiter extends string = '/'> = T extends []
67
66
  ? ''
68
67
  : T extends [infer L extends string]
69
68
  ? L
70
69
  : T extends [infer L extends string, ...infer Tail extends [...string[]]]
71
- ? CleanPath<`${L}/${Join<Tail>}`>
70
+ ? CleanPath<`${L}${Delimiter}${Join<Tail>}`>
72
71
  : never
73
72
 
73
+ export type Last<T extends any[]> = T extends [...infer _, infer L] ? L : never
74
+
74
75
  export type RelativeToPathAutoComplete<
75
76
  AllPaths extends string,
76
77
  TFrom extends string,
@@ -106,128 +107,157 @@ export type RelativeToPathAutoComplete<
106
107
  ]
107
108
  ? `${TTo}${Join<RestPath>}`
108
109
  : never
109
- : './' | '../' | AllPaths
110
+ :
111
+ | (TFrom extends `/`
112
+ ? never
113
+ : SplitPaths extends [...Split<TFrom, false>, ...infer RestPath]
114
+ ? Join<RestPath> extends { length: 0 }
115
+ ? never
116
+ : './'
117
+ : never)
118
+ | (TFrom extends `/` ? never : '../')
119
+ | AllPaths
110
120
 
111
- export type NavigateOptionsAbsolute<
112
- TAllRouteInfo extends AnyAllRouteInfo = DefaultAllRouteInfo,
113
- TFrom extends ValidFromPath<TAllRouteInfo> = '/',
114
- TTo extends string = '.',
115
- > = ToOptions<TAllRouteInfo, TFrom, TTo> & {
116
- // Whether to replace the current history stack instead of pushing a new one
121
+ export type NavigateOptions<
122
+ TRouteTree extends AnyRoute = AnyRoute,
123
+ TFrom extends RoutePaths<TRouteTree> = '/',
124
+ TTo extends string = '',
125
+ TMaskFrom extends RoutePaths<TRouteTree> = TFrom,
126
+ TMaskTo extends string = '',
127
+ > = ToOptions<TRouteTree, TFrom, TTo, TMaskFrom, TMaskTo> & {
128
+ // `replace` is a boolean that determines whether the navigation should replace the current history entry or push a new one.
117
129
  replace?: boolean
130
+ resetScroll?: boolean
118
131
  }
119
132
 
120
133
  export type ToOptions<
121
- TAllRouteInfo extends AnyAllRouteInfo = DefaultAllRouteInfo,
122
- TFrom extends ValidFromPath<TAllRouteInfo> = '/',
123
- TTo extends string = '.',
124
- TResolvedTo = ResolveRelativePath<TFrom, NoInfer<TTo>>,
134
+ TRouteTree extends AnyRoute = AnyRoute,
135
+ TFrom extends RoutePaths<TRouteTree> = '/',
136
+ TTo extends string = '',
137
+ TMaskFrom extends RoutePaths<TRouteTree> = '/',
138
+ TMaskTo extends string = '',
139
+ > = ToSubOptions<TRouteTree, TFrom, TTo> & {
140
+ mask?: ToMaskOptions<TRouteTree, TMaskFrom, TMaskTo>
141
+ }
142
+
143
+ export type ToMaskOptions<
144
+ TRouteTree extends AnyRoute = AnyRoute,
145
+ TMaskFrom extends RoutePaths<TRouteTree> = '/',
146
+ TMaskTo extends string = '',
147
+ > = ToSubOptions<TRouteTree, TMaskFrom, TMaskTo> & {
148
+ unmaskOnReload?: boolean
149
+ }
150
+
151
+ export type ToSubOptions<
152
+ TRouteTree extends AnyRoute = AnyRoute,
153
+ TFrom extends RoutePaths<TRouteTree> = '/',
154
+ TTo extends string = '',
155
+ TResolved = ResolveRelativePath<TFrom, NoInfer<TTo>>,
125
156
  > = {
126
- to?: ToPathOption<TAllRouteInfo, TFrom, TTo>
157
+ to?: ToPathOption<TRouteTree, TFrom, TTo>
127
158
  // The new has string or a function to update it
128
- hash?: Updater<string>
159
+ hash?: true | Updater<string>
129
160
  // State to pass to the history stack
130
- state?: LocationState
161
+ state?: true | NonNullableUpdater<LocationState>
131
162
  // The source route path. This is automatically set when using route-level APIs, but for type-safe relative routing on the router itself, this is required
132
163
  from?: TFrom
133
164
  // // When using relative route paths, this option forces resolution from the current path, instead of the route API's path or `from` path
134
165
  // fromCurrent?: boolean
135
- } & CheckPath<TAllRouteInfo, NoInfer<TResolvedTo>, {}> &
136
- SearchParamOptions<TAllRouteInfo, TFrom, TResolvedTo> &
137
- PathParamOptions<TAllRouteInfo, TFrom, TResolvedTo>
166
+ } & CheckPath<TRouteTree, NoInfer<TResolved>, {}> &
167
+ SearchParamOptions<TRouteTree, TFrom, TResolved> &
168
+ PathParamOptions<TRouteTree, TFrom, TResolved>
138
169
 
139
- type SearchParamOptions<
140
- TAllRouteInfo extends AnyAllRouteInfo,
170
+ export type SearchParamOptions<
171
+ TRouteTree extends AnyRoute,
141
172
  TFrom,
142
173
  TTo,
143
- TFromSchema = RouteInfoByPath<TAllRouteInfo, TFrom>['fullSearchSchema'],
144
- TToSchema = RouteInfoByPath<TAllRouteInfo, TTo>['fullSearchSchema'],
145
- > = StartsWith<TFrom, TTo> extends true // If the next route search extend or cover the from route, params will be optional
146
- ? {
147
- search?: SearchReducer<TFromSchema, TToSchema>
148
- }
149
- : // Optional search params? Allow it
150
- keyof PickRequired<TToSchema> extends never
174
+ TFromSearchEnsured = Expand<
175
+ UnionToIntersection<
176
+ PickRequired<RouteByPath<TRouteTree, TFrom>['types']['fullSearchSchema']>
177
+ >
178
+ >,
179
+ TFromSearchOptional = Omit<AllParams<TRouteTree>, keyof TFromSearchEnsured>,
180
+ TFromSearch = Expand<TFromSearchEnsured & TFromSearchOptional>,
181
+ TToSearch = Expand<RouteByPath<TRouteTree, TTo>['types']['fullSearchSchema']>,
182
+ > = keyof PickRequired<TToSearch> extends never
151
183
  ? {
152
- search?: SearchReducer<TFromSchema, TToSchema>
184
+ search?: true | SearchReducer<TFromSearch, TToSearch>
153
185
  }
154
186
  : {
155
- // Must have required search params, enforce it
156
- search: SearchReducer<TFromSchema, TToSchema>
187
+ search: TFromSearchEnsured extends PickRequired<TToSearch>
188
+ ? true | SearchReducer<TFromSearch, TToSearch>
189
+ : SearchReducer<TFromSearch, TToSearch>
157
190
  }
158
191
 
159
- type SearchReducer<TFrom, TTo> =
160
- | { [TKey in keyof TTo]: TTo[TKey] }
161
- | ((current: TFrom) => TTo)
192
+ type SearchReducer<TFrom, TTo> = TTo | ((current: TFrom) => TTo)
162
193
 
163
- type PathParamOptions<
164
- TAllRouteInfo extends AnyAllRouteInfo,
194
+ export type PathParamOptions<
195
+ TRouteTree extends AnyRoute,
165
196
  TFrom,
166
197
  TTo,
167
- TFromParams = RouteInfoByPath<TAllRouteInfo, TFrom>['allParams'],
168
- TToParams = RouteInfoByPath<TAllRouteInfo, TTo>['allParams'],
169
- > =
170
- // If the next routes params extend or cover the from route, params will be optional
171
- StartsWith<TFrom, TTo> extends true
172
- ? {
173
- params?: ParamsReducer<TFromParams, TToParams>
174
- }
175
- : // If the next route doesn't have params, warn if any have been passed
176
- AnyPathParams extends TToParams
177
- ? {
178
- params?: ParamsReducer<TFromParams, Record<string, never>>
179
- }
180
- : // If the next route has params, enforce them
181
- {
182
- params: ParamsReducer<TFromParams, TToParams>
183
- }
198
+ TFromParamsEnsured = Expand<
199
+ UnionToIntersection<
200
+ PickRequired<RouteByPath<TRouteTree, TFrom>['types']['allParams']>
201
+ >
202
+ >,
203
+ TFromParamsOptional = Omit<AllParams<TRouteTree>, keyof TFromParamsEnsured>,
204
+ TFromParams = Expand<TFromParamsOptional & TFromParamsEnsured>,
205
+ TToParams = Expand<RouteByPath<TRouteTree, TTo>['types']['allParams']>,
206
+ > = keyof PickRequired<TToParams> extends never
207
+ ? {
208
+ params?: true | ParamsReducer<TFromParams, TToParams>
209
+ }
210
+ : {
211
+ params: TFromParamsEnsured extends PickRequired<TToParams>
212
+ ? true | ParamsReducer<TFromParams, TToParams>
213
+ : ParamsReducer<TFromParams, TToParams>
214
+ }
184
215
 
185
216
  type ParamsReducer<TFrom, TTo> = TTo | ((current: TFrom) => TTo)
186
217
 
187
218
  export type ToPathOption<
188
- TAllRouteInfo extends AnyAllRouteInfo = DefaultAllRouteInfo,
189
- TFrom extends ValidFromPath<TAllRouteInfo> = '/',
190
- TTo extends string = '.',
219
+ TRouteTree extends AnyRoute = AnyRoute,
220
+ TFrom extends RoutePaths<TRouteTree> = '/',
221
+ TTo extends string = '',
191
222
  > =
192
223
  | TTo
193
224
  | RelativeToPathAutoComplete<
194
- TAllRouteInfo['routePaths'],
225
+ RoutePaths<TRouteTree>,
195
226
  NoInfer<TFrom> extends string ? NoInfer<TFrom> : '',
196
227
  NoInfer<TTo> & string
197
228
  >
198
229
 
199
230
  export type ToIdOption<
200
- TAllRouteInfo extends AnyAllRouteInfo = DefaultAllRouteInfo,
201
- TFrom extends ValidFromPath<TAllRouteInfo> = '/',
202
- TTo extends string = '.',
231
+ TRouteTree extends AnyRoute = AnyRoute,
232
+ TFrom extends RoutePaths<TRouteTree> = '/',
233
+ TTo extends string = '',
203
234
  > =
204
235
  | TTo
205
236
  | RelativeToPathAutoComplete<
206
- TAllRouteInfo['routeIds'],
237
+ RouteIds<TRouteTree>,
207
238
  NoInfer<TFrom> extends string ? NoInfer<TFrom> : '',
208
239
  NoInfer<TTo> & string
209
240
  >
210
241
 
211
- interface ActiveOptions {
242
+ export interface ActiveOptions {
212
243
  exact?: boolean
213
244
  includeHash?: boolean
245
+ includeSearch?: boolean
214
246
  }
215
247
 
216
248
  export type LinkOptions<
217
- TAllRouteInfo extends AnyAllRouteInfo = DefaultAllRouteInfo,
218
- TFrom extends ValidFromPath<TAllRouteInfo> = '/',
219
- TTo extends string = '.',
220
- > = NavigateOptionsAbsolute<TAllRouteInfo, TFrom, TTo> & {
249
+ TRouteTree extends AnyRoute = AnyRoute,
250
+ TFrom extends RoutePaths<TRouteTree> = '/',
251
+ TTo extends string = '',
252
+ TMaskFrom extends RoutePaths<TRouteTree> = TFrom,
253
+ TMaskTo extends string = '',
254
+ > = NavigateOptions<TRouteTree, TFrom, TTo, TMaskFrom, TMaskTo> & {
221
255
  // The standard anchor tag target attribute
222
256
  target?: HTMLAnchorElement['target']
223
257
  // Defaults to `{ exact: false, includeHash: false }`
224
258
  activeOptions?: ActiveOptions
225
259
  // If set, will preload the linked route on hover and cache it for this many milliseconds in hopes that the user will eventually navigate there.
226
260
  preload?: false | 'intent'
227
- // When preloaded, the preloaded result will be considered "fresh" for this duration in milliseconds
228
- preloadMaxAge?: number
229
- // When preloaded and subsequently inactive, the preloaded result will remain in memory for this duration in milliseconds
230
- preloadGcMaxAge?: number
231
261
  // Delay intent preloading by this many milliseconds. If the intent exits before this delay, the preload will be cancelled.
232
262
  preloadDelay?: number
233
263
  // If true, will render the link without the href attribute
@@ -235,58 +265,47 @@ export type LinkOptions<
235
265
  }
236
266
 
237
267
  export type CheckRelativePath<
238
- TAllRouteInfo extends AnyAllRouteInfo,
268
+ TRouteTree extends AnyRoute,
239
269
  TFrom,
240
270
  TTo,
241
271
  > = TTo extends string
242
272
  ? TFrom extends string
243
- ? ResolveRelativePath<TFrom, TTo> extends TAllRouteInfo['routePaths']
273
+ ? ResolveRelativePath<TFrom, TTo> extends RoutePaths<TRouteTree>
244
274
  ? {}
245
275
  : {
246
276
  Error: `${TFrom} + ${TTo} resolves to ${ResolveRelativePath<
247
277
  TFrom,
248
278
  TTo
249
279
  >}, which is not a valid route path.`
250
- 'Valid Route Paths': TAllRouteInfo['routePaths']
280
+ 'Valid Route Paths': RoutePaths<TRouteTree>
251
281
  }
252
282
  : {}
253
283
  : {}
254
284
 
255
- export type CheckPath<
256
- TAllRouteInfo extends AnyAllRouteInfo,
285
+ export type CheckPath<TRouteTree extends AnyRoute, TPath, TPass> = Exclude<
257
286
  TPath,
258
- TPass,
259
- > = Exclude<TPath, TAllRouteInfo['routePaths']> extends never
287
+ RoutePaths<TRouteTree>
288
+ > extends never
260
289
  ? TPass
261
- : CheckPathError<TAllRouteInfo, Exclude<TPath, TAllRouteInfo['routePaths']>>
290
+ : CheckPathError<TRouteTree, Exclude<TPath, RoutePaths<TRouteTree>>>
262
291
 
263
- export type CheckPathError<
264
- TAllRouteInfo extends AnyAllRouteInfo,
265
- TInvalids,
266
- > = Expand<{
267
- Error: `${TInvalids extends string
268
- ? TInvalids
269
- : never} is not a valid route path.`
270
- 'Valid Route Paths': TAllRouteInfo['routePaths']
271
- }>
292
+ export type CheckPathError<TRouteTree extends AnyRoute, TInvalids> = {
293
+ to: RoutePaths<TRouteTree>
294
+ }
272
295
 
273
- export type CheckId<
274
- TAllRouteInfo extends AnyAllRouteInfo,
296
+ export type CheckId<TRouteTree extends AnyRoute, TPath, TPass> = Exclude<
275
297
  TPath,
276
- TPass,
277
- > = Exclude<TPath, TAllRouteInfo['routeIds']> extends never
298
+ RouteIds<TRouteTree>
299
+ > extends never
278
300
  ? TPass
279
- : CheckIdError<TAllRouteInfo, Exclude<TPath, TAllRouteInfo['routeIds']>>
301
+ : CheckIdError<TRouteTree, Exclude<TPath, RouteIds<TRouteTree>>>
280
302
 
281
- export type CheckIdError<
282
- TAllRouteInfo extends AnyAllRouteInfo,
283
- TInvalids,
284
- > = Expand<{
303
+ export type CheckIdError<TRouteTree extends AnyRoute, TInvalids> = {
285
304
  Error: `${TInvalids extends string
286
305
  ? TInvalids
287
306
  : never} is not a valid route ID.`
288
- 'Valid Route IDs': TAllRouteInfo['routeIds']
289
- }>
307
+ 'Valid Route IDs': RouteIds<TRouteTree>
308
+ }
290
309
 
291
310
  export type ResolveRelativePath<TFrom, TTo = '.'> = TFrom extends string
292
311
  ? TTo extends string
@@ -311,11 +330,3 @@ export type ResolveRelativePath<TFrom, TTo = '.'> = TFrom extends string
311
330
  : CleanPath<Join<['/', ...Split<TFrom>, ...Split<TTo>]>>
312
331
  : never
313
332
  : never
314
-
315
- export type ValidFromPath<
316
- TAllRouteInfo extends AnyAllRouteInfo = DefaultAllRouteInfo,
317
- > =
318
- | undefined
319
- | (string extends TAllRouteInfo['routePaths']
320
- ? string
321
- : TAllRouteInfo['routePaths'])
package/src/path.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { AnyPathParams } from './routeConfig'
1
+ import { AnyPathParams } from './route'
2
2
  import { MatchLocation } from './router'
3
3
  import { last } from './utils'
4
4
 
@@ -90,14 +90,14 @@ export function parsePathname(pathname?: string): Segment[] {
90
90
 
91
91
  segments.push(
92
92
  ...split.map((part): Segment => {
93
- if (part.startsWith('*')) {
93
+ if (part === '$' || part === '*') {
94
94
  return {
95
95
  type: 'wildcard',
96
96
  value: part,
97
97
  }
98
98
  }
99
99
 
100
- if (part.charAt(0) === ':') {
100
+ if (part.charAt(0) === '$') {
101
101
  return {
102
102
  type: 'param',
103
103
  value: part,
@@ -125,14 +125,16 @@ export function parsePathname(pathname?: string): Segment[] {
125
125
  export function interpolatePath(
126
126
  path: string | undefined,
127
127
  params: any,
128
- leaveWildcard?: boolean,
128
+ leaveWildcards: boolean = false,
129
129
  ) {
130
130
  const interpolatedPathSegments = parsePathname(path)
131
131
 
132
132
  return joinPaths(
133
133
  interpolatedPathSegments.map((segment) => {
134
- if (segment.value === '*' && !leaveWildcard) {
135
- return ''
134
+ if (segment.type === 'wildcard') {
135
+ const value = params[segment.value]
136
+ if (leaveWildcards) return `${segment.value}${value ?? ''}`
137
+ return value
136
138
  }
137
139
 
138
140
  if (segment.type === 'param') {
@@ -145,29 +147,46 @@ export function interpolatePath(
145
147
  }
146
148
 
147
149
  export function matchPathname(
150
+ basepath: string,
148
151
  currentPathname: string,
149
152
  matchLocation: Pick<MatchLocation, 'to' | 'fuzzy' | 'caseSensitive'>,
150
153
  ): AnyPathParams | undefined {
151
- const pathParams = matchByPath(currentPathname, matchLocation)
152
- // const searchMatched = matchBySearch(currentLocation.search, matchLocation)
154
+ const pathParams = matchByPath(basepath, currentPathname, matchLocation)
155
+ // const searchMatched = matchBySearch(location.search, matchLocation)
153
156
 
154
157
  if (matchLocation.to && !pathParams) {
155
158
  return
156
159
  }
157
160
 
158
- // if (matchLocation.search && !searchMatched) {
159
- // return
160
- // }
161
-
162
161
  return pathParams ?? {}
163
162
  }
164
163
 
165
164
  export function matchByPath(
165
+ basepath: string,
166
166
  from: string,
167
167
  matchLocation: Pick<MatchLocation, 'to' | 'caseSensitive' | 'fuzzy'>,
168
168
  ): Record<string, string> | undefined {
169
+ // Remove the base path from the pathname
170
+ from = basepath != '/' ? from.substring(basepath.length) : from
171
+ // Default to to $ (wildcard)
172
+ const to = `${matchLocation.to ?? '$'}`
173
+ // Parse the from and to
169
174
  const baseSegments = parsePathname(from)
170
- const routeSegments = parsePathname(`${matchLocation.to ?? '*'}`)
175
+ const routeSegments = parsePathname(to)
176
+
177
+ if (!from.startsWith('/')) {
178
+ baseSegments.unshift({
179
+ type: 'pathname',
180
+ value: '/',
181
+ })
182
+ }
183
+
184
+ if (!to.startsWith('/')) {
185
+ routeSegments.unshift({
186
+ type: 'pathname',
187
+ value: '/',
188
+ })
189
+ }
171
190
 
172
191
  const params: Record<string, string> = {}
173
192
 
@@ -180,8 +199,8 @@ export function matchByPath(
180
199
  const baseSegment = baseSegments[i]
181
200
  const routeSegment = routeSegments[i]
182
201
 
183
- const isLastRouteSegment = i === routeSegments.length - 1
184
- const isLastBaseSegment = i === baseSegments.length - 1
202
+ const isLastBaseSegment = i >= baseSegments.length - 1
203
+ const isLastRouteSegment = i >= routeSegments.length - 1
185
204
 
186
205
  if (routeSegment) {
187
206
  if (routeSegment.type === 'wildcard') {
@@ -219,16 +238,17 @@ export function matchByPath(
219
238
  if (baseSegment?.value === '/') {
220
239
  return false
221
240
  }
222
- if (!baseSegment.value.startsWith(':')) {
241
+ if (baseSegment.value.charAt(0) !== '$') {
223
242
  params[routeSegment.value.substring(1)] = baseSegment.value
224
243
  }
225
244
  }
226
245
  }
227
246
 
228
- if (isLastRouteSegment && !isLastBaseSegment) {
247
+ if (!isLastBaseSegment && isLastRouteSegment) {
229
248
  return !!matchLocation.fuzzy
230
249
  }
231
250
  }
251
+
232
252
  return true
233
253
  })()
234
254
 
package/src/qss.ts CHANGED
@@ -30,8 +30,7 @@ function toValue(mix) {
30
30
  var str = decodeURIComponent(mix)
31
31
  if (str === 'false') return false
32
32
  if (str === 'true') return true
33
- if (str.charAt(0) === '0') return str
34
- return +str * 0 === 0 ? +str : str
33
+ return +str * 0 === 0 && +str + '' === str ? +str : str
35
34
  }
36
35
 
37
36
  export function decode(str) {