@sigx/lynx-navigation 0.1.3 → 0.4.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.
- package/README.md +189 -7
- package/dist/components/EntryScope.d.ts +1 -1
- package/dist/components/EntryScope.d.ts.map +1 -1
- package/dist/components/Layer.d.ts +34 -0
- package/dist/components/Layer.d.ts.map +1 -0
- package/dist/components/Link.d.ts +2 -2
- package/dist/components/Link.d.ts.map +1 -1
- package/dist/components/NavigationRoot.d.ts +2 -2
- package/dist/components/NavigationRoot.d.ts.map +1 -1
- package/dist/components/Screen.d.ts +6 -6
- package/dist/components/Screen.d.ts.map +1 -1
- package/dist/components/Stack.d.ts +83 -13
- package/dist/components/Stack.d.ts.map +1 -1
- package/dist/components/TabBar.d.ts +19 -20
- package/dist/components/TabBar.d.ts.map +1 -1
- package/dist/components/Tabs.d.ts +30 -21
- package/dist/components/Tabs.d.ts.map +1 -1
- package/dist/define-routes.d.ts +1 -1
- package/dist/define-routes.d.ts.map +1 -1
- package/dist/hooks/use-focus.d.ts.map +1 -1
- package/dist/hooks/use-hardware-back.d.ts +9 -2
- package/dist/hooks/use-hardware-back.d.ts.map +1 -1
- package/dist/hooks/use-linking-nav.d.ts +3 -3
- package/dist/hooks/use-linking-nav.d.ts.map +1 -1
- package/dist/hooks/use-nav-internal.d.ts +21 -3
- package/dist/hooks/use-nav-internal.d.ts.map +1 -1
- package/dist/hooks/use-nav-serializer.d.ts +1 -1
- package/dist/hooks/use-nav-serializer.d.ts.map +1 -1
- package/dist/hooks/use-nav.d.ts +38 -3
- package/dist/hooks/use-nav.d.ts.map +1 -1
- package/dist/hooks/use-params.d.ts +1 -1
- package/dist/hooks/use-params.d.ts.map +1 -1
- package/dist/hooks/use-screen-chrome.d.ts +19 -0
- package/dist/hooks/use-screen-chrome.d.ts.map +1 -0
- package/dist/hooks/use-screen-options.d.ts +1 -1
- package/dist/hooks/use-screen-options.d.ts.map +1 -1
- package/dist/hooks/use-search.d.ts +1 -1
- package/dist/hooks/use-search.d.ts.map +1 -1
- package/dist/href.d.ts +2 -2
- package/dist/href.d.ts.map +1 -1
- package/dist/index.d.ts +33 -31
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1160 -29
- package/dist/index.js.map +1 -1
- package/dist/internal/layer-plan.d.ts +69 -0
- package/dist/internal/layer-plan.d.ts.map +1 -0
- package/dist/internal/screen-registry.d.ts +1 -1
- package/dist/internal/screen-registry.d.ts.map +1 -1
- package/dist/internal/screen-width.d.ts +9 -7
- package/dist/internal/screen-width.d.ts.map +1 -1
- package/dist/navigator/core.d.ts +31 -4
- package/dist/navigator/core.d.ts.map +1 -1
- package/dist/register.d.ts +1 -1
- package/dist/register.d.ts.map +1 -1
- package/dist/url/index.d.ts +6 -6
- package/dist/url/index.d.ts.map +1 -1
- package/dist/url/parse.d.ts +1 -1
- package/dist/url/parse.d.ts.map +1 -1
- package/dist/url/registry.d.ts +2 -2
- package/dist/url/registry.d.ts.map +1 -1
- package/dist/url/validate.d.ts +1 -1
- package/dist/url/validate.d.ts.map +1 -1
- package/package.json +11 -10
- package/src/components/Drawer.d.ts +55 -0
- package/src/components/EdgeBackHandle.d.ts +1 -0
- package/src/components/EdgeBackHandle.tsx +2 -2
- package/{dist/components/EntryScope.js → src/components/EntryScope.d.ts} +7 -15
- package/src/components/EntryScope.tsx +15 -4
- package/src/components/Header.d.ts +6 -0
- package/src/components/Header.tsx +3 -3
- package/src/components/Layer.d.ts +33 -0
- package/src/components/Layer.tsx +96 -0
- package/src/components/Link.d.ts +60 -0
- package/src/components/Link.tsx +4 -4
- package/src/components/NavigationRoot.d.ts +36 -0
- package/src/components/NavigationRoot.tsx +6 -6
- package/src/components/Screen.d.ts +97 -0
- package/src/components/Screen.tsx +13 -11
- package/src/components/Stack.d.ts +90 -0
- package/src/components/Stack.tsx +333 -92
- package/src/components/TabBar.d.ts +38 -0
- package/src/components/TabBar.tsx +22 -22
- package/src/components/Tabs.d.ts +109 -0
- package/src/components/Tabs.tsx +54 -22
- package/{dist/define-routes.js → src/define-routes.d.ts} +2 -4
- package/src/define-routes.ts +1 -1
- package/{dist/hooks/use-focus.js → src/hooks/use-focus.d.ts} +3 -39
- package/src/hooks/use-focus.ts +9 -3
- package/src/hooks/use-hardware-back.d.ts +37 -0
- package/src/hooks/use-hardware-back.ts +43 -9
- package/src/hooks/use-linking-nav.d.ts +91 -0
- package/src/hooks/use-linking-nav.ts +4 -4
- package/src/hooks/use-nav-internal.d.ts +91 -0
- package/src/hooks/use-nav-internal.ts +24 -3
- package/src/hooks/use-nav-serializer.d.ts +82 -0
- package/src/hooks/use-nav-serializer.ts +3 -3
- package/src/hooks/use-nav.d.ts +111 -0
- package/src/hooks/use-nav.ts +40 -3
- package/{dist/hooks/use-params.js → src/hooks/use-params.d.ts} +2 -6
- package/src/hooks/use-params.ts +2 -2
- package/src/hooks/use-screen-chrome.d.ts +18 -0
- package/src/hooks/use-screen-chrome.ts +122 -0
- package/src/hooks/use-screen-options.d.ts +2 -0
- package/src/hooks/use-screen-options.ts +3 -3
- package/{dist/hooks/use-search.js → src/hooks/use-search.d.ts} +2 -6
- package/src/hooks/use-search.ts +2 -2
- package/src/href.d.ts +54 -0
- package/src/href.ts +6 -6
- package/src/index.d.ts +39 -0
- package/src/index.ts +33 -31
- package/src/internal/layer-plan.d.ts +68 -0
- package/src/internal/layer-plan.ts +187 -0
- package/{dist/internal/screen-registry.js → src/internal/screen-registry.d.ts} +21 -32
- package/src/internal/screen-registry.ts +1 -1
- package/src/internal/screen-width.d.ts +17 -0
- package/src/internal/screen-width.ts +22 -14
- package/src/navigator/core.d.ts +96 -0
- package/src/navigator/core.ts +90 -10
- package/src/register.d.ts +37 -0
- package/src/register.ts +1 -1
- package/src/types.d.ts +217 -0
- package/src/url/build.d.ts +15 -0
- package/src/url/build.ts +2 -2
- package/src/url/compile.d.ts +34 -0
- package/src/url/format.d.ts +28 -0
- package/src/url/index.ts +6 -6
- package/src/url/parse.d.ts +20 -0
- package/src/url/parse.ts +6 -6
- package/{dist/url/registry.js → src/url/registry.d.ts} +12 -28
- package/src/url/registry.ts +3 -3
- package/src/url/validate.d.ts +23 -0
- package/src/url/validate.ts +1 -1
- package/dist/components/Drawer.js +0 -74
- package/dist/components/Drawer.js.map +0 -1
- package/dist/components/EdgeBackHandle.js +0 -144
- package/dist/components/EdgeBackHandle.js.map +0 -1
- package/dist/components/EntryScope.js.map +0 -1
- package/dist/components/Header.js +0 -103
- package/dist/components/Header.js.map +0 -1
- package/dist/components/Link.js +0 -51
- package/dist/components/Link.js.map +0 -1
- package/dist/components/NavigationRoot.js +0 -67
- package/dist/components/NavigationRoot.js.map +0 -1
- package/dist/components/Screen.js +0 -94
- package/dist/components/Screen.js.map +0 -1
- package/dist/components/ScreenContainer.d.ts +0 -18
- package/dist/components/ScreenContainer.d.ts.map +0 -1
- package/dist/components/ScreenContainer.js +0 -77
- package/dist/components/ScreenContainer.js.map +0 -1
- package/dist/components/Stack.js +0 -75
- package/dist/components/Stack.js.map +0 -1
- package/dist/components/TabBar.js +0 -63
- package/dist/components/TabBar.js.map +0 -1
- package/dist/components/Tabs.js +0 -140
- package/dist/components/Tabs.js.map +0 -1
- package/dist/define-routes.js.map +0 -1
- package/dist/hooks/use-focus.js.map +0 -1
- package/dist/hooks/use-hardware-back.js +0 -50
- package/dist/hooks/use-hardware-back.js.map +0 -1
- package/dist/hooks/use-linking-nav.js +0 -109
- package/dist/hooks/use-linking-nav.js.map +0 -1
- package/dist/hooks/use-nav-internal.js +0 -44
- package/dist/hooks/use-nav-internal.js.map +0 -1
- package/dist/hooks/use-nav-serializer.js +0 -181
- package/dist/hooks/use-nav-serializer.js.map +0 -1
- package/dist/hooks/use-nav.js +0 -11
- package/dist/hooks/use-nav.js.map +0 -1
- package/dist/hooks/use-params.js.map +0 -1
- package/dist/hooks/use-screen-options.js +0 -43
- package/dist/hooks/use-screen-options.js.map +0 -1
- package/dist/hooks/use-search.js.map +0 -1
- package/dist/href.js +0 -57
- package/dist/href.js.map +0 -1
- package/dist/internal/screen-registry.js.map +0 -1
- package/dist/internal/screen-width.js +0 -30
- package/dist/internal/screen-width.js.map +0 -1
- package/dist/navigator/core.js +0 -344
- package/dist/navigator/core.js.map +0 -1
- package/dist/register.js +0 -2
- package/dist/register.js.map +0 -1
- package/dist/types.js +0 -9
- package/dist/types.js.map +0 -1
- package/dist/url/build.js +0 -30
- package/dist/url/build.js.map +0 -1
- package/dist/url/compile.js +0 -83
- package/dist/url/compile.js.map +0 -1
- package/dist/url/format.js +0 -102
- package/dist/url/format.js.map +0 -1
- package/dist/url/index.js +0 -13
- package/dist/url/index.js.map +0 -1
- package/dist/url/parse.js +0 -94
- package/dist/url/parse.js.map +0 -1
- package/dist/url/registry.js.map +0 -1
- package/dist/url/validate.js +0 -37
- package/dist/url/validate.js.map +0 -1
- package/src/components/ScreenContainer.tsx +0 -114
package/src/navigator/core.ts
CHANGED
|
@@ -7,8 +7,8 @@ import {
|
|
|
7
7
|
} from '@sigx/lynx';
|
|
8
8
|
import { isLazyComponent } from '@sigx/lynx';
|
|
9
9
|
import { withTiming } from '@sigx/lynx-motion';
|
|
10
|
-
import type { Nav } from '../hooks/use-nav
|
|
11
|
-
import type { ScreenRegistry } from '../internal/screen-registry
|
|
10
|
+
import type { Nav } from '../hooks/use-nav';
|
|
11
|
+
import type { ScreenRegistry } from '../internal/screen-registry';
|
|
12
12
|
import type {
|
|
13
13
|
PopOptions,
|
|
14
14
|
Presentation,
|
|
@@ -16,7 +16,7 @@ import type {
|
|
|
16
16
|
RouteMap,
|
|
17
17
|
StackEntry,
|
|
18
18
|
TransitionState,
|
|
19
|
-
} from '../types
|
|
19
|
+
} from '../types';
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
22
|
* The reactive backing state for one navigator instance.
|
|
@@ -61,9 +61,18 @@ export interface NavigatorState {
|
|
|
61
61
|
*/
|
|
62
62
|
readonly _screens: {
|
|
63
63
|
register(registry: ScreenRegistry): void;
|
|
64
|
-
|
|
64
|
+
/** Identity-checked: no-op when a newer registry has taken the slot. */
|
|
65
|
+
unregister(registry: ScreenRegistry): void;
|
|
65
66
|
get(entryKey: string): ScreenRegistry | undefined;
|
|
66
67
|
};
|
|
68
|
+
/**
|
|
69
|
+
* Internal: set `nav.isLocallyFocused` from outside.
|
|
70
|
+
*
|
|
71
|
+
* `<Stack>` calls this when its host entry's locally-focused state
|
|
72
|
+
* changes (top of parent + parent focused + enclosing tab active). For
|
|
73
|
+
* the root nav this stays `true` for the lifetime of the navigator.
|
|
74
|
+
*/
|
|
75
|
+
readonly _setLocallyFocused: (focused: boolean) => void;
|
|
67
76
|
}
|
|
68
77
|
|
|
69
78
|
/**
|
|
@@ -146,6 +155,24 @@ export interface CreateNavigatorOptions {
|
|
|
146
155
|
* that don't have an MT runtime.
|
|
147
156
|
*/
|
|
148
157
|
progress?: SharedValue<number>;
|
|
158
|
+
/**
|
|
159
|
+
* Parent navigator. Set when this navigator is nested under another
|
|
160
|
+
* (e.g. a per-tab `<Stack initialRoute>` under root). Drives the
|
|
161
|
+
* `nav.parent` getter and the modal-escalation behaviour of `push`:
|
|
162
|
+
* a push of a route whose resolved presentation is not `'card'`
|
|
163
|
+
* recurses via `parent.push(...)`, walking up the chain until it
|
|
164
|
+
* lands on a navigator with no parent (the root).
|
|
165
|
+
*
|
|
166
|
+
* Leave undefined for the root navigator.
|
|
167
|
+
*/
|
|
168
|
+
parent?: Nav | null;
|
|
169
|
+
/**
|
|
170
|
+
* Whether this navigator is considered "locally focused" at creation
|
|
171
|
+
* time. Defaults to true for the root nav; nested stacks pass `false`
|
|
172
|
+
* here and then flip the flag via `_setLocallyFocused` once their
|
|
173
|
+
* host-entry/tab-active state is computed.
|
|
174
|
+
*/
|
|
175
|
+
initialLocallyFocused?: boolean;
|
|
149
176
|
}
|
|
150
177
|
|
|
151
178
|
/**
|
|
@@ -154,9 +181,13 @@ export interface CreateNavigatorOptions {
|
|
|
154
181
|
* can subscribe to it.
|
|
155
182
|
*/
|
|
156
183
|
export function createNavigatorState(opts: CreateNavigatorOptions): NavigatorState {
|
|
157
|
-
const { routes, initial, progress } = opts;
|
|
184
|
+
const { routes, initial, progress, parent = null } = opts;
|
|
158
185
|
|
|
159
186
|
const stackSignal: Signal<StackEntry[]> = signal<StackEntry[]>([initial]);
|
|
187
|
+
const focusedBox: Signal<{ value: boolean }> = signal<{ value: boolean }>({
|
|
188
|
+
value: opts.initialLocallyFocused ?? true,
|
|
189
|
+
});
|
|
190
|
+
const children = new Set<Nav>();
|
|
160
191
|
// `signal(null)` would wrap as a primitive (no `$set`), so wrap in an
|
|
161
192
|
// object to get the standard `{ value }`-style API. Reading `.value`
|
|
162
193
|
// tracks; writing triggers re-render of `<Stack>`.
|
|
@@ -231,14 +262,33 @@ export function createNavigatorState(opts: CreateNavigatorOptions): NavigatorSta
|
|
|
231
262
|
}
|
|
232
263
|
|
|
233
264
|
const push: Nav['push'] = ((name: string, ...args: unknown[]) => {
|
|
234
|
-
if (isTransitioning()) return;
|
|
235
|
-
const { params, search, options } = unpackArgs(name, args, routes);
|
|
236
265
|
if (!routes[name]) {
|
|
237
266
|
throw new Error(
|
|
238
267
|
`[lynx-navigation] push('${name}'): route is not registered. ` +
|
|
239
268
|
`Known routes: ${Object.keys(routes).join(', ') || '(none)'}`,
|
|
240
269
|
);
|
|
241
270
|
}
|
|
271
|
+
const { params, search, options } = unpackArgs(name, args, routes);
|
|
272
|
+
|
|
273
|
+
// Escalate non-card presentations up the parent chain. Modals,
|
|
274
|
+
// fullScreen, and transparent-modal routes belong on the root
|
|
275
|
+
// navigator so they overlay tab UI and persistent chrome. We resolve
|
|
276
|
+
// the presentation the same way `makeEntry` does so the escalation
|
|
277
|
+
// decision matches what would actually be shown.
|
|
278
|
+
const resolvedPresentation =
|
|
279
|
+
(options?.presentation ?? routes[name].presentation ?? 'card') as Presentation;
|
|
280
|
+
if (resolvedPresentation !== 'card' && parent) {
|
|
281
|
+
// Walk straight to the root — every navigator with a parent
|
|
282
|
+
// delegates non-card pushes upward, so a chain of any depth
|
|
283
|
+
// collapses to a single push on the topmost nav.
|
|
284
|
+
// Forward original args verbatim so overloads (`push(name)`,
|
|
285
|
+
// `push(name, params)`, `push(name, params, search)`,
|
|
286
|
+
// `push(name, params, search, options)`) keep their meaning.
|
|
287
|
+
(parent.push as (n: string, ...a: unknown[]) => void)(name, ...args);
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
if (isTransitioning()) return;
|
|
242
292
|
preloadRouteComponent(routes[name].component);
|
|
243
293
|
const newEntry = makeEntry(name, params, search, options, routes);
|
|
244
294
|
const cur = getStack();
|
|
@@ -411,18 +461,38 @@ export function createNavigatorState(opts: CreateNavigatorOptions): NavigatorSta
|
|
|
411
461
|
return stackSignal.length > 1;
|
|
412
462
|
},
|
|
413
463
|
get parent() {
|
|
414
|
-
return
|
|
464
|
+
return parent;
|
|
465
|
+
},
|
|
466
|
+
get isLocallyFocused() {
|
|
467
|
+
return focusedBox.value;
|
|
468
|
+
},
|
|
469
|
+
get _children() {
|
|
470
|
+
return children;
|
|
415
471
|
},
|
|
416
472
|
get transition() {
|
|
417
473
|
return transitionBox.value;
|
|
418
474
|
},
|
|
419
475
|
};
|
|
420
476
|
|
|
477
|
+
if (parent) {
|
|
478
|
+
// Register with parent so root-level traversals (hardware back,
|
|
479
|
+
// future deepest-focused queries) can reach this nav. The matching
|
|
480
|
+
// `_children.delete(nav)` happens when the owning `<Stack>` unmounts;
|
|
481
|
+
// see Stack.tsx.
|
|
482
|
+
parent._children.add(nav);
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
function setLocallyFocused(focused: boolean): void {
|
|
486
|
+
if (focusedBox.value === focused) return;
|
|
487
|
+
focusedBox.value = focused;
|
|
488
|
+
}
|
|
489
|
+
|
|
421
490
|
return {
|
|
422
491
|
nav,
|
|
423
492
|
routes,
|
|
424
493
|
_gesture: { beginBackGesture, commitBackGesture, cancelBackGesture },
|
|
425
494
|
_screens: createScreenRegistries(),
|
|
495
|
+
_setLocallyFocused: setLocallyFocused,
|
|
426
496
|
};
|
|
427
497
|
}
|
|
428
498
|
|
|
@@ -451,8 +521,18 @@ function createScreenRegistries(): NavigatorState['_screens'] {
|
|
|
451
521
|
// would self-loop, so we untrack the bump.
|
|
452
522
|
untrack(() => { version.v = version.v + 1; });
|
|
453
523
|
},
|
|
454
|
-
unregister
|
|
455
|
-
|
|
524
|
+
// Identity-checked unregister: deletes the entry only if the
|
|
525
|
+
// currently-registered registry is the *same instance* the caller
|
|
526
|
+
// holds. Without this, the transition→idle handoff (which can
|
|
527
|
+
// mount a new `<EntryScope>` for the same entry-key before the
|
|
528
|
+
// old one unmounts) would let the old scope's `onUnmounted` wipe
|
|
529
|
+
// out the fresh registry — leaving `screens.get(key)` returning
|
|
530
|
+
// undefined and chrome consumers (NavHeader) falling back to the
|
|
531
|
+
// route-name as title with all slot fills gone.
|
|
532
|
+
unregister(reg: ScreenRegistry) {
|
|
533
|
+
const cur = byKey.get(reg.entry.key);
|
|
534
|
+
if (cur !== reg) return;
|
|
535
|
+
byKey.delete(reg.entry.key);
|
|
456
536
|
untrack(() => { version.v = version.v + 1; });
|
|
457
537
|
},
|
|
458
538
|
get(key: string) {
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { ParamsOf, RouteMap, SearchOf } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Module-augmentation surface for the user's typed route map.
|
|
4
|
+
*
|
|
5
|
+
* Apps register their routes by augmenting this interface — the rest of the
|
|
6
|
+
* library's typed APIs (useNav, useParams, useSearch, <Link>) read from
|
|
7
|
+
* `RegisteredRoutes` so all inference is global.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* // In your app's main.ts (or a routes.ts that's imported early):
|
|
12
|
+
* import type { routes } from './routes';
|
|
13
|
+
*
|
|
14
|
+
* declare module '@sigx/lynx-navigation' {
|
|
15
|
+
* interface Register { routes: typeof routes }
|
|
16
|
+
* }
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* If `Register.routes` is not augmented the library falls back to a permissive
|
|
20
|
+
* `RouteMap` so non-augmented usage still type-checks (just without precise
|
|
21
|
+
* inference). The recommended pattern is always to augment.
|
|
22
|
+
*/
|
|
23
|
+
export interface Register {
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* The user's registered route map, or a permissive fallback when not
|
|
27
|
+
* augmented. All higher-level types derive from this.
|
|
28
|
+
*/
|
|
29
|
+
export type RegisteredRoutes = Register extends {
|
|
30
|
+
routes: infer R;
|
|
31
|
+
} ? R : RouteMap;
|
|
32
|
+
/** Union of registered route names (string literal union when registered). */
|
|
33
|
+
export type RouteId = keyof RegisteredRoutes & string;
|
|
34
|
+
/** Params type for a registered route name. */
|
|
35
|
+
export type RouteParams<K extends RouteId> = ParamsOf<RegisteredRoutes[K]>;
|
|
36
|
+
/** Search type for a registered route name. */
|
|
37
|
+
export type RouteSearch<K extends RouteId> = SearchOf<RegisteredRoutes[K]>;
|
package/src/register.ts
CHANGED
package/src/types.d.ts
ADDED
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core types for @sigx/lynx-navigation.
|
|
3
|
+
*
|
|
4
|
+
* The type machinery here is the differentiating DX: route names, params, and
|
|
5
|
+
* search are all inferred end-to-end from the user's `defineRoutes` call so
|
|
6
|
+
* `nav.push('profile', { id: 42 })` is a TS error if `id` is typed as string.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Minimal Standard Schema spec subset — see https://standardschema.dev.
|
|
10
|
+
* Inlined so we don't depend on `@standard-schema/spec` for the type spike.
|
|
11
|
+
* Compatible with Zod, Valibot, ArkType, etc.
|
|
12
|
+
*/
|
|
13
|
+
export interface StandardSchemaV1<Input = unknown, Output = Input> {
|
|
14
|
+
readonly '~standard': {
|
|
15
|
+
readonly version: 1;
|
|
16
|
+
readonly vendor: string;
|
|
17
|
+
readonly types?: {
|
|
18
|
+
readonly input: Input;
|
|
19
|
+
readonly output: Output;
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Infer the validated output type of a Standard Schema, falling back to
|
|
25
|
+
* `unknown` for non-schema values.
|
|
26
|
+
*/
|
|
27
|
+
export type InferOutput<S> = S extends StandardSchemaV1<unknown, infer O> ? O : unknown;
|
|
28
|
+
/** Empty record — what `ParamsOf` returns when a route declares no schema. */
|
|
29
|
+
export type EmptyParams = Record<string, never>;
|
|
30
|
+
/**
|
|
31
|
+
* How a route entry is presented on the stack.
|
|
32
|
+
* `card` is the default push; `modal`/`fullScreen` slide up; `transparent-modal`
|
|
33
|
+
* preserves the underlying screen visible (e.g. for popovers).
|
|
34
|
+
*/
|
|
35
|
+
export type Presentation = 'card' | 'modal' | 'fullScreen' | 'transparent-modal';
|
|
36
|
+
/**
|
|
37
|
+
* A route definition entry.
|
|
38
|
+
*
|
|
39
|
+
* Users construct this via `defineRoutes({...})`. The `params` and `search`
|
|
40
|
+
* schemas drive runtime validation AND TS inference for `useParams`,
|
|
41
|
+
* `useSearch`, `nav.push`, `<Link>`, etc.
|
|
42
|
+
*
|
|
43
|
+
* `component` accepts an eager component factory or a lazy import — both shapes
|
|
44
|
+
* resolve through sigx's `<Suspense>` boundary at render time.
|
|
45
|
+
*/
|
|
46
|
+
export interface RouteDefinition<Params extends StandardSchemaV1 | undefined = StandardSchemaV1 | undefined, Search extends StandardSchemaV1 | undefined = StandardSchemaV1 | undefined> {
|
|
47
|
+
/** Component factory or lazy importer. */
|
|
48
|
+
component: ComponentLike;
|
|
49
|
+
/**
|
|
50
|
+
* Fallback shown while a lazy `component` is loading.
|
|
51
|
+
*
|
|
52
|
+
* Set this only on routes whose `component` was created with `lazy(...)`.
|
|
53
|
+
* The fallback is rendered inside a `<Suspense>` boundary wrapping the
|
|
54
|
+
* screen mount, so the user sees this UI while the screen's chunk is
|
|
55
|
+
* being fetched. When omitted, lazy routes still work — the caller is
|
|
56
|
+
* responsible for placing its own `<Suspense>` boundary (e.g. above the
|
|
57
|
+
* `<NavigationRoot>` or inside the screen component).
|
|
58
|
+
*
|
|
59
|
+
* Accepts a component factory (`MyLoadingScreen`) or a function returning
|
|
60
|
+
* JSX (`() => <Spinner />`). Eager routes ignore this field.
|
|
61
|
+
*/
|
|
62
|
+
fallback?: ComponentLike | (() => unknown);
|
|
63
|
+
/** Standard-Schema validator for path params. Optional. */
|
|
64
|
+
params?: Params;
|
|
65
|
+
/** Standard-Schema validator for query/search params. Optional. */
|
|
66
|
+
search?: Search;
|
|
67
|
+
/** Optional URL pattern for deep-link serialization (e.g. `/users/:id`). */
|
|
68
|
+
path?: string;
|
|
69
|
+
/** Default presentation when this route is pushed. */
|
|
70
|
+
presentation?: Presentation;
|
|
71
|
+
/** Nested routes — share the URL/path namespace and may inherit options. */
|
|
72
|
+
children?: Record<string, RouteDefinition>;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* The component shape we accept on a route. Kept structural so we don't pull
|
|
76
|
+
* `ComponentFactory` from sigx at type level (avoids a hard dep on sigx purely
|
|
77
|
+
* for types in the spike). Refined to a real ComponentFactory in Phase 0.1
|
|
78
|
+
* runtime work.
|
|
79
|
+
*/
|
|
80
|
+
export type ComponentLike = ((...args: any[]) => unknown) | (() => Promise<{
|
|
81
|
+
default: (...args: any[]) => unknown;
|
|
82
|
+
}>);
|
|
83
|
+
/**
|
|
84
|
+
* Map of route definitions, as returned by `defineRoutes`. Keys are route
|
|
85
|
+
* names; values are typed RouteDefinitions.
|
|
86
|
+
*/
|
|
87
|
+
export type RouteMap = Record<string, RouteDefinition>;
|
|
88
|
+
/**
|
|
89
|
+
* Extract params type from a single RouteDefinition.
|
|
90
|
+
* Falls back to `EmptyParams` when the route declares no schema.
|
|
91
|
+
*
|
|
92
|
+
* We use a structural `params: infer S` match (without an `extends
|
|
93
|
+
* StandardSchemaV1` constraint on `S`) because TS conditional types treat the
|
|
94
|
+
* generic-defaulted `StandardSchemaV1<unknown, unknown>` as invariant in this
|
|
95
|
+
* position — a schema typed `StandardSchemaV1<{id:string}>` does not match
|
|
96
|
+
* `extends StandardSchemaV1` reliably under `<const T>` inference. `InferOutput`
|
|
97
|
+
* gracefully handles non-schema `S` by returning `unknown`.
|
|
98
|
+
*/
|
|
99
|
+
export type ParamsOf<R> = R extends {
|
|
100
|
+
params: infer S;
|
|
101
|
+
} ? InferOutput<S> : EmptyParams;
|
|
102
|
+
/**
|
|
103
|
+
* Extract search type from a single RouteDefinition.
|
|
104
|
+
* Falls back to `EmptyParams` when the route declares no schema.
|
|
105
|
+
*/
|
|
106
|
+
export type SearchOf<R> = R extends {
|
|
107
|
+
search: infer S;
|
|
108
|
+
} ? InferOutput<S> : EmptyParams;
|
|
109
|
+
/**
|
|
110
|
+
* Whether a route requires a `params` argument when calling `nav.push` etc.
|
|
111
|
+
* True iff the route definition has a `params` field.
|
|
112
|
+
*/
|
|
113
|
+
export type RouteRequiresParams<R> = R extends {
|
|
114
|
+
params: object;
|
|
115
|
+
} ? true : false;
|
|
116
|
+
/**
|
|
117
|
+
* Per-entry state stored on the stack signal.
|
|
118
|
+
*
|
|
119
|
+
* `key` is unique per entry — needed because the same route can appear more
|
|
120
|
+
* than once (e.g. profile A → message → profile A again). Focus state and
|
|
121
|
+
* scroll position are keyed by `key`, not by route name.
|
|
122
|
+
*/
|
|
123
|
+
export interface StackEntry<R extends string = string, P = unknown, S = unknown> {
|
|
124
|
+
readonly key: string;
|
|
125
|
+
readonly route: R;
|
|
126
|
+
readonly params: P;
|
|
127
|
+
readonly search: S;
|
|
128
|
+
/** User state — survives suspend/restore. */
|
|
129
|
+
state: unknown;
|
|
130
|
+
readonly presentation: Presentation;
|
|
131
|
+
}
|
|
132
|
+
/** Options accepted by `nav.push` / `nav.replace`. */
|
|
133
|
+
export interface PushOptions {
|
|
134
|
+
/** Override the route's default presentation for this navigation. */
|
|
135
|
+
presentation?: Presentation;
|
|
136
|
+
/** User state to attach to the new entry. Survives suspend/restore. */
|
|
137
|
+
state?: unknown;
|
|
138
|
+
/**
|
|
139
|
+
* Skip the slide animation (instant swap). Defaults to true on platforms
|
|
140
|
+
* where `useAnimatedStyle` isn't available (test renderer); defaults to
|
|
141
|
+
* false on real Lynx. Tests can force `false` to keep assertions
|
|
142
|
+
* deterministic.
|
|
143
|
+
*/
|
|
144
|
+
animated?: boolean;
|
|
145
|
+
}
|
|
146
|
+
/** Options accepted by `nav.pop`. */
|
|
147
|
+
export interface PopOptions {
|
|
148
|
+
/** Skip the slide animation (instant swap). See `PushOptions.animated`. */
|
|
149
|
+
animated?: boolean;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Direction of an in-flight transition.
|
|
153
|
+
* - `push`: a new entry is animating in (progress 0 → 1).
|
|
154
|
+
* - `pop`: the current top is animating out (progress 0 → 1, then committed).
|
|
155
|
+
*/
|
|
156
|
+
export type TransitionKind = 'push' | 'pop';
|
|
157
|
+
/** Role of a screen during a transition — determines its transform formula. */
|
|
158
|
+
export type TransitionRole = 'top' | 'underneath';
|
|
159
|
+
/**
|
|
160
|
+
* Snapshot of an in-flight transition. Stored on the navigator state so the
|
|
161
|
+
* `<Stack>` component knows to render two entries (`topEntry` above
|
|
162
|
+
* `underneathEntry`) and bind their transforms to `progress`.
|
|
163
|
+
*
|
|
164
|
+
* `progress` is a `SharedValue<number>` (re-exported as `unknown` here to
|
|
165
|
+
* avoid a hard dep on `@sigx/lynx`'s SharedValue type at the contract level —
|
|
166
|
+
* the runtime `<Stack>` casts as needed). The value runs 0 → 1 in both push
|
|
167
|
+
* and pop, with the role/kind pair determining the visual direction.
|
|
168
|
+
*/
|
|
169
|
+
export interface TransitionState {
|
|
170
|
+
readonly kind: TransitionKind;
|
|
171
|
+
readonly topEntry: StackEntry;
|
|
172
|
+
readonly underneathEntry: StackEntry;
|
|
173
|
+
/** Animation progress signal — typed loosely; cast at the runtime boundary. */
|
|
174
|
+
readonly progress: unknown;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Per-screen display options written by `<Screen>` into its entry's registry.
|
|
178
|
+
*
|
|
179
|
+
* Read by persistent navigator chrome (the `<HeaderBar>` shipped in the
|
|
180
|
+
* `header` slice; `<TabBar>` later). All fields are optional — consumers
|
|
181
|
+
* apply sensible defaults (headerShown defaults to true, gestureEnabled to
|
|
182
|
+
* true, title falls back to the route name).
|
|
183
|
+
*
|
|
184
|
+
* `title` accepts a function so the header can be derived from reactive
|
|
185
|
+
* state (e.g. a user's display name signal). Plain strings are wrapped in
|
|
186
|
+
* a thunk by consumers when read.
|
|
187
|
+
*/
|
|
188
|
+
export interface ScreenOptions {
|
|
189
|
+
/** Header title. Either a static string or a getter (re-tracked each render). */
|
|
190
|
+
title?: string | (() => string);
|
|
191
|
+
/** When false, the navigator's header is hidden for this screen. Default true. */
|
|
192
|
+
headerShown?: boolean;
|
|
193
|
+
/** When false, the iOS edge-swipe-back gesture is disabled for this screen. Default true. */
|
|
194
|
+
gestureEnabled?: boolean;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Slot fills written by `<Screen.Header>` / `<Screen.HeaderLeft>` /
|
|
198
|
+
* `<Screen.HeaderRight>` / `<Screen.TabBarItem>`.
|
|
199
|
+
*
|
|
200
|
+
* Each fill is the rendered output of that sub-component's `default` slot,
|
|
201
|
+
* captured as a thunk so the navigator's persistent chrome can call it at
|
|
202
|
+
* render time. `tabBarItem` is a scoped slot — the consumer passes
|
|
203
|
+
* `{ active }` so the same screen's tab-bar item can style itself
|
|
204
|
+
* differently when focused vs. not.
|
|
205
|
+
*/
|
|
206
|
+
export interface ScreenSlotFills {
|
|
207
|
+
/** Full header replacement. When set, takes precedence over title + headerLeft/Right. */
|
|
208
|
+
header?: () => unknown;
|
|
209
|
+
/** Left-side header content (typically back arrow override). */
|
|
210
|
+
headerLeft?: () => unknown;
|
|
211
|
+
/** Right-side header content (typically action buttons). */
|
|
212
|
+
headerRight?: () => unknown;
|
|
213
|
+
/** Tab-bar item — scoped slot receives `{ active }` indicating focus. */
|
|
214
|
+
tabBarItem?: (ctx: {
|
|
215
|
+
active: boolean;
|
|
216
|
+
}) => unknown;
|
|
217
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed → URL: build the `url` field of an Href from a route's params/search.
|
|
3
|
+
*
|
|
4
|
+
* Mirror of parse.ts. Used by `hrefFor()` after schema validation succeeds.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Build the URL form of a route + params + search, or `null` if the route
|
|
8
|
+
* declares no `path` template (typed navigation still works — only deep-link
|
|
9
|
+
* serialization is unavailable).
|
|
10
|
+
*
|
|
11
|
+
* Params must already be valid for the route's schema (callers run this after
|
|
12
|
+
* `validateSync`). Search values are stringified as-is — schema-validated
|
|
13
|
+
* inputs survive round-tripping because `parseHref` re-runs the same schema.
|
|
14
|
+
*/
|
|
15
|
+
export declare function buildUrl(routeName: string, params: Record<string, unknown> | undefined, search: Record<string, unknown> | undefined): string | null;
|
package/src/url/build.ts
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* Mirror of parse.ts. Used by `hrefFor()` after schema validation succeeds.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { formatSearch } from './format
|
|
8
|
-
import { getCompiledPath, getRouteRegistry } from './registry
|
|
7
|
+
import { formatSearch } from './format';
|
|
8
|
+
import { getCompiledPath, getRouteRegistry } from './registry';
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Build the URL form of a route + params + search, or `null` if the route
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Path template compiler.
|
|
3
|
+
*
|
|
4
|
+
* Turns a route's `path` (e.g. `/users/:id/posts/:postId`) into a compiled
|
|
5
|
+
* object that can both match a URL pathname against it and format a typed
|
|
6
|
+
* params object back into a URL.
|
|
7
|
+
*
|
|
8
|
+
* Supported syntax (intentionally minimal for v1):
|
|
9
|
+
* - Literal segments: `/users`, `/users/me`
|
|
10
|
+
* - Named params: `:id` (matches `[^/]+`)
|
|
11
|
+
* - Trailing slashes tolerated on match
|
|
12
|
+
*
|
|
13
|
+
* Out of scope for v1 (future-compatible — additions won't break v1 paths):
|
|
14
|
+
* - Wildcards `*`
|
|
15
|
+
* - Optional params `:id?`
|
|
16
|
+
* - Typed/constrained params `:id<number>` or `:id(\\d+)`
|
|
17
|
+
*/
|
|
18
|
+
/** Result of compiling a path template — used by parse + format. */
|
|
19
|
+
export interface CompiledPath {
|
|
20
|
+
readonly source: string;
|
|
21
|
+
readonly paramNames: readonly string[];
|
|
22
|
+
/** Regex that matches a URL pathname. Captures are param values in order. */
|
|
23
|
+
readonly regex: RegExp;
|
|
24
|
+
/**
|
|
25
|
+
* Render a URL pathname for this template given param values. Each value
|
|
26
|
+
* is `encodeURIComponent`-encoded. Throws if a required `:name` is missing.
|
|
27
|
+
*/
|
|
28
|
+
format(params: Record<string, string | number>): string;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Compile a path template. Throws on malformed input (duplicate param names,
|
|
32
|
+
* unexpected `:` syntax). Pure — safe to memoize.
|
|
33
|
+
*/
|
|
34
|
+
export declare function compilePath(template: string): CompiledPath;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Format helpers: typed params/search → URL string.
|
|
3
|
+
*
|
|
4
|
+
* Used by `hrefFor()` to render the `url` field of an Href.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Serialize an object as a `key=value&key=value` querystring.
|
|
8
|
+
*
|
|
9
|
+
* Keys are sorted to make the output deterministic (useful for tests and
|
|
10
|
+
* persistence diffs). `undefined`/`null` values are skipped. Non-primitive
|
|
11
|
+
* values are JSON-stringified on the way out — `parseSearch` returns the
|
|
12
|
+
* raw string and leaves any JSON decoding to the route's `search` schema
|
|
13
|
+
* (e.g. a Zod `transform`), so the round-trip is intentionally one-way at
|
|
14
|
+
* this layer.
|
|
15
|
+
*
|
|
16
|
+
* Returns `''` (empty string) when there are no entries — callers join with
|
|
17
|
+
* `?` only when the result is non-empty.
|
|
18
|
+
*/
|
|
19
|
+
export declare function formatSearch(search: Record<string, unknown> | undefined): string;
|
|
20
|
+
/**
|
|
21
|
+
* Parse a `key=value&key=value` querystring into a string-keyed bag. Values
|
|
22
|
+
* are decoded but kept as strings — typed coercion happens in the route's
|
|
23
|
+
* `search` schema (e.g. Zod's `z.coerce.number()`).
|
|
24
|
+
*
|
|
25
|
+
* Multiple occurrences of the same key produce an array. Schemas that don't
|
|
26
|
+
* expect arrays will reject this — that's the right failure mode.
|
|
27
|
+
*/
|
|
28
|
+
export declare function parseSearch(query: string): Record<string, string | string[]>;
|
package/src/url/index.ts
CHANGED
|
@@ -5,14 +5,14 @@
|
|
|
5
5
|
* `parseHref` in ../href.ts plus `_setRouteRegistry` for tests/bootstrap.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
export { compilePath, type CompiledPath } from './compile
|
|
9
|
-
export { buildUrl } from './build
|
|
10
|
-
export { parseHrefImpl } from './parse
|
|
11
|
-
export { formatSearch, parseSearch } from './format
|
|
8
|
+
export { compilePath, type CompiledPath } from './compile';
|
|
9
|
+
export { buildUrl } from './build';
|
|
10
|
+
export { parseHrefImpl } from './parse';
|
|
11
|
+
export { formatSearch, parseSearch } from './format';
|
|
12
12
|
export {
|
|
13
13
|
_setRouteRegistry,
|
|
14
14
|
_clearRouteRegistry,
|
|
15
15
|
getRouteRegistry,
|
|
16
16
|
getCompiledPath,
|
|
17
|
-
} from './registry
|
|
18
|
-
export { validateSync, type ValidateOutcome } from './validate
|
|
17
|
+
} from './registry';
|
|
18
|
+
export { validateSync, type ValidateOutcome } from './validate';
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* URL → typed Href parser.
|
|
3
|
+
*
|
|
4
|
+
* Walks every registered route with a `path`, tries to match its compiled
|
|
5
|
+
* regex against the URL's pathname, and on a hit validates the extracted
|
|
6
|
+
* params + search through the route's Standard Schema. First match wins;
|
|
7
|
+
* iteration order follows `Object.keys` of the registered routes map.
|
|
8
|
+
*
|
|
9
|
+
* Validation failures return `null` rather than throwing — deep-link handlers
|
|
10
|
+
* fall back to the initial route on a bad URL instead of crashing the app.
|
|
11
|
+
*/
|
|
12
|
+
import type { Href } from '../href';
|
|
13
|
+
/**
|
|
14
|
+
* Parse a URL string against the active route registry.
|
|
15
|
+
*
|
|
16
|
+
* Accepts both absolute URLs (`myapp://host/users/42?tab=about`) and
|
|
17
|
+
* pathname-only forms (`/users/42?tab=about`). Returns `null` if no route's
|
|
18
|
+
* `path` matches the URL or if schema validation rejects the extracted bits.
|
|
19
|
+
*/
|
|
20
|
+
export declare function parseHrefImpl(url: string): Href | null;
|
package/src/url/parse.ts
CHANGED
|
@@ -10,13 +10,13 @@
|
|
|
10
10
|
* fall back to the initial route on a bad URL instead of crashing the app.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
import type { Href } from '../href
|
|
14
|
-
import type { RouteId } from '../register
|
|
13
|
+
import type { Href } from '../href';
|
|
14
|
+
import type { RouteId } from '../register';
|
|
15
15
|
import { parse as parseUrl } from '@sigx/lynx-linking';
|
|
16
|
-
import type { CompiledPath } from './compile
|
|
17
|
-
import { parseSearch } from './format
|
|
18
|
-
import { getCompiledPath, getRouteRegistry } from './registry
|
|
19
|
-
import { validateSync } from './validate
|
|
16
|
+
import type { CompiledPath } from './compile';
|
|
17
|
+
import { parseSearch } from './format';
|
|
18
|
+
import { getCompiledPath, getRouteRegistry } from './registry';
|
|
19
|
+
import { validateSync } from './validate';
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
22
|
* Parse a URL string against the active route registry.
|
|
@@ -11,8 +11,13 @@
|
|
|
11
11
|
* directly. The leading underscore is a convention: not part of the supported
|
|
12
12
|
* public API (test/integration use only).
|
|
13
13
|
*/
|
|
14
|
-
import {
|
|
15
|
-
|
|
14
|
+
import type { CompiledPath } from './compile';
|
|
15
|
+
import type { RouteMap } from '../types';
|
|
16
|
+
interface RegistryState {
|
|
17
|
+
readonly routes: RouteMap;
|
|
18
|
+
/** Lazy-compiled paths keyed by route name. */
|
|
19
|
+
readonly compiled: Map<string, CompiledPath>;
|
|
20
|
+
}
|
|
16
21
|
/**
|
|
17
22
|
* Set the active route registry. Called by `<NavigationRoot>` on setup and
|
|
18
23
|
* available to tests/bootstrap code as `_setRouteRegistry`.
|
|
@@ -22,35 +27,14 @@ let current = null;
|
|
|
22
27
|
* specific registry for a one-off call, pass it explicitly to the helper
|
|
23
28
|
* (parseHrefWithRoutes / hrefForWithRoutes — currently internal).
|
|
24
29
|
*/
|
|
25
|
-
export function _setRouteRegistry(routes)
|
|
26
|
-
current = { routes, compiled: new Map() };
|
|
27
|
-
}
|
|
30
|
+
export declare function _setRouteRegistry(routes: RouteMap): void;
|
|
28
31
|
/** Clear the registry. Mainly for tests that want to assert the unset path. */
|
|
29
|
-
export function _clearRouteRegistry()
|
|
30
|
-
current = null;
|
|
31
|
-
}
|
|
32
|
+
export declare function _clearRouteRegistry(): void;
|
|
32
33
|
/** Get the active registry or throw a friendly error if none is set. */
|
|
33
|
-
export function getRouteRegistry()
|
|
34
|
-
if (!current) {
|
|
35
|
-
throw new Error('[lynx-navigation] No route registry set — render a <NavigationRoot> first, or call _setRouteRegistry() for tests.');
|
|
36
|
-
}
|
|
37
|
-
return current;
|
|
38
|
-
}
|
|
34
|
+
export declare function getRouteRegistry(): RegistryState;
|
|
39
35
|
/**
|
|
40
36
|
* Look up (or lazily compile) the path template for a route name. Returns
|
|
41
37
|
* `null` when the route exists but declares no `path`.
|
|
42
38
|
*/
|
|
43
|
-
export function getCompiledPath(registry, name)
|
|
44
|
-
|
|
45
|
-
if (!def)
|
|
46
|
-
return null;
|
|
47
|
-
if (!def.path)
|
|
48
|
-
return null;
|
|
49
|
-
let compiled = registry.compiled.get(name);
|
|
50
|
-
if (!compiled) {
|
|
51
|
-
compiled = compilePath(def.path);
|
|
52
|
-
registry.compiled.set(name, compiled);
|
|
53
|
-
}
|
|
54
|
-
return compiled;
|
|
55
|
-
}
|
|
56
|
-
//# sourceMappingURL=registry.js.map
|
|
39
|
+
export declare function getCompiledPath(registry: RegistryState, name: string): CompiledPath | null;
|
|
40
|
+
export {};
|
package/src/url/registry.ts
CHANGED
|
@@ -12,9 +12,9 @@
|
|
|
12
12
|
* public API (test/integration use only).
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
-
import type { CompiledPath } from './compile
|
|
16
|
-
import { compilePath } from './compile
|
|
17
|
-
import type { RouteMap } from '../types
|
|
15
|
+
import type { CompiledPath } from './compile';
|
|
16
|
+
import { compilePath } from './compile';
|
|
17
|
+
import type { RouteMap } from '../types';
|
|
18
18
|
|
|
19
19
|
interface RegistryState {
|
|
20
20
|
readonly routes: RouteMap;
|