navgo 4.0.3 → 5.0.1

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/index.d.ts CHANGED
@@ -86,6 +86,8 @@ export interface Options {
86
86
  * scrolling lands on the correct elements.
87
87
  */
88
88
  tick?: () => void | Promise<void>
89
+ /** When `false`, do not scroll to top on non-hash navigations. Default true. */
90
+ scroll_to_top?: boolean
89
91
  /** Global hook fired whenever the URL changes.
90
92
  * Triggers for shallow pushes/replaces, hash changes, popstate-shallow, 404s, and full navigations.
91
93
  * Receives the router's current snapshot (eg `{ url: URL, route: RouteTuple|null, params: Params }`).
package/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { throttle } from 'es-toolkit'
1
2
  import { parse } from 'regexparam'
2
3
  import { tick } from 'svelte'
3
4
  import { writable } from 'svelte/store'
@@ -14,6 +15,7 @@ export default class Navgo {
14
15
  after_navigate: undefined,
15
16
  url_changed: undefined,
16
17
  tick,
18
+ scroll_to_top: true,
17
19
  attach_to_window: true,
18
20
  }
19
21
  /** @type {Array<{ pattern: RegExp, keys: string[]|null, data: RouteTuple }>} */
@@ -138,7 +140,7 @@ export default class Navgo {
138
140
  if (pos) {
139
141
  scrollTo(pos.x, pos.y)
140
142
  ℹ('[🧭 scroll]', 'restore hash-back', { idx: this.#route_idx, ...pos })
141
- } else {
143
+ } else if (this.#opts.scroll_to_top) {
142
144
  // no saved position for previous entry — default to top
143
145
  scrollTo(0, 0)
144
146
  ℹ('[🧭 scroll]', 'hash-back -> top')
@@ -254,8 +256,8 @@ export default class Navgo {
254
256
  return true
255
257
  }
256
258
 
257
- async #run_loader(route, params) {
258
- const ret_val = route[1].loader?.(params, route)
259
+ async #run_loader(route, url, params) {
260
+ const ret_val = route[1].loader?.({ route_entry: route, url, params })
259
261
  return Array.isArray(ret_val) ? Promise.all(ret_val) : ret_val
260
262
  }
261
263
 
@@ -355,7 +357,7 @@ export default class Navgo {
355
357
  const pre = this.#preloads.get(path)
356
358
  data =
357
359
  pre?.data ??
358
- (await (pre?.promise || this.#run_loader(hit.route, hit.params)).catch(e => ({
360
+ (await (pre?.promise || this.#run_loader(hit.route, url, hit.params)).catch(e => ({
359
361
  __error: e,
360
362
  })))
361
363
  this.#preloads.delete(path)
@@ -482,7 +484,7 @@ export default class Navgo {
482
484
  */
483
485
  /** @param {string} url_raw @returns {Promise<unknown|void>} */
484
486
  async preload(url_raw) {
485
- const { path } = this.#resolve_url_and_path(url_raw) || {}
487
+ const { path, url } = this.#resolve_url_and_path(url_raw) || {}
486
488
  if (!path) {
487
489
  ℹ('[🧭 preload]', 'invalid url', { url: url_raw })
488
490
  return Promise.resolve()
@@ -505,7 +507,7 @@ export default class Navgo {
505
507
  }
506
508
 
507
509
  const entry = {}
508
- entry.promise = this.#run_loader(hit.route, hit.params).then(data => {
510
+ entry.promise = this.#run_loader(hit.route, url, hit.params).then(data => {
509
511
  entry.data = data
510
512
  delete entry.promise
511
513
  ℹ('[🧭 preload]', 'done', { path })
@@ -699,8 +701,10 @@ export default class Navgo {
699
701
  return
700
702
  }
701
703
  // 3) Default: scroll to top for new navigations
702
- scrollTo(0, 0)
703
- ('[🧭 scroll]', 'top')
704
+ if (this.#opts.scroll_to_top) {
705
+ scrollTo(0, 0)
706
+ ℹ('[🧭 scroll]', 'top')
707
+ }
704
708
  })
705
709
  }
706
710
 
@@ -736,27 +740,6 @@ export default class Navgo {
736
740
  }
737
741
  }
738
742
 
739
- function throttle(fn, ms) {
740
- let t,
741
- last = 0
742
- return e => {
743
- const now = Date.now()
744
- if (now - last >= ms) {
745
- last = now
746
- fn(e)
747
- } else {
748
- clearTimeout(t)
749
- t = setTimeout(
750
- () => {
751
- last = Date.now()
752
- fn(e)
753
- },
754
- ms - (now - last),
755
- )
756
- }
757
- }
758
- }
759
-
760
743
  /** @typedef {import('./index.d.ts').Options} Options */
761
744
  /** @typedef {import('./index.d.ts').RouteTuple} RouteTuple */
762
745
  /** @typedef {import('./index.d.ts').MatchResult} MatchResult */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "navgo",
3
- "version": "4.0.3",
3
+ "version": "5.0.1",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/mustafa0x/navgo.git"
@@ -32,6 +32,7 @@
32
32
  "router"
33
33
  ],
34
34
  "dependencies": {
35
+ "es-toolkit": "^1.42.0",
35
36
  "regexparam": "^3.0.0"
36
37
  },
37
38
  "peerDependencies": {
package/readme.md CHANGED
@@ -102,6 +102,8 @@ Notes:
102
102
  - App-level hook called after routing completes (URL updated, data loaded). `nav.to.data` holds any loader data.
103
103
  - `tick`: `() => void | Promise<void>`
104
104
  - Awaited after `after_navigate` and before scroll handling; useful for frameworks to flush DOM so anchor/top scrolling lands correctly.
105
+ - `scroll_to_top`: `boolean` (default `true`)
106
+ - When `false`, skips the default top scroll for non-hash navigations.
105
107
  - `url_changed`: `(snapshot: any) => void`
106
108
  - Fires on every URL change -- shallow `push_state`/`replace_state`, hash changes, `popstate` shallow entries, 404s, and full navigations. (deprecated; subscribe to `.route` instead.)
107
109
  - Receives the router's current snapshot: an object like `{ url: URL, route: RouteTuple|null, params: Params }`.