@bquery/bquery 1.7.0 → 1.8.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.
Files changed (262) hide show
  1. package/README.md +760 -716
  2. package/dist/{a11y-C5QOVvRn.js → a11y-DVBCy09c.js} +3 -3
  3. package/dist/a11y-DVBCy09c.js.map +1 -0
  4. package/dist/a11y.es.mjs +1 -1
  5. package/dist/component/library.d.ts.map +1 -1
  6. package/dist/{component-CuuTijA6.js → component-L3-JfOFz.js} +5 -5
  7. package/dist/component-L3-JfOFz.js.map +1 -0
  8. package/dist/component.es.mjs +1 -1
  9. package/dist/{config-BW35FKuA.js → config-DhT9auRm.js} +1 -1
  10. package/dist/{config-BW35FKuA.js.map → config-DhT9auRm.js.map} +1 -1
  11. package/dist/{constraints-3lV9yyBw.js → constraints-D5RHQLmP.js} +1 -1
  12. package/dist/constraints-D5RHQLmP.js.map +1 -0
  13. package/dist/core/collection.d.ts +86 -0
  14. package/dist/core/collection.d.ts.map +1 -1
  15. package/dist/core/element.d.ts +28 -0
  16. package/dist/core/element.d.ts.map +1 -1
  17. package/dist/core/shared.d.ts +6 -0
  18. package/dist/core/shared.d.ts.map +1 -1
  19. package/dist/core-DdtZHzsS.js +168 -0
  20. package/dist/core-DdtZHzsS.js.map +1 -0
  21. package/dist/{core-Cjl7GUu8.js → core-EMYSLzaT.js} +289 -259
  22. package/dist/core-EMYSLzaT.js.map +1 -0
  23. package/dist/core.es.mjs +48 -47
  24. package/dist/{custom-directives-7wAShnnd.js → custom-directives-Dr4C5lVV.js} +1 -1
  25. package/dist/custom-directives-Dr4C5lVV.js.map +1 -0
  26. package/dist/{devtools-D2fQLhDN.js → devtools-BhB2iDPT.js} +2 -2
  27. package/dist/devtools-BhB2iDPT.js.map +1 -0
  28. package/dist/devtools.es.mjs +1 -1
  29. package/dist/{dnd-B8EgyzaI.js → dnd-NwZBYh4l.js} +1 -1
  30. package/dist/dnd-NwZBYh4l.js.map +1 -0
  31. package/dist/dnd.es.mjs +1 -1
  32. package/dist/{env-NeVmr4Gf.js → env-CTdvLaH2.js} +1 -1
  33. package/dist/env-CTdvLaH2.js.map +1 -0
  34. package/dist/forms/create-form.d.ts.map +1 -1
  35. package/dist/forms/index.d.ts +3 -2
  36. package/dist/forms/index.d.ts.map +1 -1
  37. package/dist/forms/types.d.ts +46 -0
  38. package/dist/forms/types.d.ts.map +1 -1
  39. package/dist/forms/use-field.d.ts +34 -0
  40. package/dist/forms/use-field.d.ts.map +1 -0
  41. package/dist/forms/validators.d.ts +25 -0
  42. package/dist/forms/validators.d.ts.map +1 -1
  43. package/dist/forms-UcRHsYxC.js +227 -0
  44. package/dist/forms-UcRHsYxC.js.map +1 -0
  45. package/dist/forms.es.mjs +14 -12
  46. package/dist/full.d.ts +17 -26
  47. package/dist/full.d.ts.map +1 -1
  48. package/dist/full.es.mjs +206 -181
  49. package/dist/full.iife.js +33 -33
  50. package/dist/full.iife.js.map +1 -1
  51. package/dist/full.umd.js +33 -33
  52. package/dist/full.umd.js.map +1 -1
  53. package/dist/function-Cybd57JV.js +33 -0
  54. package/dist/function-Cybd57JV.js.map +1 -0
  55. package/dist/{i18n-BnnhTFOS.js → i18n-kuF6Ekj6.js} +3 -3
  56. package/dist/i18n-kuF6Ekj6.js.map +1 -0
  57. package/dist/i18n.es.mjs +1 -1
  58. package/dist/index.es.mjs +251 -228
  59. package/dist/media/breakpoints.d.ts.map +1 -1
  60. package/dist/media/types.d.ts +2 -2
  61. package/dist/media/types.d.ts.map +1 -1
  62. package/dist/{media-Di2Ta22s.js → media-i-fB5WxI.js} +3 -3
  63. package/dist/media-i-fB5WxI.js.map +1 -0
  64. package/dist/media.es.mjs +1 -1
  65. package/dist/{motion-qPj_TYGv.js → motion-BJsAuULb.js} +2 -2
  66. package/dist/motion-BJsAuULb.js.map +1 -0
  67. package/dist/motion.es.mjs +1 -1
  68. package/dist/{mount-SM07RUa6.js → mount-B4Y8bk8Z.js} +5 -5
  69. package/dist/mount-B4Y8bk8Z.js.map +1 -0
  70. package/dist/{platform-CPbCprb6.js → platform-Dw2gE3zI.js} +3 -3
  71. package/dist/{platform-CPbCprb6.js.map → platform-Dw2gE3zI.js.map} +1 -1
  72. package/dist/platform.es.mjs +2 -2
  73. package/dist/plugin/registry.d.ts.map +1 -1
  74. package/dist/{plugin-cPoOHFLY.js → plugin-C2WuC8SF.js} +20 -18
  75. package/dist/plugin-C2WuC8SF.js.map +1 -0
  76. package/dist/plugin.es.mjs +1 -1
  77. package/dist/reactive/async-data.d.ts +28 -3
  78. package/dist/reactive/async-data.d.ts.map +1 -1
  79. package/dist/reactive/computed.d.ts +3 -0
  80. package/dist/reactive/computed.d.ts.map +1 -1
  81. package/dist/reactive/effect.d.ts +3 -0
  82. package/dist/reactive/effect.d.ts.map +1 -1
  83. package/dist/reactive/http.d.ts +194 -0
  84. package/dist/reactive/http.d.ts.map +1 -0
  85. package/dist/reactive/index.d.ts +2 -2
  86. package/dist/reactive/index.d.ts.map +1 -1
  87. package/dist/reactive/pagination.d.ts +126 -0
  88. package/dist/reactive/pagination.d.ts.map +1 -0
  89. package/dist/reactive/polling.d.ts +55 -0
  90. package/dist/reactive/polling.d.ts.map +1 -0
  91. package/dist/reactive/readonly.d.ts +20 -1
  92. package/dist/reactive/readonly.d.ts.map +1 -1
  93. package/dist/reactive/rest.d.ts +293 -0
  94. package/dist/reactive/rest.d.ts.map +1 -0
  95. package/dist/reactive/scope.d.ts +140 -0
  96. package/dist/reactive/scope.d.ts.map +1 -0
  97. package/dist/reactive/signal.d.ts +16 -2
  98. package/dist/reactive/signal.d.ts.map +1 -1
  99. package/dist/reactive/to-value.d.ts +57 -0
  100. package/dist/reactive/to-value.d.ts.map +1 -0
  101. package/dist/reactive/websocket.d.ts +285 -0
  102. package/dist/reactive/websocket.d.ts.map +1 -0
  103. package/dist/reactive-DwkhUJfP.js +1148 -0
  104. package/dist/reactive-DwkhUJfP.js.map +1 -0
  105. package/dist/reactive.es.mjs +38 -19
  106. package/dist/{registry-CWf368tT.js → registry-B08iilIh.js} +1 -1
  107. package/dist/{registry-CWf368tT.js.map → registry-B08iilIh.js.map} +1 -1
  108. package/dist/router/constraints.d.ts.map +1 -1
  109. package/dist/router/index.d.ts +1 -1
  110. package/dist/router/index.d.ts.map +1 -1
  111. package/dist/router/router.d.ts.map +1 -1
  112. package/dist/router/state.d.ts +25 -2
  113. package/dist/router/state.d.ts.map +1 -1
  114. package/dist/router-CQikC9Ed.js +492 -0
  115. package/dist/router-CQikC9Ed.js.map +1 -0
  116. package/dist/router.es.mjs +9 -8
  117. package/dist/ssr/hydrate.d.ts.map +1 -1
  118. package/dist/{ssr-B2qd_WBB.js → ssr-_dAcGdzu.js} +4 -4
  119. package/dist/ssr-_dAcGdzu.js.map +1 -0
  120. package/dist/ssr.es.mjs +1 -1
  121. package/dist/store/persisted.d.ts.map +1 -1
  122. package/dist/{store-DWpyH6p5.js → store-Cb3gPRve.js} +7 -7
  123. package/dist/store-Cb3gPRve.js.map +1 -0
  124. package/dist/store.es.mjs +2 -2
  125. package/dist/storybook.es.mjs.map +1 -1
  126. package/dist/{testing-CsqjNUyy.js → testing-C5Sjfsna.js} +8 -8
  127. package/dist/testing-C5Sjfsna.js.map +1 -0
  128. package/dist/testing.es.mjs +1 -1
  129. package/dist/{type-guards-Do9DWgNp.js → type-guards-BMX2c0LP.js} +1 -1
  130. package/dist/{type-guards-Do9DWgNp.js.map → type-guards-BMX2c0LP.js.map} +1 -1
  131. package/dist/untrack-D0fnO5k2.js +36 -0
  132. package/dist/untrack-D0fnO5k2.js.map +1 -0
  133. package/dist/view/custom-directives.d.ts.map +1 -1
  134. package/dist/view.es.mjs +4 -4
  135. package/package.json +177 -177
  136. package/src/a11y/announce.ts +131 -131
  137. package/src/a11y/audit.ts +314 -314
  138. package/src/a11y/index.ts +68 -68
  139. package/src/a11y/media-preferences.ts +255 -255
  140. package/src/a11y/roving-tab-index.ts +164 -164
  141. package/src/a11y/skip-link.ts +255 -255
  142. package/src/a11y/trap-focus.ts +184 -184
  143. package/src/a11y/types.ts +183 -183
  144. package/src/component/component.ts +599 -599
  145. package/src/component/html.ts +153 -153
  146. package/src/component/index.ts +52 -52
  147. package/src/component/library.ts +540 -542
  148. package/src/component/scope.ts +212 -212
  149. package/src/component/types.ts +310 -310
  150. package/src/core/collection.ts +876 -707
  151. package/src/core/element.ts +1015 -981
  152. package/src/core/env.ts +60 -60
  153. package/src/core/index.ts +49 -49
  154. package/src/core/shared.ts +77 -62
  155. package/src/core/utils/index.ts +148 -148
  156. package/src/devtools/devtools.ts +410 -410
  157. package/src/devtools/index.ts +48 -48
  158. package/src/devtools/types.ts +104 -104
  159. package/src/dnd/draggable.ts +296 -296
  160. package/src/dnd/droppable.ts +228 -228
  161. package/src/dnd/index.ts +62 -62
  162. package/src/dnd/sortable.ts +307 -307
  163. package/src/dnd/types.ts +293 -293
  164. package/src/forms/create-form.ts +320 -278
  165. package/src/forms/index.ts +70 -65
  166. package/src/forms/types.ts +203 -154
  167. package/src/forms/use-field.ts +231 -0
  168. package/src/forms/validators.ts +294 -265
  169. package/src/full.ts +554 -480
  170. package/src/i18n/formatting.ts +67 -67
  171. package/src/i18n/i18n.ts +200 -200
  172. package/src/i18n/index.ts +67 -67
  173. package/src/i18n/translate.ts +182 -182
  174. package/src/i18n/types.ts +171 -171
  175. package/src/index.ts +108 -108
  176. package/src/media/battery.ts +116 -116
  177. package/src/media/breakpoints.ts +129 -131
  178. package/src/media/clipboard.ts +80 -80
  179. package/src/media/device-sensors.ts +158 -158
  180. package/src/media/geolocation.ts +119 -119
  181. package/src/media/index.ts +76 -76
  182. package/src/media/media-query.ts +92 -92
  183. package/src/media/network.ts +115 -115
  184. package/src/media/types.ts +177 -177
  185. package/src/media/viewport.ts +84 -84
  186. package/src/motion/index.ts +57 -57
  187. package/src/motion/morph.ts +151 -151
  188. package/src/motion/parallax.ts +120 -120
  189. package/src/motion/reduced-motion.ts +66 -66
  190. package/src/motion/types.ts +271 -271
  191. package/src/motion/typewriter.ts +164 -164
  192. package/src/plugin/index.ts +37 -37
  193. package/src/plugin/registry.ts +284 -269
  194. package/src/plugin/types.ts +137 -137
  195. package/src/reactive/async-data.ts +250 -29
  196. package/src/reactive/computed.ts +144 -130
  197. package/src/reactive/effect.ts +29 -6
  198. package/src/reactive/http.ts +790 -0
  199. package/src/reactive/index.ts +60 -0
  200. package/src/reactive/pagination.ts +317 -0
  201. package/src/reactive/polling.ts +179 -0
  202. package/src/reactive/readonly.ts +52 -8
  203. package/src/reactive/rest.ts +859 -0
  204. package/src/reactive/scope.ts +276 -0
  205. package/src/reactive/signal.ts +61 -1
  206. package/src/reactive/to-value.ts +71 -0
  207. package/src/reactive/websocket.ts +849 -0
  208. package/src/router/bq-link.ts +279 -279
  209. package/src/router/constraints.ts +204 -201
  210. package/src/router/index.ts +49 -49
  211. package/src/router/match.ts +312 -312
  212. package/src/router/path-pattern.ts +52 -52
  213. package/src/router/query.ts +38 -38
  214. package/src/router/router.ts +421 -402
  215. package/src/router/state.ts +51 -3
  216. package/src/router/types.ts +139 -139
  217. package/src/router/use-route.ts +68 -68
  218. package/src/router/utils.ts +157 -157
  219. package/src/security/index.ts +12 -12
  220. package/src/ssr/hydrate.ts +84 -82
  221. package/src/ssr/index.ts +70 -70
  222. package/src/ssr/render.ts +508 -508
  223. package/src/ssr/serialize.ts +296 -296
  224. package/src/ssr/types.ts +81 -81
  225. package/src/store/create-store.ts +467 -467
  226. package/src/store/index.ts +27 -27
  227. package/src/store/persisted.ts +245 -249
  228. package/src/store/types.ts +247 -247
  229. package/src/store/utils.ts +135 -135
  230. package/src/storybook/index.ts +480 -480
  231. package/src/testing/index.ts +42 -42
  232. package/src/testing/testing.ts +593 -593
  233. package/src/testing/types.ts +170 -170
  234. package/src/view/custom-directives.ts +28 -30
  235. package/src/view/evaluate.ts +292 -292
  236. package/src/view/process.ts +108 -108
  237. package/dist/a11y-C5QOVvRn.js.map +0 -1
  238. package/dist/component-CuuTijA6.js.map +0 -1
  239. package/dist/constraints-3lV9yyBw.js.map +0 -1
  240. package/dist/core-Cjl7GUu8.js.map +0 -1
  241. package/dist/core-DnlyjbF2.js +0 -112
  242. package/dist/core-DnlyjbF2.js.map +0 -1
  243. package/dist/custom-directives-7wAShnnd.js.map +0 -1
  244. package/dist/devtools-D2fQLhDN.js.map +0 -1
  245. package/dist/dnd-B8EgyzaI.js.map +0 -1
  246. package/dist/env-NeVmr4Gf.js.map +0 -1
  247. package/dist/forms-C3yovgH9.js +0 -141
  248. package/dist/forms-C3yovgH9.js.map +0 -1
  249. package/dist/i18n-BnnhTFOS.js.map +0 -1
  250. package/dist/media-Di2Ta22s.js.map +0 -1
  251. package/dist/motion-qPj_TYGv.js.map +0 -1
  252. package/dist/mount-SM07RUa6.js.map +0 -1
  253. package/dist/plugin-cPoOHFLY.js.map +0 -1
  254. package/dist/reactive-Cfv0RK6x.js +0 -233
  255. package/dist/reactive-Cfv0RK6x.js.map +0 -1
  256. package/dist/router-BrthaP_z.js +0 -473
  257. package/dist/router-BrthaP_z.js.map +0 -1
  258. package/dist/ssr-B2qd_WBB.js.map +0 -1
  259. package/dist/store-DWpyH6p5.js.map +0 -1
  260. package/dist/testing-CsqjNUyy.js.map +0 -1
  261. package/dist/untrack-DJVQQ2WM.js +0 -33
  262. package/dist/untrack-DJVQQ2WM.js.map +0 -1
@@ -1,473 +0,0 @@
1
- import { i as G } from "./object-BCk-1c8T.js";
2
- import { n as nt, r as st } from "./core-DnlyjbF2.js";
3
- import { r as L } from "./untrack-DJVQQ2WM.js";
4
- import { n as Y, t as at } from "./constraints-3lV9yyBw.js";
5
- var Z = null, k = nt({
6
- path: "",
7
- params: {},
8
- query: {},
9
- matched: null,
10
- hash: ""
11
- }), ot = L(() => k.value), T = () => Z, B = (t) => {
12
- Z = t;
13
- }, Q = async (t, e = {}) => {
14
- const r = T();
15
- if (!r) throw new Error("bQuery router: No router initialized. Call createRouter() first.");
16
- await r[e.replace ? "replace" : "push"](t);
17
- }, At = () => {
18
- const t = T();
19
- t ? t.back() : history.back();
20
- }, Ct = () => {
21
- const t = T();
22
- t ? t.forward() : history.forward();
23
- }, it = "active", ct = (t) => t.split(/\s+/).map((e) => e.trim()).filter((e) => e.length > 0), lt = typeof HTMLElement < "u" ? HTMLElement : class {
24
- }, ut = class extends lt {
25
- constructor(...t) {
26
- super(...t), this._cleanup = null, this._trackedActiveClasses = /* @__PURE__ */ new Map(), this._handleClick = (e) => {
27
- e instanceof MouseEvent && (e.defaultPrevented || e.button === 0 && (e.ctrlKey || e.metaKey || e.shiftKey || e.altKey || (e.preventDefault(), this._navigate())));
28
- }, this._handleKeydown = (e) => {
29
- e instanceof KeyboardEvent && e.key === "Enter" && (e.preventDefault(), this._navigate());
30
- };
31
- }
32
- static get observedAttributes() {
33
- return [
34
- "to",
35
- "replace",
36
- "exact",
37
- "active-class"
38
- ];
39
- }
40
- get to() {
41
- const t = this.getAttribute("to");
42
- return t == null || t.trim() === "" ? "/" : t;
43
- }
44
- set to(t) {
45
- this.setAttribute("to", t);
46
- }
47
- get replace() {
48
- return this.hasAttribute("replace");
49
- }
50
- set replace(t) {
51
- t ? this.setAttribute("replace", "") : this.removeAttribute("replace");
52
- }
53
- get exact() {
54
- return this.hasAttribute("exact");
55
- }
56
- set exact(t) {
57
- t ? this.setAttribute("exact", "") : this.removeAttribute("exact");
58
- }
59
- get activeClass() {
60
- return this.getAttribute("active-class") ?? it;
61
- }
62
- set activeClass(t) {
63
- this.setAttribute("active-class", t);
64
- }
65
- connectedCallback() {
66
- this.getAttribute("role") || this.setAttribute("role", "link"), this.hasAttribute("tabindex") || this.setAttribute("tabindex", "0"), this.addEventListener("click", this._handleClick), this.addEventListener("keydown", this._handleKeydown), this._setupActiveTracking();
67
- }
68
- disconnectedCallback() {
69
- this.removeEventListener("click", this._handleClick), this.removeEventListener("keydown", this._handleKeydown), this._cleanup && (this._cleanup(), this._cleanup = null), this._clearTrackedActiveClasses();
70
- }
71
- attributeChangedCallback(t, e, r) {
72
- (t === "to" || t === "exact" || t === "active-class") && this.isConnected && this._setupActiveTracking();
73
- }
74
- _setupActiveTracking() {
75
- this._cleanup && (this._cleanup(), this._cleanup = null), this._clearTrackedActiveClasses();
76
- const t = this.to, e = this.exact, r = ct(this.activeClass);
77
- this._trackedActiveClasses = new Map(r.map((n) => [n, this.classList.contains(n)])), this._cleanup = st(() => {
78
- const n = k.value.path, s = e ? n === t : t === "/" ? n === "/" : n === t || n.startsWith(t.endsWith("/") ? t : t + "/");
79
- for (const a of r) {
80
- const o = this._trackedActiveClasses.get(a) ?? !1;
81
- this.classList.toggle(a, s || o);
82
- }
83
- s ? this.setAttribute("aria-current", "page") : this.removeAttribute("aria-current");
84
- });
85
- }
86
- _clearTrackedActiveClasses() {
87
- for (const [t, e] of this._trackedActiveClasses) this.classList.toggle(t, e);
88
- this._trackedActiveClasses.clear();
89
- }
90
- _navigate() {
91
- const t = this.to;
92
- t && T() && Q(t, { replace: this.replace }).catch((e) => {
93
- console.error("bq-link: Navigation failed:", e);
94
- });
95
- }
96
- }, $t = () => {
97
- typeof HTMLElement < "u" && typeof customElements < "u" && !customElements.get("bq-link") && customElements.define("bq-link", ut);
98
- }, kt = (t, e = {}) => (r) => {
99
- r.preventDefault(), Q(t, e).catch((n) => {
100
- console.error("Navigation failed:", n);
101
- });
102
- }, Rt = (t) => {
103
- const e = t ?? (typeof document < "u" ? document.body : null);
104
- if (!e) return () => {
105
- };
106
- const r = (n) => {
107
- if (!(n instanceof MouseEvent) || n.defaultPrevented || n.button !== 0 || n.ctrlKey || n.metaKey || n.shiftKey || n.altKey || typeof Element > "u" || !(n.target instanceof Element)) return;
108
- const s = n.target.closest("a");
109
- if (!s || !(s instanceof (s.ownerDocument.defaultView?.HTMLAnchorElement ?? HTMLAnchorElement)) || s.target || s.hasAttribute("download") || typeof window > "u" || s.origin !== window.location.origin) return;
110
- const a = T();
111
- if (!a) {
112
- n.preventDefault(), Q(s.pathname + s.search + s.hash).catch((l) => {
113
- console.error("Navigation failed:", l);
114
- });
115
- return;
116
- }
117
- const o = a.base, p = a.hash;
118
- let u;
119
- if (p && s.hash && s.hash.startsWith("#/")) u = s.hash.slice(1);
120
- else {
121
- let l = s.pathname;
122
- o && o !== "/" && l.startsWith(o) && (l = l.slice(o.length) || "/"), u = l + s.search + s.hash;
123
- }
124
- n.preventDefault(), Q(u).catch((l) => {
125
- console.error("Navigation failed:", l);
126
- });
127
- };
128
- return e.addEventListener("click", r), () => e.removeEventListener("click", r);
129
- }, ht = (t) => {
130
- const e = {};
131
- return new URLSearchParams(t).forEach((r, n) => {
132
- if (G(n)) return;
133
- const s = e[n];
134
- s === void 0 ? e[n] = r : Array.isArray(s) ? s.push(r) : e[n] = [s, r];
135
- }), e;
136
- }, N = (t) => t !== void 0 && (t >= "a" && t <= "z" || t >= "A" && t <= "Z" || t === "_"), I = (t) => N(t) || t !== void 0 && t >= "0" && t <= "9", J = (t, e) => {
137
- let r = 1, n = "", s = e + 1, a = !1;
138
- for (; s < t.length; ) {
139
- const o = t[s];
140
- if (o === "\\" && s + 1 < t.length) {
141
- n += o + t[s + 1], s += 2;
142
- continue;
143
- }
144
- if (o === "[" && !a) a = !0;
145
- else if (o === "]" && a) a = !1;
146
- else if (!a && o === "(") r++;
147
- else if (!a && o === ")" && (r--, r === 0))
148
- return {
149
- constraint: n,
150
- endIndex: s + 1
151
- };
152
- n += o, s++;
153
- }
154
- return null;
155
- }, ft = (t, e) => {
156
- const r = J(t, e);
157
- if (!r) throw new Error(`bQuery router: Invalid route param constraint syntax in path "${t}" at index ${e}.`);
158
- return r;
159
- }, V = /* @__PURE__ */ new Set(), tt = (t, e) => {
160
- if (t[e] !== ":" || !N(t[e + 1])) return null;
161
- let r = e + 2;
162
- for (; r < t.length && I(t[r]); ) r++;
163
- let n = r, s;
164
- if (t[r] === "(") {
165
- const a = ft(t, r);
166
- s = a.constraint, n = a.endIndex;
167
- }
168
- return {
169
- name: t.slice(e + 1, r),
170
- constraint: s,
171
- nextIndex: n
172
- };
173
- }, dt = (t) => {
174
- if (!V.has(t)) {
175
- for (let e = 0; e < t.length; ) {
176
- if (t[e] === ":" && N(t[e + 1])) {
177
- const r = tt(t, e);
178
- r?.constraint && at(r.constraint), e = r?.nextIndex ?? e + 1;
179
- continue;
180
- }
181
- e++;
182
- }
183
- V.add(t);
184
- }
185
- }, vt = (t, e) => {
186
- const r = t.indexOf("/", e);
187
- return r === -1 ? t.length : r;
188
- }, F = (t, e) => {
189
- let r = e;
190
- for (; r < t.length && !(t[r] === "*" || t[r] === ":" && N(t[r + 1])); )
191
- r++;
192
- return t.slice(e, r);
193
- }, X = (t, e, r, n) => {
194
- const s = [];
195
- let a = e;
196
- for (; a <= r; ) {
197
- const o = t.indexOf(n, a);
198
- if (o === -1 || o > r) break;
199
- s.push(o), a = o + 1;
200
- }
201
- return s.reverse();
202
- }, pt = (t, e) => {
203
- const r = /* @__PURE__ */ new Map(), n = (s, a) => {
204
- const o = `${s}:${a}`;
205
- if (r.has(o)) return r.get(o) ?? null;
206
- if (s === t.length) {
207
- const h = a === e.length ? {} : null;
208
- return r.set(o, h), h;
209
- }
210
- const p = t[s];
211
- if (p === "*") {
212
- if (s === t.length - 1) {
213
- const d = {};
214
- return r.set(o, d), d;
215
- }
216
- const h = F(t, s + 1), w = h.length > 0 ? X(e, a, e.length, h) : null, A = (w ? (d) => {
217
- for (const y of w) {
218
- const v = d(y);
219
- if (v) return v;
220
- }
221
- return null;
222
- } : (d) => {
223
- for (let y = e.length; y >= a; y--) {
224
- const v = d(y);
225
- if (v) return v;
226
- }
227
- return null;
228
- })((d) => {
229
- const y = n(s + 1, d);
230
- return y ? (r.set(o, y), y) : null;
231
- });
232
- return A || (r.set(o, null), null);
233
- }
234
- const u = tt(t, s);
235
- if (u) {
236
- const h = u.constraint ? Y(u.constraint) : void 0, w = u.constraint ? e.length : vt(e, a), A = F(t, u.nextIndex), d = A.length > 0 ? X(e, a, w, A) : null, y = (d ? (v) => {
237
- for (const g of d) {
238
- if (g <= a) continue;
239
- const b = v(g);
240
- if (b) return b;
241
- }
242
- return null;
243
- } : (v) => {
244
- for (let g = w; g > a; g--) {
245
- const b = v(g);
246
- if (b) return b;
247
- }
248
- return null;
249
- })((v) => {
250
- const g = e.slice(a, v);
251
- if (h && !h.test(g))
252
- return null;
253
- const b = n(u.nextIndex, v);
254
- if (b) {
255
- const q = {
256
- [u.name]: g,
257
- ...b
258
- };
259
- return r.set(o, q), q;
260
- }
261
- return null;
262
- });
263
- return y || (r.set(o, null), null);
264
- }
265
- if (a >= e.length || p !== e[a])
266
- return r.set(o, null), null;
267
- const l = n(s + 1, a + 1);
268
- return r.set(o, l), l;
269
- };
270
- return n(0, 0);
271
- }, yt = (t, e) => {
272
- for (const r of e) {
273
- dt(r.path);
274
- const n = pt(r.path, t);
275
- if (n) return {
276
- matched: r,
277
- params: n
278
- };
279
- }
280
- return null;
281
- }, O = (t, e, r, n) => {
282
- const s = yt(t, n);
283
- return {
284
- path: t,
285
- params: s?.params ?? {},
286
- query: ht(e),
287
- matched: s?.matched ?? null,
288
- hash: r.replace(/^#/, "")
289
- };
290
- }, et = (t, e = "") => {
291
- const r = [];
292
- for (const n of t) {
293
- const s = n.path === "*" ? "*" : `${e}${n.path}`.replace(/\/+/g, "/");
294
- r.push({
295
- ...n,
296
- path: s
297
- }), n.children && r.push(...et(n.children, s));
298
- }
299
- return r;
300
- }, Lt = (t, e = {}) => {
301
- const r = T();
302
- if (!r) throw new Error("bQuery router: No router initialized.");
303
- const n = r.routes.find((a) => a.name === t);
304
- if (!n) throw new Error(`bQuery router: Route "${t}" not found.`);
305
- let s = "";
306
- for (let a = 0; a < n.path.length; ) {
307
- if (n.path[a] === ":" && N(n.path[a + 1])) {
308
- let o = a + 2;
309
- for (; o < n.path.length && I(n.path[o]); ) o++;
310
- let p = o, u = null;
311
- if (n.path[o] === "(") {
312
- const w = J(n.path, o);
313
- if (!w) throw new Error(`bQuery router: Invalid constraint syntax in path "${n.path}" for route "${t}".`);
314
- u = w.constraint, p = w.endIndex;
315
- }
316
- const l = n.path.slice(a + 1, o), h = e[l];
317
- if (h === void 0) throw new Error(`bQuery router: Missing required param "${l}" for route "${t}".`);
318
- if (u && !Y(u).test(h)) throw new Error(`bQuery router: Param "${l}" with value "${h}" does not satisfy the route constraint "${u}" for route "${t}".`);
319
- s += encodeURIComponent(h), a = p;
320
- continue;
321
- }
322
- s += n.path[a], a++;
323
- }
324
- return s;
325
- }, Kt = (t, e = !1) => {
326
- const r = k.value.path;
327
- return e ? r === t : r.startsWith(t);
328
- }, xt = (t, e = !1) => L(() => {
329
- const r = k.value.path;
330
- return e ? r === t : r.startsWith(t);
331
- }), mt = 100, wt = (t) => {
332
- const e = {};
333
- for (const [r, n] of Object.entries(t))
334
- G(r) || (e[r] = n);
335
- return e;
336
- }, Tt = (t) => {
337
- const e = T();
338
- e && e.destroy();
339
- const { routes: r, base: n = "", hash: s = !1, scrollRestoration: a = !1 } = t, o = [], p = [], u = et(r), l = /* @__PURE__ */ new Map();
340
- let h = "0", w = 0, A = null;
341
- if (a && typeof history < "u" && "scrollRestoration" in history) {
342
- A = history.scrollRestoration, history.scrollRestoration !== "manual" && (history.scrollRestoration = "manual");
343
- const i = history.state && typeof history.state == "object" ? history.state : {};
344
- if (typeof i.__bqScrollKey != "string") {
345
- const c = s ? window.location.hash || "#/" : `${window.location.pathname}${window.location.search}${window.location.hash}`;
346
- history.replaceState({
347
- ...i,
348
- __bqScrollKey: h
349
- }, "", c);
350
- }
351
- }
352
- const d = () => history.state && history.state.__bqScrollKey || h, y = () => `${Date.now()}-${w++}`, v = (i = d()) => {
353
- if (a)
354
- for (l.has(i) && l.delete(i), l.set(i, {
355
- x: window.scrollX,
356
- y: window.scrollY
357
- }); l.size > mt; ) {
358
- const c = l.keys().next().value;
359
- if (c === void 0) break;
360
- l.delete(c);
361
- }
362
- }, g = (i = d()) => {
363
- if (!a) return;
364
- const c = l.get(i);
365
- c ? window.scrollTo(c.x, c.y) : window.scrollTo(0, 0);
366
- }, b = () => {
367
- const i = history.state && typeof history.state == "object" ? { ...history.state } : {};
368
- return a && (i.__bqScrollKey = h), i;
369
- }, q = () => {
370
- if (s) {
371
- const [c, _ = ""] = (window.location.hash.slice(1) || "/").split("#"), [P, f = ""] = c.split("?");
372
- return {
373
- pathname: P,
374
- search: f ? `?${f}` : "",
375
- hash: _ ? `#${_}` : ""
376
- };
377
- }
378
- let i = window.location.pathname;
379
- return n && (i === n || i.startsWith(n + "/")) && (i = i.slice(n.length) || "/"), {
380
- pathname: i,
381
- search: window.location.search,
382
- hash: window.location.hash
383
- };
384
- }, D = () => {
385
- const { pathname: i, search: c, hash: _ } = q();
386
- k.value = O(i, c, _, u);
387
- }, H = async (i, c, _ = /* @__PURE__ */ new Set()) => {
388
- const { pathname: P, search: f, hash: R } = q(), S = O(P, f, R, u), m = new URL(i, window.location.origin), C = `${m.pathname}${m.search}${m.hash}`;
389
- if (_.has(C)) throw new Error(`bQuery router: redirect loop detected for path "${C}"`);
390
- _.add(C);
391
- const E = O(m.pathname, m.search, m.hash, u);
392
- if (E.matched?.redirectTo) {
393
- await H(E.matched.redirectTo, c, _);
394
- return;
395
- }
396
- if (E.matched?.beforeEnter && await E.matched.beforeEnter(E, S) === !1)
397
- return;
398
- for (const W of o) if (await W(E, S) === !1) return;
399
- v();
400
- const K = a ? d() : void 0, $ = c === "replaceState" && K ? K : y(), x = s ? `#${i}` : `${n}${i}`, z = a && history.state && typeof history.state == "object" ? wt(history.state) : {}, rt = a ? {
401
- ...z,
402
- __bqScrollKey: $
403
- } : {};
404
- history[c](rt, "", x), h = $, D(), a && c === "pushState" && window.scrollTo(0, 0);
405
- for (const W of p) W(k.value, S);
406
- }, U = async (i) => {
407
- const { pathname: c, search: _, hash: P } = q(), f = k.value, R = O(c, _, P, u);
408
- if (R.matched?.redirectTo) {
409
- await H(R.matched.redirectTo, "replaceState");
410
- return;
411
- }
412
- if (R.matched?.beforeEnter && await R.matched.beforeEnter(R, f) === !1) {
413
- const S = new URLSearchParams(Object.entries(f.query).flatMap(([K, $]) => Array.isArray($) ? $.map((x) => [K, x]) : [[K, $]])).toString(), m = S ? `?${S}` : "", C = f.hash ? `#${f.hash}` : "", E = s ? `#${f.path}${m}${C}` : `${n}${f.path}${m}${C}`;
414
- history.replaceState(b(), "", E);
415
- return;
416
- }
417
- for (const S of o) if (await S(R, f) === !1) {
418
- const m = new URLSearchParams(Object.entries(f.query).flatMap(([$, x]) => Array.isArray(x) ? x.map((z) => [$, z]) : [[$, x]])).toString(), C = m ? `?${m}` : "", E = f.hash ? `#${f.hash}` : "", K = s ? `#${f.path}${C}${E}` : `${n}${f.path}${C}${E}`;
419
- history.replaceState(b(), "", K);
420
- return;
421
- }
422
- v(h), h = i.state?.__bqScrollKey ?? d(), D(), g(h);
423
- for (const S of p) S(k.value, f);
424
- };
425
- window.addEventListener("popstate", U), D();
426
- const j = {
427
- push: (i) => H(i, "pushState"),
428
- replace: (i) => H(i, "replaceState"),
429
- back: () => history.back(),
430
- forward: () => history.forward(),
431
- go: (i) => history.go(i),
432
- beforeEach: (i) => (o.push(i), () => {
433
- const c = o.indexOf(i);
434
- c > -1 && o.splice(c, 1);
435
- }),
436
- afterEach: (i) => (p.push(i), () => {
437
- const c = p.indexOf(i);
438
- c > -1 && p.splice(c, 1);
439
- }),
440
- currentRoute: ot,
441
- routes: u,
442
- base: n,
443
- hash: s,
444
- destroy: () => {
445
- window.removeEventListener("popstate", U), o.length = 0, p.length = 0, l.clear(), A !== null && typeof history < "u" && "scrollRestoration" in history && (history.scrollRestoration = A), B(null);
446
- }
447
- };
448
- return B(j), j;
449
- }, M = L(() => k.value), gt = {
450
- route: M,
451
- path: L(() => M.value.path),
452
- params: L(() => M.value.params),
453
- query: L(() => M.value.query),
454
- hash: L(() => M.value.hash),
455
- matched: L(() => M.value.matched)
456
- }, qt = () => gt;
457
- export {
458
- Lt as a,
459
- ut as c,
460
- Ct as d,
461
- Q as f,
462
- xt as i,
463
- $t as l,
464
- Tt as n,
465
- Rt as o,
466
- ot as p,
467
- Kt as r,
468
- kt as s,
469
- qt as t,
470
- At as u
471
- };
472
-
473
- //# sourceMappingURL=router-BrthaP_z.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"router-BrthaP_z.js","names":[],"sources":["../src/router/state.ts","../src/router/navigation.ts","../src/router/bq-link.ts","../src/router/links.ts","../src/router/query.ts","../src/router/path-pattern.ts","../src/router/match.ts","../src/router/utils.ts","../src/router/router.ts","../src/router/use-route.ts"],"sourcesContent":["/**\n * Internal router state (active router and current route signal).\n * @module bquery/router\n */\n\nimport { computed, signal, type ReadonlySignal, type Signal } from '../reactive/index';\nimport type { Route, Router } from './types';\n\n// ============================================================================\n// Internal State\n// ============================================================================\n\n/** @internal */\nlet activeRouter: Router | null = null;\n\n/** @internal */\nexport const routeSignal: Signal<Route> = signal<Route>({\n path: '',\n params: {},\n query: {},\n matched: null,\n hash: '',\n});\n\n/**\n * Reactive signal containing the current route.\n *\n * @example\n * ```ts\n * import { currentRoute } from 'bquery/router';\n * import { effect } from 'bquery/reactive';\n *\n * effect(() => {\n * document.title = `Page: ${currentRoute.value.path}`;\n * });\n * ```\n */\nexport const currentRoute: ReadonlySignal<Route> = computed(() => routeSignal.value);\n\n/** @internal */\nexport const getActiveRouter = (): Router | null => activeRouter;\n\n/** @internal */\nexport const setActiveRouter = (router: Router | null): void => {\n activeRouter = router;\n};\n","/**\n * Navigation helpers and global router access.\n * @module bquery/router\n */\n\nimport { getActiveRouter } from './state';\n\n/**\n * Navigates to a new path.\n *\n * @param path - The path to navigate to\n * @param options - Navigation options\n *\n * @example\n * ```ts\n * import { navigate } from 'bquery/router';\n *\n * // Push to history\n * await navigate('/dashboard');\n *\n * // Replace current entry\n * await navigate('/login', { replace: true });\n * ```\n */\nexport const navigate = async (\n path: string,\n options: { replace?: boolean } = {}\n): Promise<void> => {\n const activeRouter = getActiveRouter();\n if (!activeRouter) {\n throw new Error('bQuery router: No router initialized. Call createRouter() first.');\n }\n\n await activeRouter[options.replace ? 'replace' : 'push'](path);\n};\n\n/**\n * Programmatically go back in history.\n *\n * @example\n * ```ts\n * import { back } from 'bquery/router';\n * back();\n * ```\n */\nexport const back = (): void => {\n const activeRouter = getActiveRouter();\n if (activeRouter) {\n activeRouter.back();\n } else {\n history.back();\n }\n};\n\n/**\n * Programmatically go forward in history.\n *\n * @example\n * ```ts\n * import { forward } from 'bquery/router';\n * forward();\n * ```\n */\nexport const forward = (): void => {\n const activeRouter = getActiveRouter();\n if (activeRouter) {\n activeRouter.forward();\n } else {\n history.forward();\n }\n};\n","/**\r\n * `<bq-link>` custom element for declarative SPA navigation.\r\n *\r\n * Exposes an accessible custom element that behaves like a link for\r\n * client-side routing. Automatically toggles an active class when the\r\n * target path matches the current route.\r\n *\r\n * @module bquery/router\r\n *\r\n * @example\r\n * ```html\r\n * <bq-link to=\"/\">Home</bq-link>\r\n * <bq-link to=\"/about\" active-class=\"selected\">About</bq-link>\r\n * <bq-link to=\"/settings\" replace exact>Settings</bq-link>\r\n * ```\r\n */\r\n\r\nimport { effect, type CleanupFn } from '../reactive/index';\r\nimport { navigate } from './navigation';\r\nimport { getActiveRouter, routeSignal } from './state';\r\n\r\n/**\r\n * Default CSS class applied when the link's target path is active.\r\n * @internal\r\n */\r\nconst DEFAULT_ACTIVE_CLASS = 'active';\r\n\r\n/** @internal */\r\nconst tokenizeClassNames = (value: string): string[] => {\r\n return value\r\n .split(/\\s+/)\r\n .map((token) => token.trim())\r\n .filter((token) => token.length > 0);\r\n};\r\n\r\n/** @internal SSR-safe base class for environments without HTMLElement. */\r\nconst BQ_LINK_BASE =\r\n typeof HTMLElement !== 'undefined' ? HTMLElement : (class {} as unknown as typeof HTMLElement);\r\n\r\n/**\r\n * `<bq-link>` — A navigation custom element for bQuery routers.\r\n *\r\n * Attributes:\r\n * - `to` — Target path (required). Example: `to=\"/dashboard\"`.\r\n * - `replace` — If present, replaces the current history entry instead of pushing.\r\n * - `exact` — If present, the active class is only applied on an exact path match.\r\n * - `active-class` — CSS class added when the route is active (default: `'active'`).\r\n *\r\n * The custom element itself acts as the interactive link target using\r\n * `role=\"link\"` and keyboard handling. It does not render a native `<a>`,\r\n * so browser-native link affordances like context-menu \"open in new tab\"\r\n * are not provided automatically.\r\n *\r\n * @example\r\n * ```ts\r\n * import { registerBqLink } from '@bquery/bquery/router';\r\n *\r\n * // Register the <bq-link> element (idempotent)\r\n * registerBqLink();\r\n *\r\n * // Then use in HTML:\r\n * // <bq-link to=\"/about\">About</bq-link>\r\n * ```\r\n */\r\nexport class BqLinkElement extends BQ_LINK_BASE {\r\n /** @internal */\r\n private _cleanup: CleanupFn | null = null;\r\n\r\n /** @internal */\r\n private _trackedActiveClasses = new Map<string, boolean>();\r\n\r\n static get observedAttributes(): string[] {\r\n return ['to', 'replace', 'exact', 'active-class'];\r\n }\r\n\r\n /** The target path for navigation. */\r\n get to(): string {\r\n const to = this.getAttribute('to');\r\n return to == null || to.trim() === '' ? '/' : to;\r\n }\r\n\r\n set to(value: string) {\r\n this.setAttribute('to', value);\r\n }\r\n\r\n /** Whether to replace the current history entry. */\r\n get replace(): boolean {\r\n return this.hasAttribute('replace');\r\n }\r\n\r\n set replace(value: boolean) {\r\n if (value) {\r\n this.setAttribute('replace', '');\r\n } else {\r\n this.removeAttribute('replace');\r\n }\r\n }\r\n\r\n /** Whether to match the path exactly for active class. */\r\n get exact(): boolean {\r\n return this.hasAttribute('exact');\r\n }\r\n\r\n set exact(value: boolean) {\r\n if (value) {\r\n this.setAttribute('exact', '');\r\n } else {\r\n this.removeAttribute('exact');\r\n }\r\n }\r\n\r\n /** CSS class applied when the route is active. */\r\n get activeClass(): string {\r\n return this.getAttribute('active-class') ?? DEFAULT_ACTIVE_CLASS;\r\n }\r\n\r\n set activeClass(value: string) {\r\n this.setAttribute('active-class', value);\r\n }\r\n\r\n /** @internal */\r\n connectedCallback(): void {\r\n // Set role for accessibility if not an <a> already\r\n if (!this.getAttribute('role')) {\r\n this.setAttribute('role', 'link');\r\n }\r\n\r\n // Make focusable if not already\r\n if (!this.hasAttribute('tabindex')) {\r\n this.setAttribute('tabindex', '0');\r\n }\r\n\r\n // Attach click handler\r\n this.addEventListener('click', this._handleClick);\r\n this.addEventListener('keydown', this._handleKeydown);\r\n\r\n // Set up reactive active-class tracking\r\n this._setupActiveTracking();\r\n }\r\n\r\n /** @internal */\r\n disconnectedCallback(): void {\r\n this.removeEventListener('click', this._handleClick);\r\n this.removeEventListener('keydown', this._handleKeydown);\r\n\r\n if (this._cleanup) {\r\n this._cleanup();\r\n this._cleanup = null;\r\n }\r\n\r\n this._clearTrackedActiveClasses();\r\n }\r\n\r\n /** @internal */\r\n attributeChangedCallback(name: string, _oldValue: string | null, _newValue: string | null): void {\r\n // Re-setup active tracking when relevant attributes change\r\n if (name === 'to' || name === 'exact' || name === 'active-class') {\r\n if (this.isConnected) {\r\n this._setupActiveTracking();\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Sets up the reactive effect that toggles the active CSS class\r\n * based on the current route.\r\n * @internal\r\n */\r\n private _setupActiveTracking(): void {\r\n // Clean up previous effect\r\n if (this._cleanup) {\r\n this._cleanup();\r\n this._cleanup = null;\r\n }\r\n\r\n this._clearTrackedActiveClasses();\r\n\r\n const targetPath = this.to;\r\n const exactMatch = this.exact;\r\n const cssClasses = tokenizeClassNames(this.activeClass);\r\n this._trackedActiveClasses = new Map(\r\n cssClasses.map((cssClass) => [cssClass, this.classList.contains(cssClass)])\r\n );\r\n\r\n this._cleanup = effect(() => {\r\n const current = routeSignal.value.path;\r\n const isMatch = exactMatch\r\n ? current === targetPath\r\n : targetPath === '/'\r\n ? current === '/'\r\n : current === targetPath ||\r\n current.startsWith(targetPath.endsWith('/') ? targetPath : targetPath + '/');\r\n\r\n for (const cssClass of cssClasses) {\r\n const wasPresentInitially = this._trackedActiveClasses.get(cssClass) ?? false;\r\n this.classList.toggle(cssClass, isMatch || wasPresentInitially);\r\n }\r\n\r\n // Update aria-current for accessibility\r\n if (isMatch) {\r\n this.setAttribute('aria-current', 'page');\r\n } else {\r\n this.removeAttribute('aria-current');\r\n }\r\n });\r\n }\r\n\r\n /** @internal */\r\n private _clearTrackedActiveClasses(): void {\r\n for (const [cssClass, wasPresentInitially] of this._trackedActiveClasses) {\r\n this.classList.toggle(cssClass, wasPresentInitially);\r\n }\r\n this._trackedActiveClasses.clear();\r\n }\r\n\r\n /**\r\n * Handles click events for SPA navigation.\r\n * @internal\r\n */\r\n private _handleClick = (e: Event): void => {\r\n if (!(e instanceof MouseEvent)) return;\r\n if (e.defaultPrevented) return;\r\n if (e.button !== 0) return; // Only left clicks\r\n if (e.ctrlKey || e.metaKey || e.shiftKey || e.altKey) return;\r\n\r\n e.preventDefault();\r\n this._navigate();\r\n };\r\n\r\n /**\r\n * Handles keyboard activation (Enter).\r\n * @internal\r\n */\r\n private _handleKeydown = (e: Event): void => {\r\n if (e instanceof KeyboardEvent && e.key === 'Enter') {\r\n e.preventDefault();\r\n this._navigate();\r\n }\r\n };\r\n\r\n /**\r\n * Performs the actual navigation.\r\n * @internal\r\n */\r\n private _navigate(): void {\r\n const targetPath = this.to;\r\n if (!targetPath) return;\r\n if (!getActiveRouter()) return;\r\n\r\n void navigate(targetPath, { replace: this.replace }).catch((err) => {\r\n console.error('bq-link: Navigation failed:', err);\r\n });\r\n }\r\n}\r\n\r\n/**\r\n * Registers the `<bq-link>` custom element.\r\n *\r\n * This function is idempotent — calling it multiple times is safe.\r\n * The element is registered under the tag name `bq-link`.\r\n *\r\n * @example\r\n * ```ts\r\n * import { registerBqLink } from '@bquery/bquery/router';\r\n *\r\n * registerBqLink();\r\n *\r\n * // Now use <bq-link to=\"/about\">About</bq-link> in HTML\r\n * ```\r\n */\r\nexport const registerBqLink = (): void => {\r\n if (\r\n typeof HTMLElement !== 'undefined' &&\r\n typeof customElements !== 'undefined' &&\r\n !customElements.get('bq-link')\r\n ) {\r\n customElements.define('bq-link', BqLinkElement);\r\n }\r\n};\r\n","/**\n * Link helpers for client-side navigation.\n * @module bquery/router\n */\n\nimport { getActiveRouter } from './state';\nimport { navigate } from './navigation';\n\n// ============================================================================\n// Router Link Helper\n// ============================================================================\n\n/**\n * Creates click handler for router links.\n * Attach to anchor elements to enable client-side navigation.\n *\n * @param path - Target path\n * @param options - Navigation options\n * @returns Click event handler\n *\n * @example\n * ```ts\n * import { link } from 'bquery/router';\n * import { $ } from 'bquery/core';\n *\n * $('#nav-home').on('click', link('/'));\n * $('#nav-about').on('click', link('/about'));\n * ```\n */\nexport const link = (path: string, options: { replace?: boolean } = {}): ((e: Event) => void) => {\n return (e: Event) => {\n e.preventDefault();\n void navigate(path, options).catch((err) => {\n console.error('Navigation failed:', err);\n });\n };\n};\n\n/**\n * Intercepts all link clicks within a container for client-side routing.\n * Only intercepts links with matching origins and no target attribute.\n *\n * @param container - The container element to intercept links in\n * @returns Cleanup function to remove the listener\n *\n * @example\n * ```ts\n * import { interceptLinks } from 'bquery/router';\n *\n * // Intercept all links in the app\n * const cleanup = interceptLinks(document.body);\n *\n * // Later, remove the interceptor\n * cleanup();\n * ```\n */\nexport const interceptLinks = (container?: Element): (() => void) => {\n // Provide safe default in DOM environments only\n const targetContainer = container ?? (typeof document !== 'undefined' ? document.body : null);\n if (!targetContainer) {\n // No container available (SSR or invalid input)\n return () => undefined;\n }\n\n const handler = (e: Event) => {\n // Only intercept standard left-clicks without modifier keys\n if (!(e instanceof MouseEvent)) return;\n if (e.defaultPrevented) return; // Already handled\n if (e.button !== 0) return; // Not left-click (middle-click opens new tab, right-click shows context menu)\n if (e.ctrlKey || e.metaKey || e.shiftKey || e.altKey) return; // Modifier keys (Ctrl/Cmd-click = new tab)\n\n // Guard against non-Element targets and non-DOM environments\n if (typeof Element === 'undefined' || !(e.target instanceof Element)) return;\n const target = e.target as HTMLElement;\n const anchor = target.closest('a');\n\n if (!anchor) return;\n\n // Cross-realm compatible anchor check: use owner document's constructor if available\n const anchorWindow = anchor.ownerDocument.defaultView;\n const AnchorConstructor = anchorWindow?.HTMLAnchorElement ?? HTMLAnchorElement;\n if (!(anchor instanceof AnchorConstructor)) return;\n\n if (anchor.target) return; // Has target attribute\n if (anchor.hasAttribute('download')) return;\n if (typeof window === 'undefined') return; // Non-window environment\n if (anchor.origin !== window.location.origin) return; // External link\n\n // Get active router config to handle base paths correctly.\n // If no router is active, proceed with no base/hash; navigate() will throw a\n // \"No router initialized\" error, which is caught and logged below.\n const router = getActiveRouter();\n if (!router) {\n // No active router - trigger navigate(), allowing its error to be logged here\n e.preventDefault();\n void navigate(anchor.pathname + anchor.search + anchor.hash).catch((err) => {\n console.error('Navigation failed:', err);\n });\n return;\n }\n\n const base = router.base;\n const useHash = router.hash;\n\n // Detect hash-routing mode: links written as href=\"#/page\"\n // In this case, anchor.hash contains the route path\n let path: string;\n if (useHash && anchor.hash && anchor.hash.startsWith('#/')) {\n // Hash-routing mode: extract path from the hash\n // e.g., href=\"#/page?foo=bar\" → path = \"/page?foo=bar\"\n path = anchor.hash.slice(1); // Remove leading #\n } else {\n // History mode: use pathname + search + hash\n // Strip base from pathname to avoid duplication (router.push() re-adds it)\n let pathname = anchor.pathname;\n if (base && base !== '/' && pathname.startsWith(base)) {\n pathname = pathname.slice(base.length) || '/';\n }\n path = pathname + anchor.search + anchor.hash;\n }\n\n e.preventDefault();\n void navigate(path).catch((err) => {\n console.error('Navigation failed:', err);\n });\n };\n\n targetContainer.addEventListener('click', handler);\n return () => targetContainer.removeEventListener('click', handler);\n};\n","/**\r\n * Query string helpers.\r\n * @module bquery/router\r\n */\r\n\r\nimport { isPrototypePollutionKey } from '../core/utils/object';\r\n\r\n/**\r\n * Parses query string into an object.\r\n * Single values are stored as strings, duplicate keys become arrays.\r\n * @internal\r\n *\r\n * @example\r\n * parseQuery('?foo=1') // { foo: '1' }\r\n * parseQuery('?tag=a&tag=b') // { tag: ['a', 'b'] }\r\n * parseQuery('?x=1&y=2&x=3') // { x: ['1', '3'], y: '2' }\r\n */\r\nexport const parseQuery = (search: string): Record<string, string | string[]> => {\r\n const query: Record<string, string | string[]> = {};\r\n const params = new URLSearchParams(search);\r\n\r\n params.forEach((value, key) => {\r\n if (isPrototypePollutionKey(key)) return;\r\n const existing = query[key];\r\n if (existing === undefined) {\r\n // First occurrence: store as string\r\n query[key] = value;\r\n } else if (Array.isArray(existing)) {\r\n // Already an array: append\r\n existing.push(value);\r\n } else {\r\n // Second occurrence: convert to array\r\n query[key] = [existing, value];\r\n }\r\n });\r\n\r\n return query;\r\n};\r\n","/**\r\n * Shared helpers for parsing route path params and constraints.\r\n * @internal\r\n */\r\n\r\n/** Validates whether a character can start a route param name. @internal */\r\nexport const isParamStart = (char: string | undefined): boolean =>\r\n char !== undefined &&\r\n ((char >= 'a' && char <= 'z') || (char >= 'A' && char <= 'Z') || char === '_');\r\n\r\n/** Validates whether a character can appear after the start of a route param name. @internal */\r\nexport const isParamChar = (char: string | undefined): boolean =>\r\n isParamStart(char) || (char !== undefined && char >= '0' && char <= '9');\r\n\r\n/** Reads a route param constraint while preserving escaped chars and nested groups. @internal */\r\nexport const readConstraint = (\r\n path: string,\r\n startIndex: number\r\n): { constraint: string; endIndex: number } | null => {\r\n let depth = 1;\r\n let constraint = '';\r\n let i = startIndex + 1;\r\n let inCharacterClass = false;\r\n\r\n while (i < path.length) {\r\n const char = path[i];\r\n\r\n if (char === '\\\\' && i + 1 < path.length) {\r\n constraint += char + path[i + 1];\r\n i += 2;\r\n continue;\r\n }\r\n\r\n if (char === '[' && !inCharacterClass) {\r\n inCharacterClass = true;\r\n } else if (char === ']' && inCharacterClass) {\r\n inCharacterClass = false;\r\n } else if (!inCharacterClass && char === '(') {\r\n depth++;\r\n } else if (!inCharacterClass && char === ')') {\r\n depth--;\r\n if (depth === 0) {\r\n return { constraint, endIndex: i + 1 };\r\n }\r\n }\r\n\r\n constraint += char;\r\n i++;\r\n }\r\n\r\n return null;\r\n};\r\n","/**\r\n * Route matching helpers.\r\n * @module bquery/router\r\n */\r\n\r\nimport { parseQuery } from './query';\r\nimport { getNormalizedRouteConstraint, getRouteConstraintRegex } from './constraints';\r\nimport { isParamChar, isParamStart, readConstraint } from './path-pattern';\r\nimport type { Route, RouteDefinition } from './types';\r\n\r\nconst readConstraintOrThrow = (\r\n path: string,\r\n startIndex: number\r\n): { constraint: string; endIndex: number } => {\r\n const parsedConstraint = readConstraint(path, startIndex);\r\n if (!parsedConstraint) {\r\n throw new Error(\r\n `bQuery router: Invalid route param constraint syntax in path \"${path}\" at index ${startIndex}.`\r\n );\r\n }\r\n return parsedConstraint;\r\n};\r\n\r\ntype RouteParamDescriptor = {\r\n name: string;\r\n constraint?: string;\r\n nextIndex: number;\r\n};\r\n\r\nconst validatedRoutePathCache = new Set<string>();\r\n\r\nconst readParamDescriptor = (path: string, index: number): RouteParamDescriptor | null => {\r\n if (path[index] !== ':' || !isParamStart(path[index + 1])) {\r\n return null;\r\n }\r\n\r\n let nameEnd = index + 2;\r\n while (nameEnd < path.length && isParamChar(path[nameEnd])) {\r\n nameEnd++;\r\n }\r\n\r\n let nextIndex = nameEnd;\r\n let constraint: string | undefined;\r\n\r\n if (path[nameEnd] === '(') {\r\n const parsedConstraint = readConstraintOrThrow(path, nameEnd);\r\n constraint = parsedConstraint.constraint;\r\n nextIndex = parsedConstraint.endIndex;\r\n }\r\n\r\n return {\r\n name: path.slice(index + 1, nameEnd),\r\n constraint,\r\n nextIndex,\r\n };\r\n};\r\n\r\nconst validateRoutePathPattern = (path: string): void => {\r\n if (validatedRoutePathCache.has(path)) {\r\n return;\r\n }\r\n\r\n for (let i = 0; i < path.length; ) {\r\n const char = path[i];\r\n\r\n if (char === ':' && isParamStart(path[i + 1])) {\r\n const param = readParamDescriptor(path, i);\r\n if (param?.constraint) {\r\n getNormalizedRouteConstraint(param.constraint);\r\n }\r\n i = param?.nextIndex ?? i + 1;\r\n continue;\r\n }\r\n\r\n i++;\r\n }\r\n\r\n validatedRoutePathCache.add(path);\r\n};\r\n\r\nconst findSegmentBoundary = (value: string, startIndex: number): number => {\r\n const slashIndex = value.indexOf('/', startIndex);\r\n return slashIndex === -1 ? value.length : slashIndex;\r\n};\r\n\r\nconst readNextStaticChunk = (path: string, startIndex: number): string => {\r\n let chunkEnd = startIndex;\r\n\r\n while (chunkEnd < path.length) {\r\n if (path[chunkEnd] === '*') {\r\n break;\r\n }\r\n\r\n if (path[chunkEnd] === ':' && isParamStart(path[chunkEnd + 1])) {\r\n break;\r\n }\r\n\r\n chunkEnd++;\r\n }\r\n\r\n return path.slice(startIndex, chunkEnd);\r\n};\r\n\r\nconst findAnchoredCandidateEnds = (\r\n actualPath: string,\r\n startIndex: number,\r\n limit: number,\r\n nextStaticChunk: string\r\n): number[] => {\r\n const candidates: number[] = [];\r\n let searchIndex = startIndex;\r\n\r\n while (searchIndex <= limit) {\r\n const candidateEnd = actualPath.indexOf(nextStaticChunk, searchIndex);\r\n if (candidateEnd === -1 || candidateEnd > limit) {\r\n break;\r\n }\r\n\r\n candidates.push(candidateEnd);\r\n searchIndex = candidateEnd + 1;\r\n }\r\n\r\n return candidates.reverse();\r\n};\r\n\r\nconst matchPathPattern = (routePath: string, actualPath: string): Record<string, string> | null => {\r\n // Memoization keeps wildcard/param backtracking linear for repeated subproblems\r\n // within a single route/path match attempt.\r\n const memo = new Map<string, Record<string, string> | null>();\r\n\r\n const matchFrom = (routeIndex: number, pathIndex: number): Record<string, string> | null => {\r\n const memoKey = `${routeIndex}:${pathIndex}`;\r\n if (memo.has(memoKey)) {\r\n return memo.get(memoKey) ?? null;\r\n }\r\n\r\n if (routeIndex === routePath.length) {\r\n const result = pathIndex === actualPath.length ? {} : null;\r\n memo.set(memoKey, result);\r\n return result;\r\n }\r\n\r\n const routeChar = routePath[routeIndex];\r\n\r\n if (routeChar === '*') {\r\n if (routeIndex === routePath.length - 1) {\r\n const result = {};\r\n memo.set(memoKey, result);\r\n return result;\r\n }\r\n\r\n const nextStaticChunk = readNextStaticChunk(routePath, routeIndex + 1);\r\n const anchoredCandidateEnds =\r\n nextStaticChunk.length > 0\r\n ? findAnchoredCandidateEnds(actualPath, pathIndex, actualPath.length, nextStaticChunk)\r\n : null;\r\n\r\n const iterateCandidateEnds = anchoredCandidateEnds\r\n ? (callback: (candidateEnd: number) => Record<string, string> | null) => {\r\n for (const candidateEnd of anchoredCandidateEnds) {\r\n const result = callback(candidateEnd);\r\n if (result) {\r\n return result;\r\n }\r\n }\r\n return null;\r\n }\r\n : (callback: (candidateEnd: number) => Record<string, string> | null) => {\r\n for (let candidateEnd = actualPath.length; candidateEnd >= pathIndex; candidateEnd--) {\r\n const result = callback(candidateEnd);\r\n if (result) {\r\n return result;\r\n }\r\n }\r\n return null;\r\n };\r\n\r\n const wildcardMatch = iterateCandidateEnds((candidateEnd) => {\r\n const suffixMatch = matchFrom(routeIndex + 1, candidateEnd);\r\n if (suffixMatch) {\r\n memo.set(memoKey, suffixMatch);\r\n return suffixMatch;\r\n }\r\n return null;\r\n });\r\n\r\n if (wildcardMatch) {\r\n return wildcardMatch;\r\n }\r\n\r\n memo.set(memoKey, null);\r\n return null;\r\n }\r\n\r\n const param = readParamDescriptor(routePath, routeIndex);\r\n if (param) {\r\n const constraintRegex = param.constraint\r\n ? getRouteConstraintRegex(param.constraint)\r\n : undefined;\r\n const candidateLimit = param.constraint\r\n ? actualPath.length\r\n : findSegmentBoundary(actualPath, pathIndex);\r\n const nextStaticChunk = readNextStaticChunk(routePath, param.nextIndex);\r\n const anchoredCandidateEnds =\r\n nextStaticChunk.length > 0\r\n ? findAnchoredCandidateEnds(actualPath, pathIndex, candidateLimit, nextStaticChunk)\r\n : null;\r\n\r\n const iterateCandidateEnds = anchoredCandidateEnds\r\n ? (callback: (candidateEnd: number) => Record<string, string> | null) => {\r\n for (const candidateEnd of anchoredCandidateEnds) {\r\n if (candidateEnd <= pathIndex) {\r\n continue;\r\n }\r\n const result = callback(candidateEnd);\r\n if (result) {\r\n return result;\r\n }\r\n }\r\n return null;\r\n }\r\n : (callback: (candidateEnd: number) => Record<string, string> | null) => {\r\n for (let candidateEnd = candidateLimit; candidateEnd > pathIndex; candidateEnd--) {\r\n const result = callback(candidateEnd);\r\n if (result) {\r\n return result;\r\n }\r\n }\r\n return null;\r\n };\r\n\r\n const paramMatch = iterateCandidateEnds((candidateEnd) => {\r\n const candidateValue = actualPath.slice(pathIndex, candidateEnd);\r\n\r\n if (constraintRegex) {\r\n if (!constraintRegex.test(candidateValue)) {\r\n return null;\r\n }\r\n }\r\n\r\n const suffixMatch = matchFrom(param.nextIndex, candidateEnd);\r\n if (suffixMatch) {\r\n const result = {\r\n [param.name]: candidateValue,\r\n ...suffixMatch,\r\n };\r\n memo.set(memoKey, result);\r\n return result;\r\n }\r\n return null;\r\n });\r\n\r\n if (paramMatch) {\r\n return paramMatch;\r\n }\r\n\r\n memo.set(memoKey, null);\r\n return null;\r\n }\r\n\r\n if (pathIndex >= actualPath.length || routeChar !== actualPath[pathIndex]) {\r\n memo.set(memoKey, null);\r\n return null;\r\n }\r\n\r\n const result = matchFrom(routeIndex + 1, pathIndex + 1);\r\n memo.set(memoKey, result);\r\n return result;\r\n };\r\n\r\n return matchFrom(0, 0);\r\n};\r\n\r\n/**\r\n * Matches a path against route definitions and extracts params.\r\n * @internal\r\n */\r\nexport const matchRoute = (\r\n path: string,\r\n routes: RouteDefinition[]\r\n): { matched: RouteDefinition; params: Record<string, string> } | null => {\r\n for (const route of routes) {\r\n validateRoutePathPattern(route.path);\r\n const params = matchPathPattern(route.path, path);\r\n if (params) {\r\n return { matched: route, params };\r\n }\r\n }\r\n\r\n return null;\r\n};\r\n\r\n/**\r\n * Creates a Route object from the current URL.\r\n * @internal\r\n */\r\nexport const createRoute = (\r\n pathname: string,\r\n search: string,\r\n hash: string,\r\n routes: RouteDefinition[]\r\n): Route => {\r\n const result = matchRoute(pathname, routes);\r\n\r\n return {\r\n path: pathname,\r\n params: result?.params ?? {},\r\n query: parseQuery(search),\r\n matched: result?.matched ?? null,\r\n hash: hash.replace(/^#/, ''),\r\n };\r\n};\r\n","/**\r\n * Router utilities.\r\n * @module bquery/router\r\n */\r\n\r\nimport { computed, type ReadonlySignal } from '../reactive/index';\r\nimport { getRouteConstraintRegex } from './constraints';\r\nimport { isParamChar, isParamStart, readConstraint } from './path-pattern';\r\nimport { getActiveRouter, routeSignal } from './state';\r\nimport type { RouteDefinition } from './types';\r\n\r\n// ============================================================================\r\n// Utilities\r\n// ============================================================================\r\n\r\n/**\r\n * Flattens nested routes into a single array with full paths.\r\n * Does NOT include the router base - base is only for browser history.\r\n * @internal\r\n */\r\nexport const flattenRoutes = (routes: RouteDefinition[], parentPath = ''): RouteDefinition[] => {\r\n const result: RouteDefinition[] = [];\r\n\r\n for (const route of routes) {\r\n const fullPath = route.path === '*' ? '*' : `${parentPath}${route.path}`.replace(/\\/+/g, '/');\r\n\r\n result.push({\r\n ...route,\r\n path: fullPath,\r\n });\r\n\r\n if (route.children) {\r\n result.push(...flattenRoutes(route.children, fullPath));\r\n }\r\n }\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Resolves a route by name and params.\r\n *\r\n * @param name - The route name\r\n * @param params - Route params to interpolate\r\n * @returns The resolved path\r\n * @throws {Error} If no router is initialized, the route name is unknown,\r\n * a required path param is missing from `params`, a param value does not satisfy\r\n * its route regex constraint, or a route param constraint has invalid syntax\r\n *\r\n * @example\r\n * ```ts\r\n * import { resolve } from 'bquery/router';\r\n *\r\n * const path = resolve('user', { id: '42' });\r\n * // Returns '/user/42' if route is defined as { name: 'user', path: '/user/:id' }\r\n * ```\r\n */\r\nexport const resolve = (name: string, params: Record<string, string> = {}): string => {\r\n const activeRouter = getActiveRouter();\r\n if (!activeRouter) {\r\n throw new Error('bQuery router: No router initialized.');\r\n }\r\n\r\n const route = activeRouter.routes.find((r) => r.name === name);\r\n if (!route) {\r\n throw new Error(`bQuery router: Route \"${name}\" not found.`);\r\n }\r\n\r\n let path = '';\r\n for (let i = 0; i < route.path.length; ) {\r\n if (route.path[i] === ':' && isParamStart(route.path[i + 1])) {\r\n let nameEnd = i + 2;\r\n while (nameEnd < route.path.length && isParamChar(route.path[nameEnd])) {\r\n nameEnd++;\r\n }\r\n\r\n let nextIndex = nameEnd;\r\n let constraint: string | null = null;\r\n if (route.path[nameEnd] === '(') {\r\n const parsedConstraint = readConstraint(route.path, nameEnd);\r\n if (!parsedConstraint) {\r\n throw new Error(\r\n `bQuery router: Invalid constraint syntax in path \"${route.path}\" for route \"${name}\".`\r\n );\r\n }\r\n constraint = parsedConstraint.constraint;\r\n nextIndex = parsedConstraint.endIndex;\r\n }\r\n\r\n const key = route.path.slice(i + 1, nameEnd);\r\n const value = params[key];\r\n if (value === undefined) {\r\n throw new Error(`bQuery router: Missing required param \"${key}\" for route \"${name}\".`);\r\n }\r\n if (constraint && !getRouteConstraintRegex(constraint).test(value)) {\r\n throw new Error(\r\n `bQuery router: Param \"${key}\" with value \"${value}\" does not satisfy the route constraint \"${constraint}\" for route \"${name}\".`\r\n );\r\n }\r\n\r\n path += encodeURIComponent(value);\r\n i = nextIndex;\r\n continue;\r\n }\r\n\r\n path += route.path[i];\r\n i++;\r\n }\r\n\r\n return path;\r\n};\r\n\r\n/**\r\n * Checks if a path matches the current route.\r\n *\r\n * @param path - Path to check\r\n * @param exact - Whether to match exactly (default: false)\r\n * @returns True if the path matches\r\n *\r\n * @example\r\n * ```ts\r\n * import { isActive } from 'bquery/router';\r\n *\r\n * if (isActive('/dashboard')) {\r\n * // Highlight nav item\r\n * }\r\n * ```\r\n */\r\nexport const isActive = (path: string, exact = false): boolean => {\r\n const current = routeSignal.value.path;\r\n return exact ? current === path : current.startsWith(path);\r\n};\r\n\r\n/**\r\n * Creates a computed signal that checks if a path is active.\r\n *\r\n * @param path - Path to check\r\n * @param exact - Whether to match exactly\r\n * @returns A reactive signal\r\n *\r\n * @example\r\n * ```ts\r\n * import { isActiveSignal } from 'bquery/router';\r\n * import { effect } from 'bquery/reactive';\r\n *\r\n * const dashboardActive = isActiveSignal('/dashboard');\r\n * effect(() => {\r\n * navItem.classList.toggle('active', dashboardActive.value);\r\n * });\r\n * ```\r\n */\r\nexport const isActiveSignal = (path: string, exact = false): ReadonlySignal<boolean> => {\r\n return computed(() => {\r\n const current = routeSignal.value.path;\r\n return exact ? current === path : current.startsWith(path);\r\n });\r\n};\r\n","/**\r\n * Router creation and lifecycle management.\r\n * @module bquery/router\r\n */\r\n\r\nimport { isPrototypePollutionKey } from '../core/utils/object';\r\nimport { createRoute } from './match';\r\nimport { currentRoute, getActiveRouter, routeSignal, setActiveRouter } from './state';\r\nimport type { NavigationGuard, Route, Router, RouterOptions } from './types';\r\nimport { flattenRoutes } from './utils';\r\n\r\n// ============================================================================\r\n// Router Creation\r\n// ============================================================================\r\n\r\nconst MAX_SCROLL_POSITION_ENTRIES = 100;\r\n\r\nconst sanitizeHistoryState = (state: Record<string, unknown>): Record<string, unknown> => {\r\n const sanitized: Record<string, unknown> = {};\r\n\r\n for (const [key, value] of Object.entries(state)) {\r\n if (isPrototypePollutionKey(key)) continue;\r\n sanitized[key] = value;\r\n }\r\n\r\n return sanitized;\r\n};\r\n\r\n/**\r\n * Creates and initializes a router instance.\r\n *\r\n * @param options - Router configuration\r\n * @returns The router instance\r\n *\r\n * @example\r\n * ```ts\r\n * import { createRouter } from 'bquery/router';\r\n *\r\n * const router = createRouter({\r\n * routes: [\r\n * { path: '/', component: () => import('./pages/Home') },\r\n * { path: '/about', component: () => import('./pages/About') },\r\n * { path: '/user/:id(\\\\d+)', component: () => import('./pages/User') },\r\n * { path: '/old-page', redirectTo: '/new-page' },\r\n * { path: '*', component: () => import('./pages/NotFound') },\r\n * ],\r\n * base: '/app',\r\n * scrollRestoration: true,\r\n * });\r\n *\r\n * router.beforeEach((to, from) => {\r\n * if (to.path === '/admin' && !isAuthenticated()) {\r\n * return false; // Cancel navigation\r\n * }\r\n * });\r\n * ```\r\n */\r\nexport const createRouter = (options: RouterOptions): Router => {\r\n // Clean up any existing router to prevent guard leakage\r\n const existingRouter = getActiveRouter();\r\n if (existingRouter) {\r\n existingRouter.destroy();\r\n }\r\n\r\n const { routes, base = '', hash: useHash = false, scrollRestoration = false } = options;\r\n\r\n // Instance-specific guards and hooks (not shared globally)\r\n const beforeGuards: NavigationGuard[] = [];\r\n const afterHooks: Array<(to: Route, from: Route) => void> = [];\r\n\r\n // Flatten nested routes (base-relative, not including the base path)\r\n const flatRoutes = flattenRoutes(routes);\r\n\r\n // Scroll position storage keyed by history state id\r\n const scrollPositions = new Map<string, { x: number; y: number }>();\r\n let currentScrollKey = '0';\r\n let scrollKeyCounter = 0;\r\n let previousScrollRestoration: History['scrollRestoration'] | null = null;\r\n\r\n // Enable manual scroll restoration if scrollRestoration is configured\r\n if (scrollRestoration && typeof history !== 'undefined' && 'scrollRestoration' in history) {\r\n previousScrollRestoration = history.scrollRestoration;\r\n if (history.scrollRestoration !== 'manual') {\r\n history.scrollRestoration = 'manual';\r\n }\r\n\r\n const state =\r\n history.state && typeof history.state === 'object'\r\n ? (history.state as Record<string, unknown>)\r\n : {};\r\n\r\n if (typeof state.__bqScrollKey !== 'string') {\r\n const currentUrl = useHash\r\n ? window.location.hash || '#/'\r\n : `${window.location.pathname}${window.location.search}${window.location.hash}`;\r\n history.replaceState({ ...state, __bqScrollKey: currentScrollKey }, '', currentUrl);\r\n }\r\n }\r\n\r\n /**\r\n * Generates a unique key for the current history entry.\r\n * @internal\r\n */\r\n const getScrollKey = (): string => {\r\n return (history.state && history.state.__bqScrollKey) || currentScrollKey;\r\n };\r\n\r\n /**\r\n * Generates a unique key for a new history entry.\r\n * @internal\r\n */\r\n const createScrollKey = (): string => `${Date.now()}-${scrollKeyCounter++}`;\r\n\r\n /**\r\n * Saves current scroll position for the current history entry.\r\n * @internal\r\n */\r\n const saveScrollPosition = (key = getScrollKey()): void => {\r\n if (!scrollRestoration) return;\r\n if (scrollPositions.has(key)) {\r\n // Refresh the insertion order so pruning behaves like an LRU cache.\r\n scrollPositions.delete(key);\r\n }\r\n scrollPositions.set(key, { x: window.scrollX, y: window.scrollY });\r\n while (scrollPositions.size > MAX_SCROLL_POSITION_ENTRIES) {\r\n const oldestKey = scrollPositions.keys().next().value as string | undefined;\r\n if (oldestKey === undefined) {\r\n break;\r\n }\r\n scrollPositions.delete(oldestKey);\r\n }\r\n };\r\n\r\n /**\r\n * Restores scroll position for the current history entry.\r\n * @internal\r\n */\r\n const restoreScrollPosition = (key = getScrollKey()): void => {\r\n if (!scrollRestoration) return;\r\n const pos = scrollPositions.get(key);\r\n if (pos) {\r\n window.scrollTo(pos.x, pos.y);\r\n } else {\r\n window.scrollTo(0, 0);\r\n }\r\n };\r\n\r\n /**\r\n * Builds history state for canceled navigations without dropping\r\n * the scroll restoration key for the current entry.\r\n * @internal\r\n */\r\n const getRestoreHistoryState = (): Record<string, unknown> => {\r\n const state =\r\n history.state && typeof history.state === 'object'\r\n ? { ...(history.state as Record<string, unknown>) }\r\n : {};\r\n\r\n if (scrollRestoration) {\r\n state.__bqScrollKey = currentScrollKey;\r\n }\r\n\r\n return state;\r\n };\r\n\r\n /**\r\n * Gets the current path from the URL.\r\n */\r\n const getCurrentPath = (): { pathname: string; search: string; hash: string } => {\r\n if (useHash) {\r\n const hashPath = window.location.hash.slice(1) || '/';\r\n // In hash routing, URL structure is #/path?query#fragment\r\n // Extract hash fragment first (after the second #)\r\n const [pathWithQuery, hashPart = ''] = hashPath.split('#');\r\n // Then extract query from the path\r\n const [pathname, search = ''] = pathWithQuery.split('?');\r\n return {\r\n pathname,\r\n search: search ? `?${search}` : '',\r\n hash: hashPart ? `#${hashPart}` : '',\r\n };\r\n }\r\n\r\n let pathname = window.location.pathname;\r\n if (base && (pathname === base || pathname.startsWith(base + '/'))) {\r\n pathname = pathname.slice(base.length) || '/';\r\n }\r\n\r\n return {\r\n pathname,\r\n search: window.location.search,\r\n hash: window.location.hash,\r\n };\r\n };\r\n\r\n /**\r\n * Updates the route signal with current URL state.\r\n */\r\n const syncRoute = (): void => {\r\n const { pathname, search, hash } = getCurrentPath();\r\n const newRoute = createRoute(pathname, search, hash, flatRoutes);\r\n routeSignal.value = newRoute;\r\n };\r\n\r\n /**\r\n * Performs navigation with guards.\r\n */\r\n const performNavigation = async (\r\n path: string,\r\n method: 'pushState' | 'replaceState',\r\n visitedPaths: Set<string> = new Set()\r\n ): Promise<void> => {\r\n const { pathname, search, hash } = getCurrentPath();\r\n const from = createRoute(pathname, search, hash, flatRoutes);\r\n\r\n // Parse the target path\r\n const url = new URL(path, window.location.origin);\r\n const resolvedPath = `${url.pathname}${url.search}${url.hash}`;\r\n if (visitedPaths.has(resolvedPath)) {\r\n throw new Error(`bQuery router: redirect loop detected for path \"${resolvedPath}\"`);\r\n }\r\n visitedPaths.add(resolvedPath);\r\n const to = createRoute(url.pathname, url.search, url.hash, flatRoutes);\r\n\r\n // Check for redirectTo on the matched route\r\n if (to.matched?.redirectTo) {\r\n // Navigate to the redirect target instead\r\n await performNavigation(to.matched.redirectTo, method, visitedPaths);\r\n return;\r\n }\r\n\r\n // Run route-level beforeEnter guard\r\n if (to.matched?.beforeEnter) {\r\n const result = await to.matched.beforeEnter(to, from);\r\n if (result === false) {\r\n return; // Cancel navigation\r\n }\r\n }\r\n\r\n // Run beforeEach guards\r\n for (const guard of beforeGuards) {\r\n const result = await guard(to, from);\r\n if (result === false) {\r\n return; // Cancel navigation\r\n }\r\n }\r\n\r\n // Save scroll position before navigation\r\n saveScrollPosition();\r\n\r\n // Update browser history\r\n const existingScrollKey = scrollRestoration ? getScrollKey() : undefined;\r\n const scrollKey =\r\n method === 'replaceState' && existingScrollKey ? existingScrollKey : createScrollKey();\r\n const fullPath = useHash ? `#${path}` : `${base}${path}`;\r\n const baseState =\r\n scrollRestoration && history.state && typeof history.state === 'object'\r\n ? sanitizeHistoryState(history.state as Record<string, unknown>)\r\n : {};\r\n const state = scrollRestoration ? { ...baseState, __bqScrollKey: scrollKey } : {};\r\n history[method](state, '', fullPath);\r\n currentScrollKey = scrollKey;\r\n\r\n // Update route signal\r\n syncRoute();\r\n\r\n // Scroll to top on push navigation\r\n if (scrollRestoration && method === 'pushState') {\r\n window.scrollTo(0, 0);\r\n }\r\n\r\n // Run afterEach hooks\r\n for (const hook of afterHooks) {\r\n hook(routeSignal.value, from);\r\n }\r\n };\r\n\r\n /**\r\n * Handle popstate events (back/forward).\r\n */\r\n const handlePopState = async (event: PopStateEvent): Promise<void> => {\r\n const { pathname, search, hash } = getCurrentPath();\r\n const from = routeSignal.value;\r\n const to = createRoute(pathname, search, hash, flatRoutes);\r\n\r\n // Check for redirectTo on the matched route\r\n if (to.matched?.redirectTo) {\r\n await performNavigation(to.matched.redirectTo, 'replaceState');\r\n return;\r\n }\r\n\r\n // Run route-level beforeEnter guard\r\n if (to.matched?.beforeEnter) {\r\n const result = await to.matched.beforeEnter(to, from);\r\n if (result === false) {\r\n // Restore previous state with full URL (including query/hash)\r\n const queryString = new URLSearchParams(\r\n Object.entries(from.query).flatMap(([key, value]) =>\r\n Array.isArray(value) ? value.map((v) => [key, v]) : [[key, value]]\r\n )\r\n ).toString();\r\n const searchStr = queryString ? `?${queryString}` : '';\r\n const hashStr = from.hash ? `#${from.hash}` : '';\r\n const restorePath = useHash\r\n ? `#${from.path}${searchStr}${hashStr}`\r\n : `${base}${from.path}${searchStr}${hashStr}`;\r\n history.replaceState(getRestoreHistoryState(), '', restorePath);\r\n return;\r\n }\r\n }\r\n\r\n // Run beforeEach guards (supports async guards)\r\n for (const guard of beforeGuards) {\r\n const result = await guard(to, from);\r\n if (result === false) {\r\n // Restore previous state with full URL (including query/hash)\r\n const queryString = new URLSearchParams(\r\n Object.entries(from.query).flatMap(([key, value]) =>\r\n Array.isArray(value) ? value.map((v) => [key, v]) : [[key, value]]\r\n )\r\n ).toString();\r\n const search = queryString ? `?${queryString}` : '';\r\n const hash = from.hash ? `#${from.hash}` : '';\r\n const restorePath = useHash\r\n ? `#${from.path}${search}${hash}`\r\n : `${base}${from.path}${search}${hash}`;\r\n history.replaceState(getRestoreHistoryState(), '', restorePath);\r\n return;\r\n }\r\n }\r\n\r\n // Save scroll position of the page we're leaving\r\n saveScrollPosition(currentScrollKey);\r\n\r\n // Update scroll key from history state\r\n currentScrollKey =\r\n (event.state as { __bqScrollKey?: string } | null)?.__bqScrollKey ?? getScrollKey();\r\n\r\n syncRoute();\r\n\r\n // Restore scroll position for the entry we're navigating to\r\n restoreScrollPosition(currentScrollKey);\r\n\r\n for (const hook of afterHooks) {\r\n hook(routeSignal.value, from);\r\n }\r\n };\r\n\r\n // Attach popstate listener\r\n window.addEventListener('popstate', handlePopState);\r\n\r\n // Initialize route\r\n syncRoute();\r\n\r\n const router: Router = {\r\n push: (path: string) => performNavigation(path, 'pushState'),\r\n replace: (path: string) => performNavigation(path, 'replaceState'),\r\n back: () => history.back(),\r\n forward: () => history.forward(),\r\n go: (delta: number) => history.go(delta),\r\n\r\n beforeEach: (guard: NavigationGuard) => {\r\n beforeGuards.push(guard);\r\n return () => {\r\n const index = beforeGuards.indexOf(guard);\r\n if (index > -1) beforeGuards.splice(index, 1);\r\n };\r\n },\r\n\r\n afterEach: (hook: (to: Route, from: Route) => void) => {\r\n afterHooks.push(hook);\r\n return () => {\r\n const index = afterHooks.indexOf(hook);\r\n if (index > -1) afterHooks.splice(index, 1);\r\n };\r\n },\r\n\r\n currentRoute,\r\n routes: flatRoutes,\r\n base,\r\n hash: useHash,\r\n\r\n destroy: () => {\r\n window.removeEventListener('popstate', handlePopState);\r\n beforeGuards.length = 0;\r\n afterHooks.length = 0;\r\n scrollPositions.clear();\r\n // Restore the previous scroll restoration mode on destroy\r\n if (\r\n previousScrollRestoration !== null &&\r\n typeof history !== 'undefined' &&\r\n 'scrollRestoration' in history\r\n ) {\r\n history.scrollRestoration = previousScrollRestoration;\r\n }\r\n setActiveRouter(null);\r\n },\r\n };\r\n\r\n setActiveRouter(router);\r\n return router;\r\n};\r\n","/**\r\n * Reactive route composable.\r\n * @module bquery/router\r\n */\r\n\r\nimport { computed, type ReadonlySignal } from '../reactive/index';\r\nimport { routeSignal } from './state';\r\nimport type { Route, RouteDefinition } from './types';\r\n\r\n// ============================================================================\r\n// useRoute Composable\r\n// ============================================================================\r\n\r\n/**\r\n * Return type for {@link useRoute}.\r\n * Provides reactive access to individual route properties.\r\n */\r\nexport type UseRouteReturn = {\r\n /** Full reactive route object */\r\n route: ReadonlySignal<Route>;\r\n /** Reactive current path */\r\n path: ReadonlySignal<string>;\r\n /** Reactive route params */\r\n params: ReadonlySignal<Record<string, string>>;\r\n /** Reactive query params */\r\n query: ReadonlySignal<Record<string, string | string[]>>;\r\n /** Reactive hash fragment (without #) */\r\n hash: ReadonlySignal<string>;\r\n /** Reactive matched route definition */\r\n matched: ReadonlySignal<RouteDefinition | null>;\r\n};\r\n\r\nconst route = computed(() => routeSignal.value);\r\nconst path = computed(() => route.value.path);\r\nconst params = computed(() => route.value.params);\r\nconst query = computed(() => route.value.query);\r\nconst hash = computed(() => route.value.hash);\r\nconst matched = computed(() => route.value.matched);\r\n\r\nconst routeHandle: UseRouteReturn = { route, path, params, query, hash, matched };\r\n\r\n/**\r\n * Returns reactive access to the current route, params, query, and hash.\r\n *\r\n * Each property is a readonly computed signal that updates automatically\r\n * when the route changes. This is useful for fine-grained reactivity\r\n * where you only need to subscribe to specific route parts.\r\n *\r\n * @returns An object with reactive route properties\r\n *\r\n * @example\r\n * ```ts\r\n * import { useRoute } from '@bquery/bquery/router';\r\n * import { effect } from '@bquery/bquery/reactive';\r\n *\r\n * const { path, params, query, hash } = useRoute();\r\n *\r\n * effect(() => {\r\n * console.log('Path:', path.value);\r\n * console.log('Params:', params.value);\r\n * console.log('Query:', query.value);\r\n * console.log('Hash:', hash.value);\r\n * });\r\n * ```\r\n */\r\nexport const useRoute = (): UseRouteReturn => {\r\n return routeHandle;\r\n};\r\n"],"mappings":"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"}