@sigx/lynx-navigation 0.1.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 (79) hide show
  1. package/LICENSE +21 -0
  2. package/dist/components/EdgeBackHandle.d.ts +2 -0
  3. package/dist/components/EdgeBackHandle.d.ts.map +1 -0
  4. package/dist/components/Link.d.ts +61 -0
  5. package/dist/components/Link.d.ts.map +1 -0
  6. package/dist/components/Link.js +54 -0
  7. package/dist/components/Link.js.map +1 -0
  8. package/dist/components/NavigationRoot.d.ts +37 -0
  9. package/dist/components/NavigationRoot.d.ts.map +1 -0
  10. package/dist/components/NavigationRoot.js +41 -0
  11. package/dist/components/NavigationRoot.js.map +1 -0
  12. package/dist/components/ScreenContainer.d.ts +18 -0
  13. package/dist/components/ScreenContainer.d.ts.map +1 -0
  14. package/dist/components/Stack.d.ts +21 -0
  15. package/dist/components/Stack.d.ts.map +1 -0
  16. package/dist/components/Stack.js +39 -0
  17. package/dist/components/Stack.js.map +1 -0
  18. package/dist/define-routes.d.ts +31 -0
  19. package/dist/define-routes.d.ts.map +1 -0
  20. package/dist/define-routes.js +32 -0
  21. package/dist/define-routes.js.map +1 -0
  22. package/dist/hooks/use-hardware-back.d.ts +31 -0
  23. package/dist/hooks/use-hardware-back.d.ts.map +1 -0
  24. package/dist/hooks/use-nav-internal.d.ts +37 -0
  25. package/dist/hooks/use-nav-internal.d.ts.map +1 -0
  26. package/dist/hooks/use-nav-internal.js +12 -0
  27. package/dist/hooks/use-nav-internal.js.map +1 -0
  28. package/dist/hooks/use-nav.d.ts +77 -0
  29. package/dist/hooks/use-nav.d.ts.map +1 -0
  30. package/dist/hooks/use-nav.js +11 -0
  31. package/dist/hooks/use-nav.js.map +1 -0
  32. package/dist/hooks/use-params.d.ts +19 -0
  33. package/dist/hooks/use-params.d.ts.map +1 -0
  34. package/dist/hooks/use-params.js +22 -0
  35. package/dist/hooks/use-params.js.map +1 -0
  36. package/dist/hooks/use-search.d.ts +11 -0
  37. package/dist/hooks/use-search.d.ts.map +1 -0
  38. package/dist/hooks/use-search.js +14 -0
  39. package/dist/hooks/use-search.js.map +1 -0
  40. package/dist/href.d.ts +40 -0
  41. package/dist/href.d.ts.map +1 -0
  42. package/dist/href.js +14 -0
  43. package/dist/href.js.map +1 -0
  44. package/dist/index.d.ts +21 -0
  45. package/dist/index.d.ts.map +1 -0
  46. package/dist/index.js +15 -0
  47. package/dist/index.js.map +1 -0
  48. package/dist/internal/screen-width.d.ts +16 -0
  49. package/dist/internal/screen-width.d.ts.map +1 -0
  50. package/dist/navigator/core.d.ts +51 -0
  51. package/dist/navigator/core.d.ts.map +1 -0
  52. package/dist/navigator/core.js +149 -0
  53. package/dist/navigator/core.js.map +1 -0
  54. package/dist/register.d.ts +38 -0
  55. package/dist/register.d.ts.map +1 -0
  56. package/dist/register.js +2 -0
  57. package/dist/register.js.map +1 -0
  58. package/dist/types.d.ts +162 -0
  59. package/dist/types.d.ts.map +1 -0
  60. package/dist/types.js +9 -0
  61. package/dist/types.js.map +1 -0
  62. package/package.json +39 -0
  63. package/src/components/EdgeBackHandle.tsx +161 -0
  64. package/src/components/Link.tsx +113 -0
  65. package/src/components/NavigationRoot.tsx +85 -0
  66. package/src/components/ScreenContainer.tsx +101 -0
  67. package/src/components/Stack.tsx +99 -0
  68. package/src/define-routes.ts +33 -0
  69. package/src/hooks/use-hardware-back.ts +50 -0
  70. package/src/hooks/use-nav-internal.ts +47 -0
  71. package/src/hooks/use-nav.ts +118 -0
  72. package/src/hooks/use-params.ts +23 -0
  73. package/src/hooks/use-search.ts +15 -0
  74. package/src/href.ts +58 -0
  75. package/src/index.ts +38 -0
  76. package/src/internal/screen-width.ts +34 -0
  77. package/src/navigator/core.ts +386 -0
  78. package/src/register.ts +41 -0
  79. package/src/types.ts +171 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Andreas Ekdahl
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,2 @@
1
+ export declare const EdgeBackHandle: import("@sigx/runtime-core").ComponentFactory<{}, void, unknown>;
2
+ //# sourceMappingURL=EdgeBackHandle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EdgeBackHandle.d.ts","sourceRoot":"","sources":["../../src/components/EdgeBackHandle.tsx"],"names":[],"mappings":"AA+DA,eAAO,MAAM,cAAc,kEAiGzB,CAAC"}
@@ -0,0 +1,61 @@
1
+ import type { RouteId, RouteParams, RouteSearch } from '../register.js';
2
+ import type { RoutesWithParams } from '../hooks/use-nav.js';
3
+ /**
4
+ * Per-route conditional props for `<Link>`.
5
+ *
6
+ * Mapped over `RouteId`, then indexed by `RouteId` to flatten into a union.
7
+ * Each branch enforces the `params`-required-iff-route-has-schema rule:
8
+ *
9
+ * - `<Link to="profile" />` → TS error (profile requires params)
10
+ * - `<Link to="profile" params={...} />` → ok
11
+ * - `<Link to="home" />` → ok (home has no params)
12
+ * - `<Link to="home" params={...} />` → TS error (home accepts no params)
13
+ *
14
+ * Same per-route discrimination as `nav.push`, expressed as a JSX-friendly
15
+ * union rather than overloads.
16
+ */
17
+ type LinkPropsByRoute = {
18
+ [K in RouteId]: K extends RoutesWithParams ? {
19
+ to: K;
20
+ params: RouteParams<K>;
21
+ search?: RouteSearch<K>;
22
+ } : {
23
+ to: K;
24
+ params?: undefined;
25
+ search?: RouteSearch<K>;
26
+ };
27
+ }[RouteId];
28
+ /**
29
+ * Public type for `<Link>`'s props. The conditional `LinkPropsByRoute` carries
30
+ * the typed `to`/`params`/`search` triple; the rest are simple optionals.
31
+ *
32
+ * `children` is declared explicitly because the public type is exposed via a
33
+ * type-cast (so JSX sees a function-shaped signature). The cast strips sigx's
34
+ * built-in `Define.Slot<'default'>` → JSX-children wiring, so we add a
35
+ * permissive `children?` slot ourselves.
36
+ */
37
+ export type LinkProps = LinkPropsByRoute & {
38
+ /** Use `replace` instead of `push` (no new history entry). */
39
+ replace?: boolean;
40
+ /** Link content rendered inside the tappable container. */
41
+ children?: unknown;
42
+ };
43
+ /**
44
+ * Declarative navigation. Same typing as `nav.push` — pass `params` only when
45
+ * the route declares a schema. Wraps a `<view>` that fires `nav.push` (or
46
+ * `nav.replace` if `replace` is set) on tap.
47
+ *
48
+ * @example
49
+ * ```tsx
50
+ * <Link to="home">Home</Link>
51
+ * <Link to="profile" params={{ id: '42' }}>View profile</Link>
52
+ * <Link to="profile" params={{ id: '42' }} search={{ tab: 'about' }}>About</Link>
53
+ * <Link to="settings" replace>Settings (no back)</Link>
54
+ * ```
55
+ *
56
+ * The cast widens the inferred prop type from the loose impl to the strict
57
+ * `LinkProps` so JSX usage gets per-route discrimination. Runtime is identical.
58
+ */
59
+ export declare const Link: (props: LinkProps) => unknown;
60
+ export {};
61
+ //# sourceMappingURL=Link.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Link.d.ts","sourceRoot":"","sources":["../../src/components/Link.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AACxE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAE5D;;;;;;;;;;;;;GAaG;AACH,KAAK,gBAAgB,GAAG;KACnB,CAAC,IAAI,OAAO,GAAG,CAAC,SAAS,gBAAgB,GACpC;QAAE,EAAE,EAAE,CAAC,CAAC;QAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;QAAC,MAAM,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,CAAA;KAAE,GAC1D;QAAE,EAAE,EAAE,CAAC,CAAC;QAAC,MAAM,CAAC,EAAE,SAAS,CAAC;QAAC,MAAM,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,CAAA;KAAE;CAC/D,CAAC,OAAO,CAAC,CAAC;AAEX;;;;;;;;GAQG;AACH,MAAM,MAAM,SAAS,GAAG,gBAAgB,GAAG;IACvC,8DAA8D;IAC9D,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAwDF;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,IAAI,EAA0B,CAAC,KAAK,EAAE,SAAS,KAAK,OAAO,CAAC"}
@@ -0,0 +1,54 @@
1
+ import { jsx as _jsx } from "@sigx/lynx/jsx-runtime";
2
+ import { component } from '@sigx/lynx';
3
+ import { useNav } from '../hooks/use-nav.js';
4
+ import { useNavRoutes } from '../hooks/use-nav-internal.js';
5
+ const LinkImpl = component(({ props, slots }) => {
6
+ const nav = useNav();
7
+ const routes = useNavRoutes();
8
+ const handlePress = () => {
9
+ const route = props.to;
10
+ const routeDef = routes[route];
11
+ if (!routeDef) {
12
+ // Defensive: prop was typed against the registry, so this shouldn't
13
+ // happen at runtime — but if it does (e.g. a stale Link survived a
14
+ // route removal), surface a clear error rather than crashing on
15
+ // the navigator's lookup.
16
+ throw new Error(`[lynx-navigation] <Link to='${route}'>: route is not registered.`);
17
+ }
18
+ const hasParams = !!routeDef.params;
19
+ const action = props.replace ? nav.replace : nav.push;
20
+ // Branch on whether the route declares a params schema so positional
21
+ // args land correctly: routes-with-params shift everything one slot
22
+ // (push/replace overload signatures `(name, params, search?, options?)`
23
+ // vs `(name, search?, options?)`). Calling the wrong shape silently
24
+ // puts `search` into the `options` slot.
25
+ if (hasParams) {
26
+ action(route, props.params, props.search);
27
+ }
28
+ else {
29
+ action(route, props.search);
30
+ }
31
+ };
32
+ return () => (
33
+ // `bindtap` is correct here because the underlying element is a Lynx
34
+ // native `<view>` — sigx component-level events would use `onPress`.
35
+ _jsx("view", { bindtap: handlePress, children: slots.default?.() }));
36
+ }, { name: 'Link' });
37
+ /**
38
+ * Declarative navigation. Same typing as `nav.push` — pass `params` only when
39
+ * the route declares a schema. Wraps a `<view>` that fires `nav.push` (or
40
+ * `nav.replace` if `replace` is set) on tap.
41
+ *
42
+ * @example
43
+ * ```tsx
44
+ * <Link to="home">Home</Link>
45
+ * <Link to="profile" params={{ id: '42' }}>View profile</Link>
46
+ * <Link to="profile" params={{ id: '42' }} search={{ tab: 'about' }}>About</Link>
47
+ * <Link to="settings" replace>Settings (no back)</Link>
48
+ * ```
49
+ *
50
+ * The cast widens the inferred prop type from the loose impl to the strict
51
+ * `LinkProps` so JSX usage gets per-route discrimination. Runtime is identical.
52
+ */
53
+ export const Link = LinkImpl;
54
+ //# sourceMappingURL=Link.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Link.js","sourceRoot":"","sources":["../../src/components/Link.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAe,MAAM,YAAY,CAAC;AACpD,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAqD5D,MAAM,QAAQ,GAAG,SAAS,CAAiB,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE;IAC5D,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;IACrB,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;IAE9B,MAAM,WAAW,GAAG,GAAS,EAAE;QAC3B,MAAM,KAAK,GAAG,KAAK,CAAC,EAAE,CAAC;QACvB,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;QAC/B,IAAI,CAAC,QAAQ,EAAE,CAAC;YACZ,oEAAoE;YACpE,mEAAmE;YACnE,gEAAgE;YAChE,0BAA0B;YAC1B,MAAM,IAAI,KAAK,CACX,+BAA+B,KAAK,8BAA8B,CACrE,CAAC;QACN,CAAC;QACD,MAAM,SAAS,GAAG,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC;QACpC,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC;QACtD,qEAAqE;QACrE,oEAAoE;QACpE,wEAAwE;QACxE,oEAAoE;QACpE,yCAAyC;QACzC,IAAI,SAAS,EAAE,CAAC;YACX,MAAuD,CACpD,KAAK,EACL,KAAK,CAAC,MAAM,EACZ,KAAK,CAAC,MAAM,CACf,CAAC;QACN,CAAC;aAAM,CAAC;YACH,MAA2C,CAAC,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;QACtE,CAAC;IACL,CAAC,CAAC;IAEF,OAAO,GAAG,EAAE,CAAC;IACT,qEAAqE;IACrE,qEAAqE;IACrE,eAAM,OAAO,EAAE,WAAW,YAAG,KAAK,CAAC,OAAO,EAAE,EAAE,GAAQ,CACzD,CAAC;AACN,CAAC,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;AAErB;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,QAAoD,CAAC"}
@@ -0,0 +1,37 @@
1
+ import { type Define } from '@sigx/lynx';
2
+ import type { RouteId } from '../register.js';
3
+ import type { RouteMap } from '../types.js';
4
+ type NavigationRootProps = Define.Prop<'routes', RouteMap, true> & Define.Prop<'initialRoute', RouteId> & Define.Prop<'initialParams', Record<string, unknown>> & Define.Prop<'initialSearch', Record<string, unknown>>
5
+ /**
6
+ * Enable slide-from-right transitions on push/pop. Defaults to true.
7
+ * Tests against `@sigx/testing-lynx` (which doesn't have an MT runtime)
8
+ * should pass `animated={false}` so navigations commit synchronously.
9
+ */
10
+ & Define.Prop<'animated', boolean>
11
+ /**
12
+ * Enable the iOS-style edge-swipe-back gesture. Defaults to true. Set
13
+ * to false if it conflicts with screen content on the leftmost 20px,
14
+ * or while debugging gesture issues.
15
+ */
16
+ & Define.Prop<'edgeSwipeEnabled', boolean> & Define.Slot<'default'>;
17
+ /**
18
+ * Root of a navigator subtree.
19
+ *
20
+ * Creates a fresh `NavigatorState` from `routes` and provides it via
21
+ * `defineProvide`, so descendant `<Stack>` / `<Screen>` components and any
22
+ * `useNav()` / `useParams()` calls resolve through this instance.
23
+ *
24
+ * The bottom-of-stack entry is built from `initialRoute` (defaults to the
25
+ * first key in `routes`). For routes that declare a params schema, you must
26
+ * pass `initialParams` matching that schema.
27
+ *
28
+ * Mirrors the install pattern of `@sigx/router` (see
29
+ * `packages/router/src/router.ts:519-528`), but at component scope rather than
30
+ * `app.use(router)` — no app-wide singleton, so multi-navigator apps and
31
+ * tests get isolated state for free.
32
+ */
33
+ export declare const NavigationRoot: import("@sigx/runtime-core").ComponentFactory<NavigationRootProps, void, {
34
+ default: () => import("@sigx/runtime-core").JSXElement | import("@sigx/runtime-core").JSXElement[] | null;
35
+ }>;
36
+ export {};
37
+ //# sourceMappingURL=NavigationRoot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NavigationRoot.d.ts","sourceRoot":"","sources":["../../src/components/NavigationRoot.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA4C,KAAK,MAAM,EAAE,MAAM,YAAY,CAAC;AAInF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,KAAK,EAAgB,QAAQ,EAAc,MAAM,aAAa,CAAC;AAEtE,KAAK,mBAAmB,GAClB,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,CAAC,GACrC,MAAM,CAAC,IAAI,CAAC,cAAc,EAAE,OAAO,CAAC,GACpC,MAAM,CAAC,IAAI,CAAC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GACrD,MAAM,CAAC,IAAI,CAAC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AACvD;;;;GAIG;GACD,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC;AAClC;;;;GAIG;GACD,MAAM,CAAC,IAAI,CAAC,kBAAkB,EAAE,OAAO,CAAC,GACxC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;AAE7B;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,cAAc;;EA0CzB,CAAC"}
@@ -0,0 +1,41 @@
1
+ import { component, defineProvide } from '@sigx/lynx';
2
+ import { createNavigatorState } from '../navigator/core.js';
3
+ import { useNav } from '../hooks/use-nav.js';
4
+ import { useNavRoutes } from '../hooks/use-nav-internal.js';
5
+ /**
6
+ * Root of a navigator subtree.
7
+ *
8
+ * Creates a fresh `NavigatorState` from `routes` and provides it via
9
+ * `defineProvide`, so descendant `<Stack>` / `<Screen>` components and any
10
+ * `useNav()` / `useParams()` calls resolve through this instance.
11
+ *
12
+ * The bottom-of-stack entry is built from `initialRoute` (defaults to the
13
+ * first key in `routes`). For routes that declare a params schema, you must
14
+ * pass `initialParams` matching that schema.
15
+ *
16
+ * Mirrors the install pattern of `@sigx/router` (see
17
+ * `packages/router/src/router.ts:519-528`), but at component scope rather than
18
+ * `app.use(router)` — no app-wide singleton, so multi-navigator apps and
19
+ * tests get isolated state for free.
20
+ */
21
+ export const NavigationRoot = component(({ props, slots }) => {
22
+ const routes = props.routes;
23
+ const initialName = props.initialRoute ?? Object.keys(routes)[0];
24
+ if (!routes[initialName]) {
25
+ throw new Error(`[lynx-navigation] <NavigationRoot> initialRoute='${initialName}' is not in the routes registry.`);
26
+ }
27
+ const initialPresentation = routes[initialName].presentation ?? 'card';
28
+ const initial = {
29
+ key: 'root',
30
+ route: initialName,
31
+ params: props.initialParams ?? {},
32
+ search: props.initialSearch ?? {},
33
+ state: undefined,
34
+ presentation: initialPresentation,
35
+ };
36
+ const navState = createNavigatorState(routes, initial);
37
+ defineProvide(useNav, () => navState.nav);
38
+ defineProvide(useNavRoutes, () => navState.routes);
39
+ return () => slots.default?.();
40
+ });
41
+ //# sourceMappingURL=NavigationRoot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NavigationRoot.js","sourceRoot":"","sources":["../../src/components/NavigationRoot.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,aAAa,EAAe,MAAM,YAAY,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAW5D;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,SAAS,CAAsB,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE;IAC9E,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;IAC5B,MAAM,WAAW,GAAW,KAAK,CAAC,YAAY,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IACzE,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CACX,oDAAoD,WAAW,kCAAkC,CACpG,CAAC;IACN,CAAC;IACD,MAAM,mBAAmB,GAAiB,MAAM,CAAC,WAAW,CAAC,CAAC,YAAY,IAAI,MAAM,CAAC;IACrF,MAAM,OAAO,GAAe;QACxB,GAAG,EAAE,MAAM;QACX,KAAK,EAAE,WAAW;QAClB,MAAM,EAAE,KAAK,CAAC,aAAa,IAAI,EAAE;QACjC,MAAM,EAAE,KAAK,CAAC,aAAa,IAAI,EAAE;QACjC,KAAK,EAAE,SAAS;QAChB,YAAY,EAAE,mBAAmB;KACpC,CAAC;IAEF,MAAM,QAAQ,GAAG,oBAAoB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAEvD,aAAa,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IAC1C,aAAa,CAAC,YAAY,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IAEnD,OAAO,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;AACnC,CAAC,CAAC,CAAC"}
@@ -0,0 +1,18 @@
1
+ import { type ComponentFactory, type Define, type SharedValue } from '@sigx/lynx';
2
+ import type { RouteMap, StackEntry, TransitionKind, TransitionRole } from '../types.js';
3
+ type ScreenContainerProps = Define.Prop<'entry', StackEntry, true> & Define.Prop<'routes', RouteMap, true> & Define.Prop<'role', TransitionRole, true> & Define.Prop<'kind', TransitionKind, true> & Define.Prop<'progress', SharedValue<number>, true>;
4
+ /**
5
+ * Animated screen slot — absolutely positioned, MT-bound translateX driven by
6
+ * the navigator's progress SharedValue. Used during transitions to render the
7
+ * top + underneath entries together.
8
+ *
9
+ * Each instance is keyed by `${entry.key}-${role}-${kind}` in the parent so a
10
+ * role/kind change forces a fresh mount with a fresh `useAnimatedStyle`
11
+ * binding (the binding is set at setup and can't be re-keyed mid-life). State
12
+ * loss across transition boundaries is accepted in v0.2; persistent screen
13
+ * state (scroll position, input fields surviving navigations) is a polish
14
+ * item for Phase 0.5+.
15
+ */
16
+ export declare const ScreenContainer: ComponentFactory<ScreenContainerProps, void, {}>;
17
+ export {};
18
+ //# sourceMappingURL=ScreenContainer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ScreenContainer.d.ts","sourceRoot":"","sources":["../../src/components/ScreenContainer.tsx"],"names":[],"mappings":"AAAA,OAAO,EAIH,KAAK,gBAAgB,EACrB,KAAK,MAAM,EAEX,KAAK,WAAW,EACnB,MAAM,YAAY,CAAC;AAGpB,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAuCxF,KAAK,oBAAoB,GACnB,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,IAAI,CAAC,GACtC,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,CAAC,GACrC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,cAAc,EAAE,IAAI,CAAC,GACzC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,cAAc,EAAE,IAAI,CAAC,GACzC,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC;AAEzD;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,eAAe,kDA+B1B,CAAC"}
@@ -0,0 +1,21 @@
1
+ import { type ComponentFactory } from '@sigx/lynx';
2
+ /**
3
+ * Stack navigator — renders the topmost stack entry's component at rest, or
4
+ * the top + underneath entries during a transition.
5
+ *
6
+ * **Idle**: just the top entry, full-bleed, no transform. The screen
7
+ * component mounts directly so it can use its own layout (no extra absolute
8
+ * positioning that would break percentage heights).
9
+ *
10
+ * **Transitioning**: two `<ScreenContainer>` instances stacked absolutely,
11
+ * each with an MT-driven `translateX` that reads from the navigator's
12
+ * progress `SharedValue`. The host's BG thread doesn't tick per frame —
13
+ * `useAnimatedStyle` runs the interpolation entirely on MT.
14
+ *
15
+ * `key={top.key}` keeps the idle render's component instance stable across
16
+ * unrelated re-renders. During transitions, composite keys
17
+ * (`${entry.key}-${role}-${kind}`) ensure a fresh mount per role/kind pair so
18
+ * the `useAnimatedStyle` binding is set with the right input/output ranges.
19
+ */
20
+ export declare const Stack: ComponentFactory<{}, void, unknown>;
21
+ //# sourceMappingURL=Stack.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Stack.d.ts","sourceRoot":"","sources":["../../src/components/Stack.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAa,KAAK,gBAAgB,EAAoB,MAAM,YAAY,CAAC;AAMhF;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,KAAK,qCA0EhB,CAAC"}
@@ -0,0 +1,39 @@
1
+ import { jsx as _jsx } from "@sigx/lynx/jsx-runtime";
2
+ import { component } from '@sigx/lynx';
3
+ import { useNav } from '../hooks/use-nav.js';
4
+ import { useNavRoutes } from '../hooks/use-nav-internal.js';
5
+ /**
6
+ * Stack navigator — renders the topmost stack entry's component.
7
+ *
8
+ * v0.1 minimal slice: renders only the top entry, with no transition and no
9
+ * preserved-mount lower entries. Phase 0.2 extends this to mount the
10
+ * top-N entries (so back-swipe can show the underlying screen) and runs MTS
11
+ * transition drivers between them.
12
+ *
13
+ * `key={top.key}` forces unmount/remount when the active entry changes — same
14
+ * pattern `@sigx/router`'s `<RouterView>` uses to prevent lazy components
15
+ * from stacking (`packages/router/src/RouterView.tsx:97-98`).
16
+ */
17
+ export const Stack = component(() => {
18
+ const nav = useNav();
19
+ const routes = useNavRoutes();
20
+ return () => {
21
+ const top = nav.current;
22
+ const route = routes[top.route];
23
+ if (!route) {
24
+ // Defensive: navigator state should never reference an unregistered
25
+ // route, but if it does we surface nothing rather than crash.
26
+ return null;
27
+ }
28
+ const Comp = route.component;
29
+ if (typeof Comp !== 'function')
30
+ return null;
31
+ // Phase 0.1 only handles eager component factories. Lazy
32
+ // imports — `() => import(...)` — need a `lazy()` wrapper from sigx;
33
+ // we'll integrate that in the showcase-migration slice.
34
+ const ComponentFactoryRef = Comp;
35
+ const params = top.params;
36
+ return _jsx(ComponentFactoryRef, { ...params }, top.key);
37
+ };
38
+ });
39
+ //# sourceMappingURL=Stack.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Stack.js","sourceRoot":"","sources":["../../src/components/Stack.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAyB,MAAM,YAAY,CAAC;AAC9D,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAE5D;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,SAAS,CAAC,GAAG,EAAE;IAChC,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;IACrB,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;IAE9B,OAAO,GAAG,EAAE;QACR,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC;QACxB,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAChC,IAAI,CAAC,KAAK,EAAE,CAAC;YACT,oEAAoE;YACpE,8DAA8D;YAC9D,OAAO,IAAI,CAAC;QAChB,CAAC;QACD,MAAM,IAAI,GAAG,KAAK,CAAC,SAAS,CAAC;QAC7B,IAAI,OAAO,IAAI,KAAK,UAAU;YAAE,OAAO,IAAI,CAAC;QAC5C,yDAAyD;QACzD,qEAAqE;QACrE,wDAAwD;QACxD,MAAM,mBAAmB,GAAG,IAI3B,CAAC;QACF,MAAM,MAAM,GAAG,GAAG,CAAC,MAAiC,CAAC;QACrD,OAAO,KAAC,mBAAmB,OAAmB,MAAM,IAAnB,GAAG,CAAC,GAAG,CAAgB,CAAC;IAC7D,CAAC,CAAC;AACN,CAAC,CAAC,CAAC"}
@@ -0,0 +1,31 @@
1
+ import type { RouteMap } from './types.js';
2
+ /**
3
+ * Define a typed route registry.
4
+ *
5
+ * Returns the input verbatim at runtime — the function exists for TypeScript
6
+ * inference. The returned type is narrowed to the literal route map so that
7
+ * downstream APIs (`useNav`, `useParams`, `<Link>`) can extract route names
8
+ * and params/search schemas precisely.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * import { defineRoutes } from '@sigx/lynx-navigation';
13
+ * import { z } from 'zod';
14
+ *
15
+ * export const routes = defineRoutes({
16
+ * home: { component: lazy(() => import('./Home')) },
17
+ * profile: {
18
+ * params: z.object({ id: z.string() }),
19
+ * component: lazy(() => import('./Profile')),
20
+ * path: '/users/:id',
21
+ * },
22
+ * });
23
+ *
24
+ * // Then in app entry:
25
+ * declare module '@sigx/lynx-navigation' {
26
+ * interface Register { routes: typeof routes }
27
+ * }
28
+ * ```
29
+ */
30
+ export declare function defineRoutes<const T extends RouteMap>(routes: T): T;
31
+ //# sourceMappingURL=define-routes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define-routes.d.ts","sourceRoot":"","sources":["../src/define-routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,YAAY,CAAC,KAAK,CAAC,CAAC,SAAS,QAAQ,EAAE,MAAM,EAAE,CAAC,GAAG,CAAC,CAEnE"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Define a typed route registry.
3
+ *
4
+ * Returns the input verbatim at runtime — the function exists for TypeScript
5
+ * inference. The returned type is narrowed to the literal route map so that
6
+ * downstream APIs (`useNav`, `useParams`, `<Link>`) can extract route names
7
+ * and params/search schemas precisely.
8
+ *
9
+ * @example
10
+ * ```ts
11
+ * import { defineRoutes } from '@sigx/lynx-navigation';
12
+ * import { z } from 'zod';
13
+ *
14
+ * export const routes = defineRoutes({
15
+ * home: { component: lazy(() => import('./Home')) },
16
+ * profile: {
17
+ * params: z.object({ id: z.string() }),
18
+ * component: lazy(() => import('./Profile')),
19
+ * path: '/users/:id',
20
+ * },
21
+ * });
22
+ *
23
+ * // Then in app entry:
24
+ * declare module '@sigx/lynx-navigation' {
25
+ * interface Register { routes: typeof routes }
26
+ * }
27
+ * ```
28
+ */
29
+ export function defineRoutes(routes) {
30
+ return routes;
31
+ }
32
+ //# sourceMappingURL=define-routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define-routes.js","sourceRoot":"","sources":["../src/define-routes.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,UAAU,YAAY,CAA2B,MAAS;IAC5D,OAAO,MAAM,CAAC;AAClB,CAAC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Wire the Android hardware back button to the active navigator.
3
+ *
4
+ * Listens for `hardwareBackPress` events from `@sigx/lynx-linking`'s
5
+ * `BackHandler` (which the native side dispatches from
6
+ * `MainActivity.onBackPressed`). On press:
7
+ *
8
+ * - If `nav.canGoBack` → `nav.pop()`.
9
+ * - Otherwise → `BackHandler.exitApp()` (Android: `moveTaskToBack(true)`,
10
+ * keeps the bundle warm; iOS: rejects, since iOS doesn't permit
11
+ * programmatic termination).
12
+ *
13
+ * Call this once in any component under `<NavigationRoot>` (typically a
14
+ * thin wrapper sibling to `<Stack />`). iOS doesn't fire the event so the
15
+ * hook is a no-op there.
16
+ *
17
+ * @example
18
+ * ```tsx
19
+ * const BackHandlerWiring = component(() => {
20
+ * useHardwareBack();
21
+ * return () => null;
22
+ * });
23
+ *
24
+ * <NavigationRoot routes={routes}>
25
+ * <BackHandlerWiring />
26
+ * <Stack />
27
+ * </NavigationRoot>
28
+ * ```
29
+ */
30
+ export declare function useHardwareBack(): void;
31
+ //# sourceMappingURL=use-hardware-back.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-hardware-back.d.ts","sourceRoot":"","sources":["../../src/hooks/use-hardware-back.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,eAAe,IAAI,IAAI,CAgBtC"}
@@ -0,0 +1,37 @@
1
+ import { type SharedValue } from '@sigx/lynx';
2
+ import type { RouteMap } from '../types.js';
3
+ /**
4
+ * Internal injectable: the route registry passed into `<NavigationRoot>`.
5
+ * Components (Stack, Screen) read this to look up route definitions by name.
6
+ *
7
+ * Not exported from the package barrel — use `useNav()` for navigation, and
8
+ * the registry is implicit from `<NavigationRoot routes={...}>`.
9
+ */
10
+ export declare const useNavRoutes: import("@sigx/runtime-core").InjectableFunction<RouteMap>;
11
+ /**
12
+ * Internal injectable: low-level navigator handles used by the edge-back
13
+ * gesture. Holds the progress SharedValue (so gesture worklets can write it
14
+ * directly on MT) plus BG-side begin/commit/cancel functions invoked via
15
+ * `runOnBackground` from gesture worklets.
16
+ *
17
+ * `progress` is `null` when the navigator was created with `animated={false}`
18
+ * (e.g. tests). `beginBackGesture` is also a no-op in that case.
19
+ */
20
+ export interface NavInternals {
21
+ /** MT-driven transition progress; null when animations are disabled. */
22
+ readonly progress: SharedValue<number> | null;
23
+ /**
24
+ * Set transition state for a gesture-driven pop. Does not start any
25
+ * automatic animation — the gesture worklet writes `progress` directly
26
+ * per frame, then animates to the commit/cancel endpoint on release.
27
+ */
28
+ beginBackGesture(): void;
29
+ /** Commit the back gesture: pop top entry + clear transition. */
30
+ commitBackGesture(): void;
31
+ /** Cancel the back gesture: clear transition without popping. */
32
+ cancelBackGesture(): void;
33
+ /** Whether the user opted into the edge-swipe-back gesture. */
34
+ readonly edgeSwipeEnabled: boolean;
35
+ }
36
+ export declare const useNavInternals: import("@sigx/runtime-core").InjectableFunction<NavInternals>;
37
+ //# sourceMappingURL=use-nav-internal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-nav-internal.d.ts","sourceRoot":"","sources":["../../src/hooks/use-nav-internal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AAChE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C;;;;;;GAMG;AACH,eAAO,MAAM,YAAY,2DAIvB,CAAC;AAEH;;;;;;;;GAQG;AACH,MAAM,WAAW,YAAY;IACzB,wEAAwE;IACxE,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;IAC9C;;;;OAIG;IACH,gBAAgB,IAAI,IAAI,CAAC;IACzB,iEAAiE;IACjE,iBAAiB,IAAI,IAAI,CAAC;IAC1B,iEAAiE;IACjE,iBAAiB,IAAI,IAAI,CAAC;IAC1B,+DAA+D;IAC/D,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC;CACtC;AAED,eAAO,MAAM,eAAe,+DAI1B,CAAC"}
@@ -0,0 +1,12 @@
1
+ import { defineInjectable } from '@sigx/lynx';
2
+ /**
3
+ * Internal injectable: the route registry passed into `<NavigationRoot>`.
4
+ * Components (Stack, Screen) read this to look up route definitions by name.
5
+ *
6
+ * Not exported from the package barrel — use `useNav()` for navigation, and
7
+ * the registry is implicit from `<NavigationRoot routes={...}>`.
8
+ */
9
+ export const useNavRoutes = defineInjectable(() => {
10
+ throw new Error('[lynx-navigation] No <NavigationRoot> found in the component tree.');
11
+ });
12
+ //# sourceMappingURL=use-nav-internal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-nav-internal.js","sourceRoot":"","sources":["../../src/hooks/use-nav-internal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAG9C;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,gBAAgB,CAAW,GAAG,EAAE;IACxD,MAAM,IAAI,KAAK,CACX,oEAAoE,CACvE,CAAC;AACN,CAAC,CAAC,CAAC"}
@@ -0,0 +1,77 @@
1
+ import type { RegisteredRoutes, RouteId, RouteParams, RouteSearch } from '../register.js';
2
+ import type { PopOptions, PushOptions, RouteRequiresParams, StackEntry, TransitionState } from '../types.js';
3
+ /**
4
+ * Subset of registered route names that declare a `params` schema (and so
5
+ * require a `params` argument when navigating).
6
+ *
7
+ * Computed via mapped-type filtering rather than a conditional inside the
8
+ * method signature: when a conditional like `RouteRequiresParams<R[K]>` is
9
+ * embedded inside a generic method parameter, TS evaluates it at definition
10
+ * time with K bound to the *whole* union of route ids — which distributes
11
+ * `RouteRequiresParams` over every route and collapses the result to
12
+ * `boolean`, breaking the conditional. Filtering once at the type level avoids
13
+ * the issue and produces clean overload candidates.
14
+ */
15
+ export type RoutesWithParams = {
16
+ [K in RouteId]: RouteRequiresParams<RegisteredRoutes[K]> extends true ? K : never;
17
+ }[RouteId];
18
+ /** Routes that don't declare a `params` schema. */
19
+ export type RoutesWithoutParams = Exclude<RouteId, RoutesWithParams>;
20
+ /**
21
+ * The navigator handle returned by `useNav()`.
22
+ *
23
+ * Read access (`current`, `stack`, `canGoBack`) is reactive — these properties
24
+ * are getters that read from the underlying stack signal, so accessing them
25
+ * inside a component's render function (or inside `effect` / `computed`) takes
26
+ * a reactive dependency. Mutating methods (`push`, `pop`, etc.) trigger the
27
+ * dependents to update.
28
+ *
29
+ * `push` and `replace` are split into two overloads — one for routes without a
30
+ * params schema (no params arg) and one for routes with a params schema
31
+ * (params required). See `RoutesWithParams` above for why this isn't a single
32
+ * conditional return type.
33
+ */
34
+ export interface Nav {
35
+ /** Push a route that has no params schema. */
36
+ push<K extends RoutesWithoutParams>(name: K, search?: RouteSearch<K>, options?: PushOptions): void;
37
+ /** Push a route that requires params. */
38
+ push<K extends RoutesWithParams>(name: K, params: RouteParams<K>, search?: RouteSearch<K>, options?: PushOptions): void;
39
+ /** Replace the top entry — same overload pattern as push. */
40
+ replace<K extends RoutesWithoutParams>(name: K, search?: RouteSearch<K>, options?: PushOptions): void;
41
+ replace<K extends RoutesWithParams>(name: K, params: RouteParams<K>, search?: RouteSearch<K>, options?: PushOptions): void;
42
+ /** Pop one or more entries off the top of the stack. */
43
+ pop(count?: number, options?: PopOptions): void;
44
+ /** Pop entries until the named route is at the top. */
45
+ popTo<K extends RouteId>(name: K): void;
46
+ /** Pop all the way to the root entry. */
47
+ popToRoot(): void;
48
+ /** Wholesale-replace the stack. */
49
+ reset(state: {
50
+ stack: ReadonlyArray<StackEntry>;
51
+ }): void;
52
+ /** Dismiss the topmost modal stack (no-op if none active). */
53
+ dismiss(): void;
54
+ /** Currently-focused entry. Reactive via property access. */
55
+ readonly current: StackEntry;
56
+ /** Full stack, top last. Reactive. */
57
+ readonly stack: ReadonlyArray<StackEntry>;
58
+ /** Whether the user can go back from the current entry. Reactive. */
59
+ readonly canGoBack: boolean;
60
+ /** Parent navigator (e.g. the Tabs above this Stack), or null at the root. */
61
+ readonly parent: Nav | null;
62
+ /**
63
+ * In-flight transition, or null when navigation is at rest. Reactive —
64
+ * `<Stack>` reads this to decide whether to render one screen or two
65
+ * (during a slide transition both the outgoing and incoming screens
66
+ * stay mounted with `useAnimatedStyle`-driven transforms).
67
+ */
68
+ readonly transition: TransitionState | null;
69
+ }
70
+ /**
71
+ * Access the innermost navigator. Provided by `<NavigationRoot>` via
72
+ * `defineProvide`. Throws when called outside a NavigationRoot subtree.
73
+ *
74
+ * Mirrors `@sigx/router`'s `useRouter` pattern (`packages/router/src/router.ts:30`).
75
+ */
76
+ export declare const useNav: import("@sigx/runtime-core").InjectableFunction<Nav>;
77
+ //# sourceMappingURL=use-nav.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-nav.d.ts","sourceRoot":"","sources":["../../src/hooks/use-nav.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC1F,OAAO,KAAK,EACR,UAAU,EACV,WAAW,EACX,mBAAmB,EACnB,UAAU,EACV,eAAe,EAClB,MAAM,aAAa,CAAC;AAErB;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,gBAAgB,GAAG;KAC1B,CAAC,IAAI,OAAO,GAAG,mBAAmB,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,SAAS,IAAI,GAAG,CAAC,GAAG,KAAK;CACpF,CAAC,OAAO,CAAC,CAAC;AAEX,mDAAmD;AACnD,MAAM,MAAM,mBAAmB,GAAG,OAAO,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC;AAErE;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,GAAG;IAChB,8CAA8C;IAC9C,IAAI,CAAC,CAAC,SAAS,mBAAmB,EAC9B,IAAI,EAAE,CAAC,EACP,MAAM,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,EACvB,OAAO,CAAC,EAAE,WAAW,GACtB,IAAI,CAAC;IACR,yCAAyC;IACzC,IAAI,CAAC,CAAC,SAAS,gBAAgB,EAC3B,IAAI,EAAE,CAAC,EACP,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,EACtB,MAAM,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,EACvB,OAAO,CAAC,EAAE,WAAW,GACtB,IAAI,CAAC;IAER,6DAA6D;IAC7D,OAAO,CAAC,CAAC,SAAS,mBAAmB,EACjC,IAAI,EAAE,CAAC,EACP,MAAM,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,EACvB,OAAO,CAAC,EAAE,WAAW,GACtB,IAAI,CAAC;IACR,OAAO,CAAC,CAAC,SAAS,gBAAgB,EAC9B,IAAI,EAAE,CAAC,EACP,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,EACtB,MAAM,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,EACvB,OAAO,CAAC,EAAE,WAAW,GACtB,IAAI,CAAC;IAER,wDAAwD;IACxD,GAAG,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;IAEhD,uDAAuD;IACvD,KAAK,CAAC,CAAC,SAAS,OAAO,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC;IAExC,yCAAyC;IACzC,SAAS,IAAI,IAAI,CAAC;IAElB,mCAAmC;IACnC,KAAK,CAAC,KAAK,EAAE;QAAE,KAAK,EAAE,aAAa,CAAC,UAAU,CAAC,CAAA;KAAE,GAAG,IAAI,CAAC;IAEzD,8DAA8D;IAC9D,OAAO,IAAI,IAAI,CAAC;IAEhB,6DAA6D;IAC7D,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;IAE7B,sCAAsC;IACtC,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC;IAE1C,qEAAqE;IACrE,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAE5B,8EAA8E;IAC9E,QAAQ,CAAC,MAAM,EAAE,GAAG,GAAG,IAAI,CAAC;IAE5B;;;;;OAKG;IACH,QAAQ,CAAC,UAAU,EAAE,eAAe,GAAG,IAAI,CAAC;CAC/C;AAED;;;;;GAKG;AACH,eAAO,MAAM,MAAM,sDAIjB,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { defineInjectable } from '@sigx/lynx';
2
+ /**
3
+ * Access the innermost navigator. Provided by `<NavigationRoot>` via
4
+ * `defineProvide`. Throws when called outside a NavigationRoot subtree.
5
+ *
6
+ * Mirrors `@sigx/router`'s `useRouter` pattern (`packages/router/src/router.ts:30`).
7
+ */
8
+ export const useNav = defineInjectable(() => {
9
+ throw new Error('[lynx-navigation] useNav() called but no <NavigationRoot> is mounted in the component tree.');
10
+ });
11
+ //# sourceMappingURL=use-nav.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-nav.js","sourceRoot":"","sources":["../../src/hooks/use-nav.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AA6F9C;;;;;GAKG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,gBAAgB,CAAM,GAAG,EAAE;IAC7C,MAAM,IAAI,KAAK,CACX,6FAA6F,CAChG,CAAC;AACN,CAAC,CAAC,CAAC"}
@@ -0,0 +1,19 @@
1
+ import type { RouteId, RouteParams } from '../register.js';
2
+ /**
3
+ * Read the typed params for the current screen, asserted against the named
4
+ * route from the registry.
5
+ *
6
+ * Returns the current entry's params snapshot. The `name` arg is the type
7
+ * discriminator at compile time; we don't currently runtime-check that the
8
+ * caller's route matches the active entry — the dev-mode warning lands in a
9
+ * later slice along with schema validation.
10
+ *
11
+ * **Reactivity**: each `nav.push` / `replace` produces a new entry with a
12
+ * fresh `key`. `<Stack>` keys the rendered component on `entry.key`, so the
13
+ * screen component fully remounts on every navigation — useParams runs again
14
+ * during the new mount and reads the new params. There is no "in-place params
15
+ * update for the same mounted screen" path in v0.1, so a snapshot at setup
16
+ * time is correct.
17
+ */
18
+ export declare function useParams<K extends RouteId>(_name: K): RouteParams<K>;
19
+ //# sourceMappingURL=use-params.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-params.d.ts","sourceRoot":"","sources":["../../src/hooks/use-params.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAG3D;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,SAAS,CAAC,CAAC,SAAS,OAAO,EAAE,KAAK,EAAE,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAGrE"}