@sigx/lynx-navigation 0.1.0 → 0.1.2

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 (139) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +355 -0
  3. package/dist/components/Drawer.d.ts +56 -0
  4. package/dist/components/Drawer.d.ts.map +1 -0
  5. package/dist/components/Drawer.js +74 -0
  6. package/dist/components/Drawer.js.map +1 -0
  7. package/dist/components/EdgeBackHandle.js +144 -0
  8. package/dist/components/EdgeBackHandle.js.map +1 -0
  9. package/dist/components/EntryScope.d.ts +26 -0
  10. package/dist/components/EntryScope.d.ts.map +1 -0
  11. package/dist/components/EntryScope.js +33 -0
  12. package/dist/components/EntryScope.js.map +1 -0
  13. package/dist/components/Header.d.ts +7 -0
  14. package/dist/components/Header.d.ts.map +1 -0
  15. package/dist/components/Header.js +103 -0
  16. package/dist/components/Header.js.map +1 -0
  17. package/dist/components/Link.js +1 -4
  18. package/dist/components/Link.js.map +1 -1
  19. package/dist/components/NavigationRoot.d.ts +1 -1
  20. package/dist/components/NavigationRoot.d.ts.map +1 -1
  21. package/dist/components/NavigationRoot.js +29 -3
  22. package/dist/components/NavigationRoot.js.map +1 -1
  23. package/dist/components/Screen.d.ts +98 -0
  24. package/dist/components/Screen.d.ts.map +1 -0
  25. package/dist/components/Screen.js +94 -0
  26. package/dist/components/Screen.js.map +1 -0
  27. package/dist/components/ScreenContainer.d.ts.map +1 -1
  28. package/dist/components/ScreenContainer.js +77 -0
  29. package/dist/components/ScreenContainer.js.map +1 -0
  30. package/dist/components/Stack.d.ts.map +1 -1
  31. package/dist/components/Stack.js +60 -24
  32. package/dist/components/Stack.js.map +1 -1
  33. package/dist/components/TabBar.d.ts +40 -0
  34. package/dist/components/TabBar.d.ts.map +1 -0
  35. package/dist/components/TabBar.js +63 -0
  36. package/dist/components/TabBar.js.map +1 -0
  37. package/dist/components/Tabs.d.ts +101 -0
  38. package/dist/components/Tabs.d.ts.map +1 -0
  39. package/dist/components/Tabs.js +140 -0
  40. package/dist/components/Tabs.js.map +1 -0
  41. package/dist/hooks/use-focus.d.ts +46 -0
  42. package/dist/hooks/use-focus.d.ts.map +1 -0
  43. package/dist/hooks/use-focus.js +81 -0
  44. package/dist/hooks/use-focus.js.map +1 -0
  45. package/dist/hooks/use-hardware-back.js +50 -0
  46. package/dist/hooks/use-hardware-back.js.map +1 -0
  47. package/dist/hooks/use-linking-nav.d.ts +92 -0
  48. package/dist/hooks/use-linking-nav.d.ts.map +1 -0
  49. package/dist/hooks/use-linking-nav.js +109 -0
  50. package/dist/hooks/use-linking-nav.js.map +1 -0
  51. package/dist/hooks/use-nav-internal.d.ts +38 -1
  52. package/dist/hooks/use-nav-internal.d.ts.map +1 -1
  53. package/dist/hooks/use-nav-internal.js +32 -0
  54. package/dist/hooks/use-nav-internal.js.map +1 -1
  55. package/dist/hooks/use-nav-serializer.d.ts +83 -0
  56. package/dist/hooks/use-nav-serializer.d.ts.map +1 -0
  57. package/dist/hooks/use-nav-serializer.js +181 -0
  58. package/dist/hooks/use-nav-serializer.js.map +1 -0
  59. package/dist/hooks/use-nav.js.map +1 -1
  60. package/dist/hooks/use-screen-options.d.ts +3 -0
  61. package/dist/hooks/use-screen-options.d.ts.map +1 -0
  62. package/dist/hooks/use-screen-options.js +43 -0
  63. package/dist/hooks/use-screen-options.js.map +1 -0
  64. package/dist/href.d.ts +16 -1
  65. package/dist/href.d.ts.map +1 -1
  66. package/dist/href.js +50 -7
  67. package/dist/href.js.map +1 -1
  68. package/dist/index.d.ts +18 -1
  69. package/dist/index.d.ts.map +1 -1
  70. package/dist/index.js +15 -0
  71. package/dist/index.js.map +1 -1
  72. package/dist/internal/screen-registry.d.ts +49 -0
  73. package/dist/internal/screen-registry.d.ts.map +1 -0
  74. package/dist/internal/screen-registry.js +59 -0
  75. package/dist/internal/screen-registry.js.map +1 -0
  76. package/dist/internal/screen-width.js +30 -0
  77. package/dist/internal/screen-width.js.map +1 -0
  78. package/dist/navigator/core.d.ts +20 -1
  79. package/dist/navigator/core.d.ts.map +1 -1
  80. package/dist/navigator/core.js +231 -36
  81. package/dist/navigator/core.js.map +1 -1
  82. package/dist/types.d.ts +56 -0
  83. package/dist/types.d.ts.map +1 -1
  84. package/dist/url/build.d.ts +16 -0
  85. package/dist/url/build.d.ts.map +1 -0
  86. package/dist/url/build.js +30 -0
  87. package/dist/url/build.js.map +1 -0
  88. package/dist/url/compile.d.ts +35 -0
  89. package/dist/url/compile.d.ts.map +1 -0
  90. package/dist/url/compile.js +83 -0
  91. package/dist/url/compile.js.map +1 -0
  92. package/dist/url/format.d.ts +29 -0
  93. package/dist/url/format.d.ts.map +1 -0
  94. package/dist/url/format.js +102 -0
  95. package/dist/url/format.js.map +1 -0
  96. package/dist/url/index.d.ts +13 -0
  97. package/dist/url/index.d.ts.map +1 -0
  98. package/dist/url/index.js +13 -0
  99. package/dist/url/index.js.map +1 -0
  100. package/dist/url/parse.d.ts +21 -0
  101. package/dist/url/parse.d.ts.map +1 -0
  102. package/dist/url/parse.js +94 -0
  103. package/dist/url/parse.js.map +1 -0
  104. package/dist/url/registry.d.ts +41 -0
  105. package/dist/url/registry.d.ts.map +1 -0
  106. package/dist/url/registry.js +56 -0
  107. package/dist/url/registry.js.map +1 -0
  108. package/dist/url/validate.d.ts +24 -0
  109. package/dist/url/validate.d.ts.map +1 -0
  110. package/dist/url/validate.js +37 -0
  111. package/dist/url/validate.js.map +1 -0
  112. package/package.json +44 -15
  113. package/src/components/Drawer.tsx +119 -0
  114. package/src/components/EdgeBackHandle.tsx +1 -1
  115. package/src/components/EntryScope.tsx +38 -0
  116. package/src/components/Header.tsx +129 -0
  117. package/src/components/NavigationRoot.tsx +9 -1
  118. package/src/components/Screen.tsx +116 -0
  119. package/src/components/ScreenContainer.tsx +14 -1
  120. package/src/components/Stack.tsx +21 -2
  121. package/src/components/TabBar.tsx +104 -0
  122. package/src/components/Tabs.tsx +216 -0
  123. package/src/hooks/use-focus.ts +88 -0
  124. package/src/hooks/use-linking-nav.ts +159 -0
  125. package/src/hooks/use-nav-internal.ts +48 -1
  126. package/src/hooks/use-nav-serializer.ts +239 -0
  127. package/src/hooks/use-screen-options.ts +48 -0
  128. package/src/href.ts +68 -11
  129. package/src/index.ts +29 -0
  130. package/src/internal/screen-registry.ts +89 -0
  131. package/src/navigator/core.ts +86 -4
  132. package/src/types.ts +56 -0
  133. package/src/url/build.ts +35 -0
  134. package/src/url/compile.ts +109 -0
  135. package/src/url/format.ts +95 -0
  136. package/src/url/index.ts +18 -0
  137. package/src/url/parse.ts +102 -0
  138. package/src/url/registry.ts +69 -0
  139. package/src/url/validate.ts +67 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EntryScope.d.ts","sourceRoot":"","sources":["../../src/components/EntryScope.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAyC,KAAK,MAAM,EAAE,MAAM,YAAY,CAAC;AAGhF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,KAAK,eAAe,GACd,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,IAAI,CAAC,GACtC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;AAE7B;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,UAAU;;EAUrB,CAAC"}
@@ -0,0 +1,33 @@
1
+ import { component, defineProvide, onUnmounted } from '@sigx/lynx';
2
+ import { useCurrentEntry, useNavInternals, useScreenRegistry } from '../hooks/use-nav-internal.js';
3
+ import { createScreenRegistry } from '../internal/screen-registry.js';
4
+ /**
5
+ * Provider wrapper for a single screen mount.
6
+ *
7
+ * `<Stack>` and `<ScreenContainer>` instantiate this around each route
8
+ * component so calls to `useIsFocused()` / `useFocusEffect()` /
9
+ * `<Screen>` inside that screen resolve through `useCurrentEntry()` and
10
+ * `useScreenRegistry()` to the entry it was rendered for. Without this
11
+ * wrapper there'd be no per-screen way to know "which stack entry am I?"
12
+ * — the navigator only knows what's currently on top.
13
+ *
14
+ * Also allocates a fresh `ScreenRegistry` per entry and publishes it to
15
+ * the navigator's cross-entry registry map, so persistent chrome (HeaderBar
16
+ * / TabBar — later slices) can read the focused entry's options + slot
17
+ * fills without remounting itself.
18
+ *
19
+ * Renders the default slot directly; no extra layout element is inserted,
20
+ * so this is layout-neutral for the screen it wraps.
21
+ */
22
+ export const EntryScope = component(({ props, slots }) => {
23
+ const internals = useNavInternals();
24
+ const registry = createScreenRegistry(props.entry);
25
+ internals.screens.register(registry);
26
+ onUnmounted(() => {
27
+ internals.screens.unregister(props.entry.key);
28
+ });
29
+ defineProvide(useCurrentEntry, () => props.entry);
30
+ defineProvide(useScreenRegistry, () => registry);
31
+ return () => slots.default?.();
32
+ });
33
+ //# sourceMappingURL=EntryScope.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EntryScope.js","sourceRoot":"","sources":["../../src/components/EntryScope.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,WAAW,EAAe,MAAM,YAAY,CAAC;AAChF,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACnG,OAAO,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AAOtE;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,SAAS,CAAkB,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE;IACtE,MAAM,SAAS,GAAG,eAAe,EAAE,CAAC;IACpC,MAAM,QAAQ,GAAG,oBAAoB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACnD,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACrC,WAAW,CAAC,GAAG,EAAE;QACb,SAAS,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IACH,aAAa,CAAC,eAAe,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAClD,aAAa,CAAC,iBAAiB,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,CAAC;IACjD,OAAO,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;AACnC,CAAC,CAAC,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Persistent header chrome. Mount once above `<Stack>`; reactively follows
3
+ * the focused entry. No props in v1 — styling is a host-app concern,
4
+ * arrived at through the slot fills.
5
+ */
6
+ export declare const Header: import("@sigx/runtime-core").ComponentFactory<{}, void, unknown>;
7
+ //# sourceMappingURL=Header.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Header.d.ts","sourceRoot":"","sources":["../../src/components/Header.tsx"],"names":[],"mappings":"AAkEA;;;;GAIG;AACH,eAAO,MAAM,MAAM,kEAyDjB,CAAC"}
@@ -0,0 +1,103 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "@sigx/lynx/jsx-runtime";
2
+ /**
3
+ * `<Header>` — default navigator header chrome.
4
+ *
5
+ * Reads from the currently-focused entry's `ScreenRegistry`:
6
+ *
7
+ * - If `slots.header` is set, render that (full override).
8
+ * - Else render the default layout: headerLeft (back button when
9
+ * `nav.canGoBack`), title (from `options.title`, or the route name as
10
+ * a fallback), headerRight.
11
+ *
12
+ * Persistent: the Header component itself is mounted once near the root and
13
+ * stays mounted across navigations — it reactively switches its content
14
+ * when `nav.current` changes, rather than being remounted per screen. That
15
+ * matters because mounting cost adds to perceived transition latency.
16
+ *
17
+ * Header chrome is opt-in. Consumers place `<Header />` inside
18
+ * `<NavigationRoot>` above `<Stack />`. We don't auto-inject because:
19
+ * - app shells vary (some want the header inside a `<SafeArea>`, some
20
+ * want a custom toolbar, some want no header at all in tabs).
21
+ * - making it opt-in keeps `<Stack>`'s contract narrow.
22
+ */
23
+ import { component, computed } from '@sigx/lynx';
24
+ import { useNav } from '../hooks/use-nav.js';
25
+ import { useNavInternals } from '../hooks/use-nav-internal.js';
26
+ /**
27
+ * Resolve a title (string or getter) to a plain string.
28
+ *
29
+ * Getter is the more general case; the `<Screen title={() => state.value}>`
30
+ * call site is how reactive titles work. A plain string is wrapped in a
31
+ * trivial closure so consumers always handle one shape.
32
+ */
33
+ function resolveTitle(t, routeName) {
34
+ if (typeof t === 'function')
35
+ return t();
36
+ if (typeof t === 'string')
37
+ return t;
38
+ return routeName;
39
+ }
40
+ /**
41
+ * Default back-button rendering. Plain `<text>` with a tap handler — apps
42
+ * that want an icon or a custom design override via
43
+ * `<Screen.HeaderLeft>`. Kept minimal because there's no shared icon
44
+ * primitive at the navigation layer.
45
+ */
46
+ const DefaultBackButton = component(({ props }) => {
47
+ return () => (_jsx("view", { bindtap: () => props.onPress(), "accessibility-element": true, "accessibility-label": "Back", "accessibility-trait": "button", children: _jsx("text", { children: "\u2039 Back" }) }));
48
+ });
49
+ const DefaultTitle = component(({ props }) => {
50
+ return () => (_jsx("view", { children: _jsx("text", { children: props.text }) }));
51
+ });
52
+ /**
53
+ * Persistent header chrome. Mount once above `<Stack>`; reactively follows
54
+ * the focused entry. No props in v1 — styling is a host-app concern,
55
+ * arrived at through the slot fills.
56
+ */
57
+ export const Header = component(() => {
58
+ const nav = useNav();
59
+ const internals = useNavInternals();
60
+ // Snapshot computeds — each one reads only what it needs so the header
61
+ // doesn't re-run wholesale on every signal touch. The slot-fill thunks
62
+ // captured by `<Screen.Header>` etc. are themselves reactive (they
63
+ // execute on every render of the consumer's tree), so re-running the
64
+ // outer template is enough to pick up downstream updates.
65
+ const currentEntry = computed(() => nav.current);
66
+ const headerSlot = computed(() => {
67
+ const reg = internals.screens.get(currentEntry.value.key);
68
+ return reg?.slots.header;
69
+ });
70
+ const headerLeftSlot = computed(() => {
71
+ const reg = internals.screens.get(currentEntry.value.key);
72
+ return reg?.slots.headerLeft;
73
+ });
74
+ const headerRightSlot = computed(() => {
75
+ const reg = internals.screens.get(currentEntry.value.key);
76
+ return reg?.slots.headerRight;
77
+ });
78
+ const headerShown = computed(() => {
79
+ const reg = internals.screens.get(currentEntry.value.key);
80
+ // Default true — most screens want a header. Opting out is one prop
81
+ // on `<Screen>`.
82
+ return reg?.options.headerShown !== false;
83
+ });
84
+ const titleText = computed(() => {
85
+ const reg = internals.screens.get(currentEntry.value.key);
86
+ return resolveTitle(reg?.options.title, currentEntry.value.route);
87
+ });
88
+ return () => {
89
+ if (!headerShown.value)
90
+ return null;
91
+ // Full-override path: `<Screen.Header>` supplied its own content,
92
+ // we render that and skip the default layout entirely.
93
+ const override = headerSlot.value;
94
+ if (override)
95
+ return override();
96
+ return (_jsxs("view", { children: [_jsx("view", { children: headerLeftSlot.value
97
+ ? headerLeftSlot.value()
98
+ : nav.canGoBack
99
+ ? _jsx(DefaultBackButton, { onPress: () => nav.pop() })
100
+ : null }), _jsx(DefaultTitle, { text: titleText.value }), _jsx("view", { children: headerRightSlot.value ? headerRightSlot.value() : null })] }));
101
+ };
102
+ });
103
+ //# sourceMappingURL=Header.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Header.js","sourceRoot":"","sources":["../../src/components/Header.tsx"],"names":[],"mappings":"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"}
@@ -29,10 +29,7 @@ const LinkImpl = component(({ props, slots }) => {
29
29
  action(route, props.search);
30
30
  }
31
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?.() }));
32
+ return () => (_jsx("view", { bindtap: handlePress, children: slots.default?.() }));
36
33
  }, { name: 'Link' });
37
34
  /**
38
35
  * Declarative navigation. Same typing as `nav.push` — pass `params` only when
@@ -1 +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"}
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,CAGT,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"}
@@ -4,7 +4,7 @@ import type { RouteMap } from '../types.js';
4
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
5
  /**
6
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)
7
+ * Tests against `@sigx/lynx-testing` (which doesn't have an MT runtime)
8
8
  * should pass `animated={false}` so navigations commit synchronously.
9
9
  */
10
10
  & Define.Prop<'animated', boolean>
@@ -1 +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"}
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;AAGtE,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;;EAiDzB,CAAC"}
@@ -1,7 +1,8 @@
1
- import { component, defineProvide } from '@sigx/lynx';
1
+ import { component, defineProvide, useSharedValue } from '@sigx/lynx';
2
2
  import { createNavigatorState } from '../navigator/core.js';
3
3
  import { useNav } from '../hooks/use-nav.js';
4
- import { useNavRoutes } from '../hooks/use-nav-internal.js';
4
+ import { useNavInternals, useNavRoutes } from '../hooks/use-nav-internal.js';
5
+ import { _setRouteRegistry } from '../url/registry.js';
5
6
  /**
6
7
  * Root of a navigator subtree.
7
8
  *
@@ -24,6 +25,12 @@ export const NavigationRoot = component(({ props, slots }) => {
24
25
  if (!routes[initialName]) {
25
26
  throw new Error(`[lynx-navigation] <NavigationRoot> initialRoute='${initialName}' is not in the routes registry.`);
26
27
  }
28
+ // Publish the active route registry to the URL bridge so module-level
29
+ // `hrefFor` / `parseHref` callers (deep-link handlers, anything outside
30
+ // the component tree) resolve against this navigator's routes. Last
31
+ // mount wins — multi-root apps that need isolation should call the
32
+ // URL helpers with explicit context (TBD post-1.0).
33
+ _setRouteRegistry(routes);
27
34
  const initialPresentation = routes[initialName].presentation ?? 'card';
28
35
  const initial = {
29
36
  key: 'root',
@@ -33,9 +40,28 @@ export const NavigationRoot = component(({ props, slots }) => {
33
40
  state: undefined,
34
41
  presentation: initialPresentation,
35
42
  };
36
- const navState = createNavigatorState(routes, initial);
43
+ // SharedValue driving the slide-from-right push/pop transition. Created
44
+ // unconditionally (hooks must be) but only forwarded into the navigator
45
+ // when animations are enabled — `createNavigatorState` falls back to
46
+ // instant swaps when `progress` is undefined.
47
+ const progressSv = useSharedValue(0);
48
+ const animationsEnabled = props.animated !== false;
49
+ const navState = createNavigatorState({
50
+ routes,
51
+ initial,
52
+ progress: animationsEnabled ? progressSv : undefined,
53
+ });
37
54
  defineProvide(useNav, () => navState.nav);
38
55
  defineProvide(useNavRoutes, () => navState.routes);
56
+ const edgeSwipeEnabled = props.edgeSwipeEnabled !== false;
57
+ defineProvide(useNavInternals, () => ({
58
+ progress: animationsEnabled ? progressSv : null,
59
+ beginBackGesture: navState._gesture.beginBackGesture,
60
+ commitBackGesture: navState._gesture.commitBackGesture,
61
+ cancelBackGesture: navState._gesture.cancelBackGesture,
62
+ edgeSwipeEnabled,
63
+ screens: navState._screens,
64
+ }));
39
65
  return () => slots.default?.();
40
66
  });
41
67
  //# sourceMappingURL=NavigationRoot.js.map
@@ -1 +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"}
1
+ {"version":3,"file":"NavigationRoot.js","sourceRoot":"","sources":["../../src/components/NavigationRoot.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,cAAc,EAAe,MAAM,YAAY,CAAC;AACnF,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAG7E,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAqBvD;;;;;;;;;;;;;;;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,sEAAsE;IACtE,wEAAwE;IACxE,oEAAoE;IACpE,mEAAmE;IACnE,oDAAoD;IACpD,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC1B,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,wEAAwE;IACxE,wEAAwE;IACxE,qEAAqE;IACrE,8CAA8C;IAC9C,MAAM,UAAU,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC;IACrC,MAAM,iBAAiB,GAAG,KAAK,CAAC,QAAQ,KAAK,KAAK,CAAC;IACnD,MAAM,QAAQ,GAAG,oBAAoB,CAAC;QAClC,MAAM;QACN,OAAO;QACP,QAAQ,EAAE,iBAAiB,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS;KACvD,CAAC,CAAC;IAEH,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;IACnD,MAAM,gBAAgB,GAAG,KAAK,CAAC,gBAAgB,KAAK,KAAK,CAAC;IAC1D,aAAa,CAAC,eAAe,EAAE,GAAG,EAAE,CAAC,CAAC;QAClC,QAAQ,EAAE,iBAAiB,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI;QAC/C,gBAAgB,EAAE,QAAQ,CAAC,QAAQ,CAAC,gBAAgB;QACpD,iBAAiB,EAAE,QAAQ,CAAC,QAAQ,CAAC,iBAAiB;QACtD,iBAAiB,EAAE,QAAQ,CAAC,QAAQ,CAAC,iBAAiB;QACtD,gBAAgB;QAChB,OAAO,EAAE,QAAQ,CAAC,QAAQ;KAC7B,CAAC,CAAC,CAAC;IAEJ,OAAO,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;AACnC,CAAC,CAAC,CAAC"}
@@ -0,0 +1,98 @@
1
+ /**
2
+ * `<Screen>` — declarative per-screen options + slot fills.
3
+ *
4
+ * Usage:
5
+ *
6
+ * ```tsx
7
+ * const ProfileScreen = component(() => () => (
8
+ * <Screen title="Profile" headerShown gestureEnabled>
9
+ * <Screen.HeaderRight>
10
+ * <text bindtap={onEdit}>Edit</text>
11
+ * </Screen.HeaderRight>
12
+ * <view>body…</view>
13
+ * </Screen>
14
+ * ));
15
+ * ```
16
+ *
17
+ * `<Screen>` itself renders its `default` slot inline — so the body lives
18
+ * where you'd expect with no extra layout wrapper. The sub-components
19
+ * (`Screen.Header`, `Screen.HeaderLeft`, `Screen.HeaderRight`,
20
+ * `Screen.TabBarItem`) render `null` and write into the entry's
21
+ * `ScreenRegistry`. The navigator's persistent chrome reads from there.
22
+ *
23
+ * Note: `<Screen.TabBarItem>` registers a scoped slot fill on the entry's
24
+ * `ScreenRegistry`, but the built-in `<TabBar>` doesn't read it yet — the
25
+ * fill is exposed for custom tab-bar renderers (pass `renderTab` and look
26
+ * up the active entry's registry yourself).
27
+ *
28
+ * Sub-component placement inside `<Screen>` is conventional — sigx scopes
29
+ * are by component tree, so they work anywhere under the same EntryScope.
30
+ * Placing them as direct children of `<Screen>` keeps the call site
31
+ * declarative and grep-friendly.
32
+ */
33
+ import { type Define } from '@sigx/lynx';
34
+ type ScreenProps = Define.Prop<'title', string | (() => string)> & Define.Prop<'headerShown', boolean> & Define.Prop<'gestureEnabled', boolean> & Define.Slot<'default'>;
35
+ type SimpleSlotProps = Define.Slot<'default'>;
36
+ /**
37
+ * `<Screen.TabBarItem>` — scoped slot. The default slot is a function that
38
+ * receives `{ active }`; whatever it returns is the tab-bar item content.
39
+ *
40
+ * Sigx's `Define.Slot<'default', { active: boolean }>` would express this
41
+ * directly on the component, but since `<Screen.TabBarItem>`'s parent
42
+ * (the user's tree, not the navigator) doesn't actually pass `active`, we
43
+ * accept a plain default slot whose body is itself a function. The
44
+ * navigator's TabBar invokes that function with the active flag.
45
+ */
46
+ type TabBarItemProps = Define.Slot<'default'>;
47
+ /**
48
+ * Compound export. `Screen` is callable as a JSX element and exposes the
49
+ * sub-components as properties (`Screen.Header`, etc.) for the declarative
50
+ * call site shown in the file header.
51
+ */
52
+ export declare const Screen: ((props: {
53
+ title?: string | (() => string) | undefined;
54
+ headerShown?: boolean | undefined;
55
+ gestureEnabled?: boolean | undefined;
56
+ } & {} & {
57
+ slots?: Partial<{
58
+ default: () => import("@sigx/runtime-core").JSXElement | import("@sigx/runtime-core").JSXElement[] | null;
59
+ }> | undefined;
60
+ } & {} & JSX.IntrinsicAttributes & import("@sigx/runtime-core").ComponentAttributeExtensions & {
61
+ ref?: import("@sigx/runtime-core").Ref<void> | undefined;
62
+ children?: any;
63
+ }) => import("@sigx/runtime-core").JSXElement) & {
64
+ __setup: import("@sigx/runtime-core").SetupFn<{
65
+ title?: string | (() => string) | undefined;
66
+ headerShown?: boolean | undefined;
67
+ gestureEnabled?: boolean | undefined;
68
+ }, ScreenProps, void, {
69
+ default: () => import("@sigx/runtime-core").JSXElement | import("@sigx/runtime-core").JSXElement[] | null;
70
+ }>;
71
+ __name?: string;
72
+ __islandId?: string;
73
+ __props: {
74
+ title?: string | (() => string) | undefined;
75
+ headerShown?: boolean | undefined;
76
+ gestureEnabled?: boolean | undefined;
77
+ };
78
+ __events: ScreenProps;
79
+ __ref: void;
80
+ __slots: {
81
+ default: () => import("@sigx/runtime-core").JSXElement | import("@sigx/runtime-core").JSXElement[] | null;
82
+ };
83
+ } & {
84
+ Header: import("@sigx/runtime-core").ComponentFactory<SimpleSlotProps, void, {
85
+ default: () => import("@sigx/runtime-core").JSXElement | import("@sigx/runtime-core").JSXElement[] | null;
86
+ }>;
87
+ HeaderLeft: import("@sigx/runtime-core").ComponentFactory<SimpleSlotProps, void, {
88
+ default: () => import("@sigx/runtime-core").JSXElement | import("@sigx/runtime-core").JSXElement[] | null;
89
+ }>;
90
+ HeaderRight: import("@sigx/runtime-core").ComponentFactory<SimpleSlotProps, void, {
91
+ default: () => import("@sigx/runtime-core").JSXElement | import("@sigx/runtime-core").JSXElement[] | null;
92
+ }>;
93
+ TabBarItem: import("@sigx/runtime-core").ComponentFactory<TabBarItemProps, void, {
94
+ default: () => import("@sigx/runtime-core").JSXElement | import("@sigx/runtime-core").JSXElement[] | null;
95
+ }>;
96
+ };
97
+ export {};
98
+ //# sourceMappingURL=Screen.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Screen.d.ts","sourceRoot":"","sources":["../../src/components/Screen.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,OAAO,EAA0B,KAAK,MAAM,EAAE,MAAM,YAAY,CAAC;AAIjE,KAAK,WAAW,GACV,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,CAAC,CAAC,GAC7C,MAAM,CAAC,IAAI,CAAC,aAAa,EAAE,OAAO,CAAC,GACnC,MAAM,CAAC,IAAI,CAAC,gBAAgB,EAAE,OAAO,CAAC,GACtC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;AAgB7B,KAAK,eAAe,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;AAoB9C;;;;;;;;;GASG;AACH,KAAK,eAAe,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;AAmB9C;;;;GAIG;AACH,eAAO,MAAM,MAAM;4BAzEwB,MAAM;;;;;;;;;;;;gCAAN,MAAM;;;;;;;;;gCAAN,MAAM;;;;;;;;;;;;;;;;;;;;;;CA8E/C,CAAC"}
@@ -0,0 +1,94 @@
1
+ /**
2
+ * `<Screen>` — declarative per-screen options + slot fills.
3
+ *
4
+ * Usage:
5
+ *
6
+ * ```tsx
7
+ * const ProfileScreen = component(() => () => (
8
+ * <Screen title="Profile" headerShown gestureEnabled>
9
+ * <Screen.HeaderRight>
10
+ * <text bindtap={onEdit}>Edit</text>
11
+ * </Screen.HeaderRight>
12
+ * <view>body…</view>
13
+ * </Screen>
14
+ * ));
15
+ * ```
16
+ *
17
+ * `<Screen>` itself renders its `default` slot inline — so the body lives
18
+ * where you'd expect with no extra layout wrapper. The sub-components
19
+ * (`Screen.Header`, `Screen.HeaderLeft`, `Screen.HeaderRight`,
20
+ * `Screen.TabBarItem`) render `null` and write into the entry's
21
+ * `ScreenRegistry`. The navigator's persistent chrome reads from there.
22
+ *
23
+ * Note: `<Screen.TabBarItem>` registers a scoped slot fill on the entry's
24
+ * `ScreenRegistry`, but the built-in `<TabBar>` doesn't read it yet — the
25
+ * fill is exposed for custom tab-bar renderers (pass `renderTab` and look
26
+ * up the active entry's registry yourself).
27
+ *
28
+ * Sub-component placement inside `<Screen>` is conventional — sigx scopes
29
+ * are by component tree, so they work anywhere under the same EntryScope.
30
+ * Placing them as direct children of `<Screen>` keeps the call site
31
+ * declarative and grep-friendly.
32
+ */
33
+ import { component, onUnmounted } from '@sigx/lynx';
34
+ import { useScreenRegistry } from '../hooks/use-nav-internal.js';
35
+ import { mergeOptions, setSlot } from '../internal/screen-registry.js';
36
+ const ScreenRoot = component(({ props, slots }) => {
37
+ const registry = useScreenRegistry();
38
+ // Apply options whenever the component sets up. Options are reactive
39
+ // through the registry's `options` signal — chrome consumers re-render
40
+ // on the next merge. We don't bother diffing here: the patch is small
41
+ // and writes only happen during setup + explicit prop changes upstream.
42
+ mergeOptions(registry, {
43
+ title: props.title,
44
+ headerShown: props.headerShown,
45
+ gestureEnabled: props.gestureEnabled,
46
+ });
47
+ return () => slots.default?.();
48
+ });
49
+ /**
50
+ * Build a sub-component that registers its `default` slot under `name` on
51
+ * the current screen's registry. Unmount removes the fill so navigating
52
+ * away from a screen with a `<Screen.HeaderRight>` clears that action.
53
+ */
54
+ function makeSlotFiller(name) {
55
+ return component(({ slots }) => {
56
+ const registry = useScreenRegistry();
57
+ setSlot(registry, name, () => slots.default?.());
58
+ onUnmounted(() => setSlot(registry, name, undefined));
59
+ return () => null;
60
+ });
61
+ }
62
+ const Header = makeSlotFiller('header');
63
+ const HeaderLeft = makeSlotFiller('headerLeft');
64
+ const HeaderRight = makeSlotFiller('headerRight');
65
+ const TabBarItem = component(({ slots }) => {
66
+ const registry = useScreenRegistry();
67
+ setSlot(registry, 'tabBarItem', (ctx) => {
68
+ const out = slots.default?.();
69
+ // Children may be a render function `({active}) => JSX` or plain
70
+ // JSX (in which case `active` is ignored). Normalise to a value.
71
+ if (typeof out === 'function')
72
+ return out(ctx);
73
+ if (Array.isArray(out)) {
74
+ const first = out[0];
75
+ if (typeof first === 'function')
76
+ return first(ctx);
77
+ }
78
+ return out;
79
+ });
80
+ onUnmounted(() => setSlot(registry, 'tabBarItem', undefined));
81
+ return () => null;
82
+ });
83
+ /**
84
+ * Compound export. `Screen` is callable as a JSX element and exposes the
85
+ * sub-components as properties (`Screen.Header`, etc.) for the declarative
86
+ * call site shown in the file header.
87
+ */
88
+ export const Screen = Object.assign(ScreenRoot, {
89
+ Header,
90
+ HeaderLeft,
91
+ HeaderRight,
92
+ TabBarItem,
93
+ });
94
+ //# sourceMappingURL=Screen.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Screen.js","sourceRoot":"","sources":["../../src/components/Screen.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,OAAO,EAAE,SAAS,EAAE,WAAW,EAAe,MAAM,YAAY,CAAC;AACjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAC;AAQvE,MAAM,UAAU,GAAG,SAAS,CAAc,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE;IAC3D,MAAM,QAAQ,GAAG,iBAAiB,EAAE,CAAC;IACrC,qEAAqE;IACrE,uEAAuE;IACvE,sEAAsE;IACtE,wEAAwE;IACxE,YAAY,CAAC,QAAQ,EAAE;QACnB,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,cAAc,EAAE,KAAK,CAAC,cAAc;KACvC,CAAC,CAAC;IACH,OAAO,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;AACnC,CAAC,CAAC,CAAC;AAIH;;;;GAIG;AACH,SAAS,cAAc,CAAC,IAA6C;IACjE,OAAO,SAAS,CAAkB,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE;QAC5C,MAAM,QAAQ,GAAG,iBAAiB,EAAE,CAAC;QACrC,OAAO,CAAC,QAAQ,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QACjD,WAAW,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC;QACtD,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC;IACtB,CAAC,CAAC,CAAC;AACP,CAAC;AAED,MAAM,MAAM,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;AACxC,MAAM,UAAU,GAAG,cAAc,CAAC,YAAY,CAAC,CAAC;AAChD,MAAM,WAAW,GAAG,cAAc,CAAC,aAAa,CAAC,CAAC;AAclD,MAAM,UAAU,GAAG,SAAS,CAAkB,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE;IACxD,MAAM,QAAQ,GAAG,iBAAiB,EAAE,CAAC;IACrC,OAAO,CAAC,QAAQ,EAAE,YAAY,EAAE,CAAC,GAAG,EAAE,EAAE;QACpC,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;QAC9B,iEAAiE;QACjE,iEAAiE;QACjE,IAAI,OAAO,GAAG,KAAK,UAAU;YAAE,OAAQ,GAAkC,CAAC,GAAG,CAAC,CAAC;QAC/E,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YACrB,MAAM,KAAK,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;YACrB,IAAI,OAAO,KAAK,KAAK,UAAU;gBAAE,OAAQ,KAAoC,CAAC,GAAG,CAAC,CAAC;QACvF,CAAC;QACD,OAAO,GAAG,CAAC;IACf,CAAC,CAAC,CAAC;IACH,WAAW,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,QAAQ,EAAE,YAAY,EAAE,SAAS,CAAC,CAAC,CAAC;IAC9D,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC;AACtB,CAAC,CAAC,CAAC;AAEH;;;;GAIG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE;IAC5C,MAAM;IACN,UAAU;IACV,WAAW;IACX,UAAU;CACb,CAAC,CAAC"}
@@ -1 +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"}
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;AAIpB,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAwCxF,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,kDA0C1B,CAAC"}
@@ -0,0 +1,77 @@
1
+ import { jsx as _jsx } from "@sigx/lynx/jsx-runtime";
2
+ import { component, useMainThreadRef, useAnimatedStyle, } from '@sigx/lynx';
3
+ import { Suspense, isLazyComponent } from '@sigx/lynx';
4
+ import { SCREEN_WIDTH } from '../internal/screen-width.js';
5
+ import { EntryScope } from './EntryScope.js';
6
+ /**
7
+ * Slide-from-right transition geometry. `SCREEN_WIDTH` is read from
8
+ * `lynx.SystemInfo` at module load so the animation lands the screen at
9
+ * exactly translateX=0 (centered) at progress=1, rather than overshooting
10
+ * into the parent's clip region. `<EdgeBackHandle>` reads the same
11
+ * constant — they have to agree, otherwise the gesture commit threshold
12
+ * and the animation geometry don't line up.
13
+ */
14
+ const PARALLAX_FACTOR = 0.3;
15
+ /**
16
+ * Compute the `translateX` range for a given (role, kind) pair. Progress
17
+ * always runs 0 → 1; the role and kind decide what visual state each end of
18
+ * the progress represents.
19
+ *
20
+ * Slide-from-right semantics:
21
+ * - PUSH: new top slides in from the right; old top parallaxes left.
22
+ * - POP: current top slides out to the right; underneath returns from the
23
+ * parallax-left position.
24
+ */
25
+ function getRangeParams(role, kind) {
26
+ if (kind === 'push') {
27
+ if (role === 'top') {
28
+ return { inputRange: [0, 1], outputRange: [SCREEN_WIDTH, 0] };
29
+ }
30
+ return { inputRange: [0, 1], outputRange: [0, -PARALLAX_FACTOR * SCREEN_WIDTH] };
31
+ }
32
+ // pop
33
+ if (role === 'top') {
34
+ return { inputRange: [0, 1], outputRange: [0, SCREEN_WIDTH] };
35
+ }
36
+ return { inputRange: [0, 1], outputRange: [-PARALLAX_FACTOR * SCREEN_WIDTH, 0] };
37
+ }
38
+ /**
39
+ * Animated screen slot — absolutely positioned, MT-bound translateX driven by
40
+ * the navigator's progress SharedValue. Used during transitions to render the
41
+ * top + underneath entries together.
42
+ *
43
+ * Each instance is keyed by `${entry.key}-${role}-${kind}` in the parent so a
44
+ * role/kind change forces a fresh mount with a fresh `useAnimatedStyle`
45
+ * binding (the binding is set at setup and can't be re-keyed mid-life). State
46
+ * loss across transition boundaries is accepted in v0.2; persistent screen
47
+ * state (scroll position, input fields surviving navigations) is a polish
48
+ * item for Phase 0.5+.
49
+ */
50
+ export const ScreenContainer = component(({ props }) => {
51
+ const ref = useMainThreadRef(null);
52
+ const params = getRangeParams(props.role, props.kind);
53
+ useAnimatedStyle(ref, props.progress, 'translateX', params);
54
+ return () => {
55
+ const route = props.routes[props.entry.route];
56
+ if (!route)
57
+ return null;
58
+ const Comp = route.component;
59
+ if (typeof Comp !== 'function')
60
+ return null;
61
+ const entryParams = props.entry.params;
62
+ // Wrap lazy screens that declare a fallback in Suspense — see Stack.tsx
63
+ // for rationale.
64
+ const body = isLazyComponent(Comp) && route.fallback
65
+ ? (_jsx(Suspense, { fallback: route.fallback, children: _jsx(Comp, { ...entryParams }) }))
66
+ : _jsx(Comp, { ...entryParams });
67
+ return (_jsx("view", { "main-thread:ref": ref, style: {
68
+ position: 'absolute',
69
+ top: '0',
70
+ left: '0',
71
+ right: '0',
72
+ bottom: '0',
73
+ backgroundColor: '#0f172a',
74
+ }, children: _jsx(EntryScope, { entry: props.entry, children: body }, props.entry.key) }));
75
+ };
76
+ });
77
+ //# sourceMappingURL=ScreenContainer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ScreenContainer.js","sourceRoot":"","sources":["../../src/components/ScreenContainer.tsx"],"names":[],"mappings":"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"}
@@ -1 +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"}
1
+ {"version":3,"file":"Stack.d.ts","sourceRoot":"","sources":["../../src/components/Stack.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAa,KAAK,gBAAgB,EAAoB,MAAM,YAAY,CAAC;AAQhF;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,KAAK,qCA2FhB,CAAC"}