@multiplatform.one/router 6.1.0 → 6.3.0

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 (106) hide show
  1. package/README.md +51 -0
  2. package/dist/cjs/hooks/useUrlState.cjs +30 -9
  3. package/dist/cjs/hooks/useUrlState.native.js +32 -9
  4. package/dist/cjs/hooks/useUrlState.native.js.map +1 -1
  5. package/dist/cjs/seam/DomNavigationHost.cjs +122 -0
  6. package/dist/cjs/seam/DomNavigationHost.native.js +186 -0
  7. package/dist/cjs/seam/DomNavigationHost.native.js.map +1 -0
  8. package/dist/cjs/seam/index.cjs +47 -0
  9. package/dist/cjs/seam/index.native.js +50 -0
  10. package/dist/cjs/seam/index.native.js.map +1 -0
  11. package/dist/cjs/seam/navigator.cjs +309 -0
  12. package/dist/cjs/seam/navigator.native.js +479 -0
  13. package/dist/cjs/seam/navigator.native.js.map +1 -0
  14. package/dist/cjs/seam/oneAdapter.cjs +128 -0
  15. package/dist/cjs/seam/oneAdapter.native.js +141 -0
  16. package/dist/cjs/seam/oneAdapter.native.js.map +1 -0
  17. package/dist/esm/hooks/useUrlState.mjs +31 -10
  18. package/dist/esm/hooks/useUrlState.mjs.map +1 -1
  19. package/dist/esm/hooks/useUrlState.native.js +33 -10
  20. package/dist/esm/hooks/useUrlState.native.js.map +1 -1
  21. package/dist/esm/seam/DomNavigationHost.mjs +96 -0
  22. package/dist/esm/seam/DomNavigationHost.mjs.map +1 -0
  23. package/dist/esm/seam/DomNavigationHost.native.js +157 -0
  24. package/dist/esm/seam/DomNavigationHost.native.js.map +1 -0
  25. package/dist/esm/seam/index.mjs +5 -0
  26. package/dist/esm/seam/index.mjs.map +1 -0
  27. package/dist/esm/seam/index.native.js +5 -0
  28. package/dist/esm/seam/index.native.js.map +1 -0
  29. package/dist/esm/seam/navigator.mjs +279 -0
  30. package/dist/esm/seam/navigator.mjs.map +1 -0
  31. package/dist/esm/seam/navigator.native.js +446 -0
  32. package/dist/esm/seam/navigator.native.js.map +1 -0
  33. package/dist/esm/seam/oneAdapter.mjs +90 -0
  34. package/dist/esm/seam/oneAdapter.mjs.map +1 -0
  35. package/dist/esm/seam/oneAdapter.native.js +100 -0
  36. package/dist/esm/seam/oneAdapter.native.js.map +1 -0
  37. package/dist/jsx/hooks/useUrlState.mjs +31 -10
  38. package/dist/jsx/hooks/useUrlState.mjs.map +1 -1
  39. package/dist/jsx/hooks/useUrlState.native.js +32 -9
  40. package/dist/jsx/hooks/useUrlState.native.js.map +1 -1
  41. package/dist/jsx/seam/DomNavigationHost.mjs +96 -0
  42. package/dist/jsx/seam/DomNavigationHost.mjs.map +1 -0
  43. package/dist/jsx/seam/DomNavigationHost.native.js +186 -0
  44. package/dist/jsx/seam/DomNavigationHost.native.js.map +1 -0
  45. package/dist/jsx/seam/index.mjs +5 -0
  46. package/dist/jsx/seam/index.mjs.map +1 -0
  47. package/dist/jsx/seam/index.native.js +50 -0
  48. package/dist/jsx/seam/index.native.js.map +1 -0
  49. package/dist/jsx/seam/navigator.mjs +279 -0
  50. package/dist/jsx/seam/navigator.mjs.map +1 -0
  51. package/dist/jsx/seam/navigator.native.js +479 -0
  52. package/dist/jsx/seam/navigator.native.js.map +1 -0
  53. package/dist/jsx/seam/oneAdapter.mjs +90 -0
  54. package/dist/jsx/seam/oneAdapter.mjs.map +1 -0
  55. package/dist/jsx/seam/oneAdapter.native.js +141 -0
  56. package/dist/jsx/seam/oneAdapter.native.js.map +1 -0
  57. package/package.json +26 -9
  58. package/src/hooks/urlStateEdges.spec.ts +98 -0
  59. package/src/hooks/useUrlState.ts +34 -8
  60. package/src/seam/DomNavigationHost.spec.tsx +78 -0
  61. package/src/seam/DomNavigationHost.tsx +150 -0
  62. package/src/seam/index.ts +41 -0
  63. package/src/seam/navigator.spec.ts +189 -0
  64. package/src/seam/navigator.ts +405 -0
  65. package/src/seam/oneAdapter.tsx +166 -0
  66. package/types/hooks/index.d.ts +2 -0
  67. package/types/hooks/index.d.ts.map +1 -0
  68. package/types/hooks/useUrlState.d.ts +36 -0
  69. package/types/hooks/useUrlState.d.ts.map +1 -0
  70. package/types/index.d.ts +4 -0
  71. package/types/index.d.ts.map +1 -0
  72. package/types/index.storybook.d.ts +4 -0
  73. package/types/index.storybook.d.ts.map +1 -0
  74. package/types/router/EmptyRouter.d.ts +7 -0
  75. package/types/router/EmptyRouter.d.ts.map +1 -0
  76. package/types/router/ReactRouter.d.ts +6 -0
  77. package/types/router/ReactRouter.d.ts.map +1 -0
  78. package/types/router/index.d.ts +2 -0
  79. package/types/router/index.d.ts.map +1 -0
  80. package/types/router/index.storybook-expo.d.ts +2 -0
  81. package/types/router/index.storybook-expo.d.ts.map +1 -0
  82. package/types/router/index.storybook.d.ts +2 -0
  83. package/types/router/index.storybook.d.ts.map +1 -0
  84. package/types/router/index.webext.d.ts +2 -0
  85. package/types/router/index.webext.d.ts.map +1 -0
  86. package/types/seam/DomNavigationHost.d.ts +33 -0
  87. package/types/seam/DomNavigationHost.d.ts.map +1 -0
  88. package/types/seam/index.d.ts +7 -0
  89. package/types/seam/index.d.ts.map +1 -0
  90. package/types/seam/navigator.d.ts +133 -0
  91. package/types/seam/navigator.d.ts.map +1 -0
  92. package/types/seam/oneAdapter.d.ts +57 -0
  93. package/types/seam/oneAdapter.d.ts.map +1 -0
  94. package/types/types.d.ts +40 -0
  95. package/types/types.d.ts.map +1 -0
  96. package/dist/cjs/hooks/useUrlState.spec.cjs +0 -280
  97. package/dist/cjs/hooks/useUrlState.spec.native.js +0 -315
  98. package/dist/cjs/hooks/useUrlState.spec.native.js.map +0 -1
  99. package/dist/esm/hooks/useUrlState.spec.mjs +0 -257
  100. package/dist/esm/hooks/useUrlState.spec.mjs.map +0 -1
  101. package/dist/esm/hooks/useUrlState.spec.native.js +0 -289
  102. package/dist/esm/hooks/useUrlState.spec.native.js.map +0 -1
  103. package/dist/jsx/hooks/useUrlState.spec.mjs +0 -257
  104. package/dist/jsx/hooks/useUrlState.spec.mjs.map +0 -1
  105. package/dist/jsx/hooks/useUrlState.spec.native.js +0 -315
  106. package/dist/jsx/hooks/useUrlState.spec.native.js.map +0 -1
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all) __defProp(target, name, {
9
+ get: all[name],
10
+ enumerable: true
11
+ });
12
+ };
13
+ var __copyProps = (to, from, except, desc) => {
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
16
+ get: () => from[key],
17
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
18
+ });
19
+ }
20
+ return to;
21
+ };
22
+ var __toCommonJS = mod => __copyProps(__defProp({}, "__esModule", {
23
+ value: true
24
+ }), mod);
25
+ var seam_exports = {};
26
+ __export(seam_exports, {
27
+ DomNavigationHost: () => import_DomNavigationHost.DomNavigationHost,
28
+ DomStackAdapter: () => import_DomNavigationHost.DomStackAdapter,
29
+ Link: () => import_oneAdapter.Link,
30
+ LoadProgressBar: () => import_oneAdapter.LoadProgressBar,
31
+ RouteTagContext: () => import_navigator.RouteTagContext,
32
+ Slot: () => import_oneAdapter.Slot,
33
+ StackNavigator: () => import_navigator.StackNavigator,
34
+ hrefToString: () => import_navigator.hrefToString,
35
+ stackNavigator: () => import_navigator.stackNavigator,
36
+ useBlocker: () => import_oneAdapter.useBlocker,
37
+ useLoader: () => import_oneAdapter.useLoader,
38
+ useLocalSearchParams: () => import_oneAdapter.useLocalSearchParams,
39
+ useMatches: () => import_oneAdapter.useMatches,
40
+ useNavState: () => import_navigator.useNavState,
41
+ useParams: () => import_oneAdapter.useParams,
42
+ usePathname: () => import_oneAdapter.usePathname,
43
+ useRouteParams: () => import_navigator.useRouteParams,
44
+ useRouter: () => import_oneAdapter.useRouter
45
+ });
46
+ module.exports = __toCommonJS(seam_exports);
47
+ var import_navigator = require("./navigator.native.js");
48
+ var import_DomNavigationHost = require("./DomNavigationHost.native.js");
49
+ var import_oneAdapter = require("./oneAdapter.native.js");
50
+ //# sourceMappingURL=index.native.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["__toCommonJS","mod","__copyProps","__defProp","value","seam_exports","__export","DomNavigationHost","import_DomNavigationHost","DomStackAdapter","Link","import_oneAdapter","LoadProgressBar","RouteTagContext","import_navigator","Slot","StackNavigator","hrefToString","stackNavigator","useBlocker","useLoader","useLocalSearchParams","useMatches","useNavState","useParams","usePathname","useRouteParams","useRouter","module","exports","require"],"sources":["../../../src/seam/index.ts"],"sourcesContent":[null],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA,IAAAA,YAAA,GAAAC,GAAA,IAAAC,WAAA,CAAAC,SAAA;EAAAC,KAAA;AAAA,IAAAH,GAAA;AAAA,IAAAI,YAAA;AAAAC,QAAA,CAAAD,YAAA;EAAAE,iBAAA,EAAAA,CAAA,KAAAC,wBAAA,CAAAD,iBAAA;EAAAE,eAAA,EAAAA,CAAA,KAAAD,wBAAA,CAAAC,eAAA;EAAAC,IAAA,EAAAA,CAAA,KAAAC,iBAAA,CAAAD,IAAA;EAAAE,eAAA,EAAAA,CAAA,KAAAD,iBAAA,CAAAC,eAAA;EAAAC,eAAA,EAAAA,CAAA,KAAAC,gBAAA,CAAAD,eAAA;EAAAE,IAAA,EAAAA,CAAA,KAAAJ,iBAAA,CAAAI,IAAA;EAAAC,cAAA,EAAAA,CAAA,KAAAF,gBAAA,CAAAE,cAAA;EAAAC,YAAA,EAAAA,CAAA,KAAAH,gBAAA,CAAAG,YAAA;EAAAC,cAAA,EAAAA,CAAA,KAAAJ,gBAAA,CAAAI,cAAA;EAAAC,UAAA,EAAAA,CAAA,KAAAR,iBAAA,CAAAQ,UAAA;EAAAC,SAAA,EAAAA,CAAA,KAAAT,iBAAA,CAAAS,SAAA;EAAAC,oBAAA,EAAAA,CAAA,KAAAV,iBAAA,CAAAU,oBAAA;EAAAC,UAAA,EAAAA,CAAA,KAAAX,iBAAA,CAAAW,UAAA;EAAAC,WAAA,EAAAA,CAAA,KAAAT,gBAAA,CAAAS,WAAA;EAAAC,SAAA,EAAAA,CAAA,KAAAb,iBAAA,CAAAa,SAAA;EAAAC,WAAA,EAAAA,CAAA,KAAAd,iBAAA,CAAAc,WAAA;EAAAC,cAAA,EAAAA,CAAA,KAAAZ,gBAAA,CAAAY,cAAA;EAAAC,SAAA,EAAAA,CAAA,KAAAhB,iBAAA,CAAAgB;AAAA;AASAC,MAAA,CAAAC,OAAA,GAAA7B,YAOO,CAAAK,YAAA;AAUP,IAAAS,gBAAA,GAAAgB,OAAA,CAAmD;AAEnD,IAAAtB,wBAWO,GAAAsB,OAAA","ignoreList":[]}
@@ -0,0 +1,309 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all) __defProp(target, name, {
7
+ get: all[name],
8
+ enumerable: true
9
+ });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
14
+ get: () => from[key],
15
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
16
+ });
17
+ }
18
+ return to;
19
+ };
20
+ var __toCommonJS = mod => __copyProps(__defProp({}, "__esModule", {
21
+ value: true
22
+ }), mod);
23
+ var navigator_exports = {};
24
+ __export(navigator_exports, {
25
+ RouteTagContext: () => RouteTagContext,
26
+ StackNavigator: () => StackNavigator,
27
+ hrefToString: () => hrefToString,
28
+ stackNavigator: () => stackNavigator,
29
+ useNavState: () => useNavState,
30
+ useRouteParams: () => useRouteParams
31
+ });
32
+ module.exports = __toCommonJS(navigator_exports);
33
+ var import_react = require("react");
34
+ function compileRoute(def) {
35
+ const segments = def.pattern.split("/").filter(Boolean).map(seg => {
36
+ const m = seg.match(/^\[(\.{3})?(.+)\]$/);
37
+ return m ? {
38
+ param: m[2]
39
+ } : {
40
+ literal: seg
41
+ };
42
+ });
43
+ return {
44
+ ...def,
45
+ segments
46
+ };
47
+ }
48
+ function parseQuery(query) {
49
+ const params = {};
50
+ if (!query) return params;
51
+ for (const pair of query.split("&")) {
52
+ if (!pair) continue;
53
+ const eq = pair.indexOf("=");
54
+ const key = decodeURIComponent(eq === -1 ? pair : pair.slice(0, eq));
55
+ const value = eq === -1 ? "" : decodeURIComponent(pair.slice(eq + 1));
56
+ const prev = params[key];
57
+ if (prev === void 0) params[key] = value;else if (Array.isArray(prev)) prev.push(value);else params[key] = [prev, value];
58
+ }
59
+ return params;
60
+ }
61
+ function hrefToString(href) {
62
+ if (typeof href === "string") return href;
63
+ let path = href.pathname;
64
+ const leftover = [];
65
+ for (const [key, raw] of Object.entries(href.params ?? {})) {
66
+ const value = String(raw);
67
+ const token = `[${key}]`;
68
+ if (path.includes(token)) path = path.replace(token, encodeURIComponent(value));else leftover.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`);
69
+ }
70
+ return leftover.length ? `${path}?${leftover.join("&")}` : path;
71
+ }
72
+ const EMPTY_PARAMS = Object.freeze({});
73
+ class StackNavigator {
74
+ routes = [];
75
+ host = null;
76
+ listeners = /* @__PURE__ */new Set();
77
+ /** Stack mirror rebuilt from the host on every pushed/popped/replaced
78
+ * signal. */
79
+ stackTags = [];
80
+ paramsByTag = /* @__PURE__ */new Map();
81
+ pathnameByTag = /* @__PURE__ */new Map();
82
+ /** Tags whose page content has been navigated to at least once. The host
83
+ * gates each page's React content on this (lazy mounting) — a tag enters
84
+ * the set right before its first host push and never leaves (backgrounded
85
+ * pages stay alive, same as One keeping stack screens mounted). */
86
+ visitedTags = /* @__PURE__ */new Set();
87
+ /** Route-loader results, per tag (the loader bridge's store). */
88
+ loaderDataByTag = /* @__PURE__ */new Map();
89
+ /** Monotonic navigation sequence — a loader that resolves after a NEWER
90
+ * navigation started must not perform its (stale) host action. */
91
+ navSeq = 0;
92
+ generation = 0;
93
+ snapshot = {
94
+ pathname: "/",
95
+ tag: "",
96
+ depth: 0,
97
+ canGoBack: false,
98
+ generation: 0
99
+ };
100
+ get isConfigured() {
101
+ return this.routes.length > 0;
102
+ }
103
+ /** Register the route manifest. The FIRST route is the root page. */
104
+ configure(defs) {
105
+ this.routes = defs.map(compileRoute);
106
+ this.visitedTags = /* @__PURE__ */new Set();
107
+ this.loaderDataByTag = /* @__PURE__ */new Map();
108
+ const root = defs[0];
109
+ if (root) {
110
+ this.stackTags = [root.tag];
111
+ this.visitedTags.add(root.tag);
112
+ this.pathnameByTag.set(root.tag, root.pattern);
113
+ this.rebuildSnapshot();
114
+ }
115
+ }
116
+ /** Has this route's page been navigated to (⇒ its content may mount)? */
117
+ isVisited(tag) {
118
+ return tag !== null && this.visitedTags.has(tag);
119
+ }
120
+ /** The route's last loader result (stable identity until the loader runs
121
+ * again). undefined when the route has no loader / hasn't resolved. */
122
+ loaderSnapshot(tag) {
123
+ if (!tag) return void 0;
124
+ return this.loaderDataByTag.get(tag);
125
+ }
126
+ /** Resolve a route's loader WITHOUT navigating. For the initial page:
127
+ * entries can `await stackNavigator.preload("/")` during top-level await
128
+ * (where GJS reliably drains promise jobs) so even the root page's first
129
+ * paint has loader data. */
130
+ async preload(href) {
131
+ const hit = this.match(href);
132
+ if (!hit?.route.loader) return;
133
+ try {
134
+ const data = await hit.route.loader({
135
+ path: hit.pathname,
136
+ params: hit.params
137
+ });
138
+ this.loaderDataByTag.set(hit.route.tag, data);
139
+ this.rebuildSnapshot();
140
+ } catch (err) {
141
+ console.error(`[stack nav] preload loader for ${hit.route.tag} failed: ${String(err)}`);
142
+ }
143
+ }
144
+ /** Bind the live host stack (an Adw.NavigationView widget on GTK, a
145
+ * DomStackAdapter on DOM targets). */
146
+ attach(host) {
147
+ this.host = host;
148
+ this.syncFromHost();
149
+ }
150
+ detach() {
151
+ this.host = null;
152
+ }
153
+ subscribe = fn => {
154
+ this.listeners.add(fn);
155
+ return () => this.listeners.delete(fn);
156
+ };
157
+ getSnapshot = () => this.snapshot;
158
+ paramsSnapshot(tag) {
159
+ if (!tag) return EMPTY_PARAMS;
160
+ return this.paramsByTag.get(tag) ?? EMPTY_PARAMS;
161
+ }
162
+ match(href) {
163
+ const str = hrefToString(href);
164
+ const [path = "", query] = str.split("?");
165
+ const parts = path.split("/").filter(Boolean);
166
+ for (const route of this.routes) {
167
+ if (route.segments.length !== parts.length) continue;
168
+ const params = parseQuery(query);
169
+ let ok = true;
170
+ for (let i = 0; i < parts.length; i++) {
171
+ const seg = route.segments[i];
172
+ const part = decodeURIComponent(parts[i]);
173
+ if (seg.literal !== void 0) {
174
+ if (seg.literal !== part) {
175
+ ok = false;
176
+ break;
177
+ }
178
+ } else if (seg.param !== void 0) {
179
+ params[seg.param] = part;
180
+ }
181
+ }
182
+ if (ok) return {
183
+ route,
184
+ pathname: path === "" ? "/" : `/${parts.join("/")}`,
185
+ params
186
+ };
187
+ }
188
+ return null;
189
+ }
190
+ push = href => {
191
+ void this.navigate(href, "push");
192
+ };
193
+ replace = href => {
194
+ void this.navigate(href, "replace");
195
+ };
196
+ /** Shared push/replace flow, incl. the loader bridge. When the target
197
+ * route has no loader the whole body runs SYNCHRONOUSLY (an async
198
+ * function only yields at its first await), preserving the original
199
+ * timing. With a loader, the host action waits for the loader to resolve
200
+ * — same contract as One on web, where client navigation completes only
201
+ * after the route's loader data arrived — so the page's first paint has
202
+ * its data (and the lazily-mounted content mounts with it). */
203
+ async navigate(href, mode) {
204
+ const hit = this.match(href);
205
+ if (!hit) {
206
+ console.log(`[stack nav] ${mode} ${hrefToString(href)} \u2014 no page in the route manifest, ignored`);
207
+ return;
208
+ }
209
+ if (!this.host) {
210
+ console.log(`[stack nav] ${mode} ${hrefToString(href)} \u2014 no stack host attached, ignored`);
211
+ return;
212
+ }
213
+ const {
214
+ route,
215
+ pathname,
216
+ params
217
+ } = hit;
218
+ const seq = ++this.navSeq;
219
+ if (route.loader) {
220
+ try {
221
+ const data = await route.loader({
222
+ path: pathname,
223
+ params
224
+ });
225
+ if (seq !== this.navSeq) return;
226
+ this.loaderDataByTag.set(route.tag, data);
227
+ } catch (err) {
228
+ if (seq !== this.navSeq) return;
229
+ console.error(`[stack nav] loader for ${route.tag} failed: ${String(err)}`);
230
+ }
231
+ }
232
+ this.visitedTags.add(route.tag);
233
+ this.setRouteState(route.tag, pathname, params);
234
+ if (mode === "replace") {
235
+ const top = this.stackTags[this.stackTags.length - 1];
236
+ if (top === route.tag) return;
237
+ const tags = [...this.stackTags.slice(0, -1), route.tag];
238
+ this.host.replace_with_tags(tags);
239
+ return;
240
+ }
241
+ const idx = this.stackTags.indexOf(route.tag);
242
+ if (idx === -1) {
243
+ this.host.push_by_tag(route.tag);
244
+ } else if (idx < this.stackTags.length - 1) {
245
+ this.host.pop_to_tag(route.tag);
246
+ }
247
+ }
248
+ back = () => {
249
+ if (!this.host) {
250
+ console.log("[stack nav] back \u2014 no stack host attached, ignored");
251
+ return;
252
+ }
253
+ this.navSeq++;
254
+ this.host.pop();
255
+ };
256
+ setParams = params => {
257
+ const top = this.stackTags[this.stackTags.length - 1];
258
+ if (!top) return;
259
+ const prev = this.paramsByTag.get(top) ?? {};
260
+ this.paramsByTag.set(top, {
261
+ ...prev,
262
+ ...params
263
+ });
264
+ this.rebuildSnapshot();
265
+ };
266
+ /** Re-read the host navigation stack (called from pushed/popped/replaced
267
+ * signal handlers and attach). The host is the source of truth. */
268
+ syncFromHost = () => {
269
+ if (!this.host) return;
270
+ this.navSeq++;
271
+ const model = this.host.get_navigation_stack();
272
+ const tags = [];
273
+ const count = model.get_n_items();
274
+ for (let i = 0; i < count; i++) {
275
+ const tag = model.get_item(i)?.get_tag();
276
+ if (tag) tags.push(tag);
277
+ }
278
+ if (tags.length > 0) this.stackTags = tags;
279
+ for (const tag of this.stackTags) this.visitedTags.add(tag);
280
+ this.rebuildSnapshot();
281
+ };
282
+ setRouteState(tag, pathname, params) {
283
+ this.paramsByTag.set(tag, params);
284
+ this.pathnameByTag.set(tag, pathname);
285
+ this.rebuildSnapshot();
286
+ }
287
+ rebuildSnapshot() {
288
+ const tag = this.stackTags[this.stackTags.length - 1] ?? "";
289
+ const route = this.routes.find(r => r.tag === tag);
290
+ this.generation++;
291
+ this.snapshot = {
292
+ pathname: this.pathnameByTag.get(tag) ?? route?.pattern ?? "/",
293
+ tag,
294
+ depth: this.stackTags.length,
295
+ canGoBack: this.stackTags.length > 1,
296
+ generation: this.generation
297
+ };
298
+ for (const fn of this.listeners) fn();
299
+ }
300
+ }
301
+ const stackNavigator = new StackNavigator();
302
+ const RouteTagContext = (0, import_react.createContext)(null);
303
+ function useNavState() {
304
+ return (0, import_react.useSyncExternalStore)(stackNavigator.subscribe, stackNavigator.getSnapshot);
305
+ }
306
+ function useRouteParams() {
307
+ const tag = (0, import_react.useContext)(RouteTagContext);
308
+ return (0, import_react.useSyncExternalStore)(stackNavigator.subscribe, () => stackNavigator.paramsSnapshot(tag));
309
+ }