navgo 6.0.7 → 6.0.9

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 (3) hide show
  1. package/changelog.md +5 -0
  2. package/index.js +34 -12
  3. package/package.json +1 -1
package/changelog.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## v6.0.8
4
+
5
+ - breaking: make search-schema transitions atomic by publishing `router.route` before global `router.search_params`, with sync guard across both writes
6
+ - note: `router.route.subscribe(...)` now fires before `router.search_params` updates on search-schema transitions
7
+
3
8
  ## v6.0.7
4
9
 
5
10
  - add `nav.status` as the formal HTTP-like status for completed navigations
package/index.js CHANGED
@@ -12,7 +12,7 @@ import {
12
12
  scroll_to_hash,
13
13
  validate_search,
14
14
  } from './utils.js'
15
- import { tick } from 'svelte'
15
+ import * as svelte from 'svelte'
16
16
  import { writable } from 'svelte/store'
17
17
  export { v }
18
18
  import { parse } from 'regexparam'
@@ -28,7 +28,7 @@ export default class Navgo {
28
28
  preload_on_hover: true,
29
29
  before_navigate: undefined,
30
30
  after_navigate: undefined,
31
- tick,
31
+ tick: svelte.tick,
32
32
  scroll_to_top: true,
33
33
  aria_current: false,
34
34
  attach_to_window: true,
@@ -288,7 +288,12 @@ export default class Navgo {
288
288
  ℹ('[🧭 navigate]', 'cancelled by before_route_leave during unload')
289
289
  ev.preventDefault()
290
290
  ev.returnValue = ''
291
+ return
291
292
  }
293
+
294
+ try {
295
+ history.scrollRestoration = 'auto'
296
+ } catch {}
292
297
  }
293
298
 
294
299
  //
@@ -588,10 +593,13 @@ export default class Navgo {
588
593
  #set_search_store(values) {
589
594
  const next = values || {}
590
595
  this.#search_syncing = true
591
- this.search_params.set(next)
592
- this.#search_syncing = false
593
- this.#current.search_params = next
594
- if (this.#current.url) this.route.set(this.#current)
596
+ try {
597
+ this.#current.search_params = next
598
+ if (this.#current.url) this.route.set(this.#current)
599
+ this.search_params.set(next)
600
+ } finally {
601
+ this.#search_syncing = false
602
+ }
595
603
  }
596
604
 
597
605
  /* Apply resolved search config to current route. */
@@ -1131,6 +1139,8 @@ export default class Navgo {
1131
1139
 
1132
1140
  // allow frameworks to flush DOM before scrolling
1133
1141
  try {
1142
+ await svelte.settled?.()
1143
+ await this.#opts.tick?.()
1134
1144
  await this.#opts.tick?.()
1135
1145
  } catch (e) {
1136
1146
  ℹ('[🧭 hooks]', 'tick threw', { err: e })
@@ -1379,7 +1389,6 @@ export default class Navgo {
1379
1389
  if (initial) this.route.set({ ...this.#target(initial), search_params: {} })
1380
1390
 
1381
1391
  const group_ids = new Map()
1382
-
1383
1392
  function compile_routes(entries, stack = []) {
1384
1393
  const out = []
1385
1394
  for (const e of entries || []) {
@@ -1437,9 +1446,8 @@ export default class Navgo {
1437
1446
  //
1438
1447
  // Lifecycle hooks
1439
1448
  //
1440
- init() {
1441
- history.scrollRestoration = 'manual'
1442
- ℹ('[🧭 init]', 'attach listeners; scrollRestoration=manual')
1449
+ async init() {
1450
+ ℹ('[🧭 init]', 'attach listeners')
1443
1451
 
1444
1452
  addEventListener('popstate', this.#on_popstate)
1445
1453
  addEventListener('click', this.#click)
@@ -1472,7 +1480,11 @@ export default class Navgo {
1472
1480
 
1473
1481
  ℹ('[🧭 init]', 'initial goto')
1474
1482
  if (this.#opts.attach_to_window) window.navgo = this
1475
- return this.goto()
1483
+ await this.goto()
1484
+ try {
1485
+ history.scrollRestoration = 'manual'
1486
+ ℹ('[🧭 init]', 'scrollRestoration=manual')
1487
+ } catch {}
1476
1488
  }
1477
1489
  destroy() {
1478
1490
  removeEventListener('popstate', this.#on_popstate)
@@ -1497,17 +1509,27 @@ export default class Navgo {
1497
1509
  const hash = location.hash
1498
1510
  const t = ctx?.type || ctx?.event?.type
1499
1511
  requestAnimationFrame(() => {
1500
- // 0) Initial (first) navigation: prefer restoring session scroll
1512
+ // 0) Initial (first) navigation: prefer restoring session scroll,
1513
+ // otherwise preserve whatever the browser already did for the SSR document.
1501
1514
  const is_initial = ctx && 'from' in ctx ? ctx.from == null : !t
1502
1515
  if (is_initial) {
1503
1516
  try {
1504
1517
  const k = `__navgo_scroll:${location.href}`
1505
1518
  const { x, y } = JSON.parse(sessionStorage.getItem(k))
1506
1519
  sessionStorage.removeItem(k)
1520
+ try {
1521
+ history.scrollRestoration = 'manual'
1522
+ } catch {}
1507
1523
  scrollTo(x, y)
1508
1524
  ℹ('[🧭 scroll]', 'restore session', { x, y })
1509
1525
  return
1510
1526
  } catch {}
1527
+ if (hash && scroll_to_hash(hash)) {
1528
+ ℹ('[🧭 scroll]', 'initial hash')
1529
+ return
1530
+ }
1531
+ ℹ('[🧭 scroll]', 'initial preserve')
1532
+ return
1511
1533
  }
1512
1534
  // 1) On back/forward, restore saved position if available
1513
1535
  if (t === 'popstate') {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "navgo",
3
- "version": "6.0.7",
3
+ "version": "6.0.9",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/mustafa0x/navgo.git"