@sigx/lynx-navigation 0.4.0 → 0.4.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 (187) hide show
  1. package/dist/components/Drawer.js +74 -0
  2. package/dist/components/Drawer.js.map +1 -0
  3. package/dist/components/EdgeBackHandle.js +144 -0
  4. package/dist/components/EdgeBackHandle.js.map +1 -0
  5. package/dist/components/EntryScope.d.ts +1 -1
  6. package/dist/components/EntryScope.d.ts.map +1 -1
  7. package/dist/components/EntryScope.js +39 -0
  8. package/dist/components/EntryScope.js.map +1 -0
  9. package/dist/components/Header.js +103 -0
  10. package/dist/components/Header.js.map +1 -0
  11. package/dist/components/Layer.d.ts +2 -2
  12. package/dist/components/Layer.d.ts.map +1 -1
  13. package/dist/components/Layer.js +66 -0
  14. package/dist/components/Layer.js.map +1 -0
  15. package/dist/components/Link.d.ts +2 -2
  16. package/dist/components/Link.d.ts.map +1 -1
  17. package/dist/components/Link.js +51 -0
  18. package/dist/components/Link.js.map +1 -0
  19. package/dist/components/NavigationRoot.d.ts +2 -2
  20. package/dist/components/NavigationRoot.d.ts.map +1 -1
  21. package/dist/components/NavigationRoot.js +67 -0
  22. package/dist/components/NavigationRoot.js.map +1 -0
  23. package/dist/components/Screen.js +98 -0
  24. package/dist/components/Screen.js.map +1 -0
  25. package/dist/components/Stack.js +257 -0
  26. package/dist/components/Stack.js.map +1 -0
  27. package/dist/components/TabBar.d.ts +1 -1
  28. package/dist/components/TabBar.d.ts.map +1 -1
  29. package/dist/components/TabBar.js +63 -0
  30. package/dist/components/TabBar.js.map +1 -0
  31. package/dist/components/Tabs.d.ts +8 -3
  32. package/dist/components/Tabs.d.ts.map +1 -1
  33. package/dist/components/Tabs.js +168 -0
  34. package/dist/components/Tabs.js.map +1 -0
  35. package/dist/define-routes.d.ts +1 -1
  36. package/dist/define-routes.d.ts.map +1 -1
  37. package/{src/define-routes.d.ts → dist/define-routes.js} +4 -2
  38. package/dist/define-routes.js.map +1 -0
  39. package/dist/hooks/use-focus.js +87 -0
  40. package/dist/hooks/use-focus.js.map +1 -0
  41. package/dist/hooks/use-hardware-back.js +84 -0
  42. package/dist/hooks/use-hardware-back.js.map +1 -0
  43. package/dist/hooks/use-linking-nav.d.ts +3 -3
  44. package/dist/hooks/use-linking-nav.d.ts.map +1 -1
  45. package/dist/hooks/use-linking-nav.js +109 -0
  46. package/dist/hooks/use-linking-nav.js.map +1 -0
  47. package/dist/hooks/use-nav-internal.d.ts +2 -2
  48. package/dist/hooks/use-nav-internal.d.ts.map +1 -1
  49. package/dist/hooks/use-nav-internal.js +55 -0
  50. package/dist/hooks/use-nav-internal.js.map +1 -0
  51. package/dist/hooks/use-nav-serializer.d.ts +1 -1
  52. package/dist/hooks/use-nav-serializer.d.ts.map +1 -1
  53. package/dist/hooks/use-nav-serializer.js +181 -0
  54. package/dist/hooks/use-nav-serializer.js.map +1 -0
  55. package/dist/hooks/use-nav.d.ts +2 -2
  56. package/dist/hooks/use-nav.d.ts.map +1 -1
  57. package/dist/hooks/use-nav.js +11 -0
  58. package/dist/hooks/use-nav.js.map +1 -0
  59. package/dist/hooks/use-params.d.ts +1 -1
  60. package/dist/hooks/use-params.d.ts.map +1 -1
  61. package/{src/hooks/use-params.d.ts → dist/hooks/use-params.js} +6 -2
  62. package/dist/hooks/use-params.js.map +1 -0
  63. package/dist/hooks/use-screen-chrome.d.ts +1 -1
  64. package/dist/hooks/use-screen-chrome.d.ts.map +1 -1
  65. package/dist/hooks/use-screen-chrome.js +102 -0
  66. package/dist/hooks/use-screen-chrome.js.map +1 -0
  67. package/dist/hooks/use-screen-options.d.ts +1 -1
  68. package/dist/hooks/use-screen-options.d.ts.map +1 -1
  69. package/dist/hooks/use-screen-options.js +43 -0
  70. package/dist/hooks/use-screen-options.js.map +1 -0
  71. package/dist/hooks/use-search.d.ts +1 -1
  72. package/dist/hooks/use-search.d.ts.map +1 -1
  73. package/{src/hooks/use-search.d.ts → dist/hooks/use-search.js} +6 -2
  74. package/dist/hooks/use-search.js.map +1 -0
  75. package/dist/href.d.ts +2 -2
  76. package/dist/href.d.ts.map +1 -1
  77. package/dist/href.js +57 -0
  78. package/dist/href.js.map +1 -0
  79. package/dist/index.d.ts +33 -33
  80. package/dist/index.d.ts.map +1 -1
  81. package/dist/index.js +30 -1160
  82. package/dist/index.js.map +1 -1
  83. package/dist/internal/layer-plan.d.ts +1 -1
  84. package/dist/internal/layer-plan.d.ts.map +1 -1
  85. package/dist/internal/layer-plan.js +102 -0
  86. package/dist/internal/layer-plan.js.map +1 -0
  87. package/dist/internal/screen-registry.d.ts +1 -1
  88. package/dist/internal/screen-registry.d.ts.map +1 -1
  89. package/{src/internal/screen-registry.d.ts → dist/internal/screen-registry.js} +32 -21
  90. package/dist/internal/screen-registry.js.map +1 -0
  91. package/{src/internal/screen-width.d.ts → dist/internal/screen-width.js} +17 -2
  92. package/dist/internal/screen-width.js.map +1 -0
  93. package/dist/navigator/core.d.ts +3 -3
  94. package/dist/navigator/core.d.ts.map +1 -1
  95. package/dist/navigator/core.js +394 -0
  96. package/dist/navigator/core.js.map +1 -0
  97. package/dist/register.d.ts +1 -1
  98. package/dist/register.d.ts.map +1 -1
  99. package/dist/register.js +2 -0
  100. package/dist/register.js.map +1 -0
  101. package/dist/types.js +9 -0
  102. package/dist/types.js.map +1 -0
  103. package/dist/url/build.js +30 -0
  104. package/dist/url/build.js.map +1 -0
  105. package/dist/url/compile.js +83 -0
  106. package/dist/url/compile.js.map +1 -0
  107. package/dist/url/format.js +102 -0
  108. package/dist/url/format.js.map +1 -0
  109. package/dist/url/index.d.ts +6 -6
  110. package/dist/url/index.d.ts.map +1 -1
  111. package/dist/url/index.js +13 -0
  112. package/dist/url/index.js.map +1 -0
  113. package/dist/url/parse.d.ts +1 -1
  114. package/dist/url/parse.d.ts.map +1 -1
  115. package/dist/url/parse.js +94 -0
  116. package/dist/url/parse.js.map +1 -0
  117. package/dist/url/registry.d.ts +2 -2
  118. package/dist/url/registry.d.ts.map +1 -1
  119. package/{src/url/registry.d.ts → dist/url/registry.js} +28 -12
  120. package/dist/url/registry.js.map +1 -0
  121. package/dist/url/validate.d.ts +1 -1
  122. package/dist/url/validate.d.ts.map +1 -1
  123. package/dist/url/validate.js +37 -0
  124. package/dist/url/validate.js.map +1 -0
  125. package/package.json +16 -13
  126. package/src/components/EdgeBackHandle.tsx +2 -2
  127. package/src/components/EntryScope.tsx +3 -3
  128. package/src/components/Header.tsx +3 -3
  129. package/src/components/Layer.tsx +3 -3
  130. package/src/components/Link.tsx +4 -4
  131. package/src/components/NavigationRoot.tsx +6 -6
  132. package/src/components/Screen.tsx +3 -3
  133. package/src/components/Stack.tsx +8 -8
  134. package/src/components/TabBar.tsx +1 -1
  135. package/src/components/Tabs.tsx +8 -3
  136. package/src/define-routes.ts +1 -1
  137. package/src/hooks/use-focus.ts +2 -2
  138. package/src/hooks/use-hardware-back.ts +1 -1
  139. package/src/hooks/use-linking-nav.ts +4 -4
  140. package/src/hooks/use-nav-internal.ts +2 -2
  141. package/src/hooks/use-nav-serializer.ts +3 -3
  142. package/src/hooks/use-nav.ts +2 -2
  143. package/src/hooks/use-params.ts +2 -2
  144. package/src/hooks/use-screen-chrome.ts +3 -3
  145. package/src/hooks/use-screen-options.ts +3 -3
  146. package/src/hooks/use-search.ts +2 -2
  147. package/src/href.ts +6 -6
  148. package/src/index.ts +33 -33
  149. package/src/internal/layer-plan.ts +2 -2
  150. package/src/internal/screen-registry.ts +1 -1
  151. package/src/navigator/core.ts +3 -3
  152. package/src/register.ts +1 -1
  153. package/src/url/build.ts +2 -2
  154. package/src/url/index.ts +6 -6
  155. package/src/url/parse.ts +6 -6
  156. package/src/url/registry.ts +3 -3
  157. package/src/url/validate.ts +1 -1
  158. package/src/components/Drawer.d.ts +0 -55
  159. package/src/components/EdgeBackHandle.d.ts +0 -1
  160. package/src/components/EntryScope.d.ts +0 -25
  161. package/src/components/Header.d.ts +0 -6
  162. package/src/components/Layer.d.ts +0 -33
  163. package/src/components/Link.d.ts +0 -60
  164. package/src/components/NavigationRoot.d.ts +0 -36
  165. package/src/components/Screen.d.ts +0 -97
  166. package/src/components/Stack.d.ts +0 -90
  167. package/src/components/TabBar.d.ts +0 -38
  168. package/src/components/Tabs.d.ts +0 -109
  169. package/src/hooks/use-focus.d.ts +0 -45
  170. package/src/hooks/use-hardware-back.d.ts +0 -37
  171. package/src/hooks/use-linking-nav.d.ts +0 -91
  172. package/src/hooks/use-nav-internal.d.ts +0 -91
  173. package/src/hooks/use-nav-serializer.d.ts +0 -82
  174. package/src/hooks/use-nav.d.ts +0 -111
  175. package/src/hooks/use-screen-chrome.d.ts +0 -18
  176. package/src/hooks/use-screen-options.d.ts +0 -2
  177. package/src/href.d.ts +0 -54
  178. package/src/index.d.ts +0 -39
  179. package/src/internal/layer-plan.d.ts +0 -68
  180. package/src/navigator/core.d.ts +0 -96
  181. package/src/register.d.ts +0 -37
  182. package/src/types.d.ts +0 -217
  183. package/src/url/build.d.ts +0 -15
  184. package/src/url/compile.d.ts +0 -34
  185. package/src/url/format.d.ts +0 -28
  186. package/src/url/parse.d.ts +0 -20
  187. package/src/url/validate.d.ts +0 -23
@@ -0,0 +1,67 @@
1
+ import { component, defineProvide, useSharedValue } from '@sigx/lynx';
2
+ import { createNavigatorState } from '../navigator/core.js';
3
+ import { useNav } from '../hooks/use-nav.js';
4
+ import { useNavInternals, useNavRoutes } from '../hooks/use-nav-internal.js';
5
+ import { _setRouteRegistry } from '../url/registry.js';
6
+ /**
7
+ * Root of a navigator subtree.
8
+ *
9
+ * Creates a fresh `NavigatorState` from `routes` and provides it via
10
+ * `defineProvide`, so descendant `<Stack>` / `<Screen>` components and any
11
+ * `useNav()` / `useParams()` calls resolve through this instance.
12
+ *
13
+ * The bottom-of-stack entry is built from `initialRoute` (defaults to the
14
+ * first key in `routes`). For routes that declare a params schema, you must
15
+ * pass `initialParams` matching that schema.
16
+ *
17
+ * Mirrors the install pattern of `@sigx/router` (see
18
+ * `packages/router/src/router.ts:519-528`), but at component scope rather than
19
+ * `app.use(router)` — no app-wide singleton, so multi-navigator apps and
20
+ * tests get isolated state for free.
21
+ */
22
+ export const NavigationRoot = component(({ props, slots }) => {
23
+ const routes = props.routes;
24
+ const initialName = props.initialRoute ?? Object.keys(routes)[0];
25
+ if (!routes[initialName]) {
26
+ throw new Error(`[lynx-navigation] <NavigationRoot> initialRoute='${initialName}' is not in the routes registry.`);
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);
34
+ const initialPresentation = routes[initialName].presentation ?? 'card';
35
+ const initial = {
36
+ key: 'root',
37
+ route: initialName,
38
+ params: props.initialParams ?? {},
39
+ search: props.initialSearch ?? {},
40
+ state: undefined,
41
+ presentation: initialPresentation,
42
+ };
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
+ });
54
+ defineProvide(useNav, () => navState.nav);
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
+ }));
65
+ return () => slots.default?.();
66
+ });
67
+ //# 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,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 { 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. Only set keys that
39
+ // were actually passed — `mergeOptions` treats `undefined` as "clear
40
+ // this key", so building the patch from raw `props.X` would wipe
41
+ // every option a previous `useScreenOptions(...)` (or another `<Screen>`)
42
+ // had set on this same entry.
43
+ const patch = {};
44
+ if (props.title !== undefined)
45
+ patch.title = props.title;
46
+ if (props.headerShown !== undefined)
47
+ patch.headerShown = props.headerShown;
48
+ if (props.gestureEnabled !== undefined)
49
+ patch.gestureEnabled = props.gestureEnabled;
50
+ mergeOptions(registry, patch);
51
+ return () => slots.default?.();
52
+ });
53
+ /**
54
+ * Build a sub-component that registers its `default` slot under `name` on
55
+ * the current screen's registry. Unmount removes the fill so navigating
56
+ * away from a screen with a `<Screen.HeaderRight>` clears that action.
57
+ */
58
+ function makeSlotFiller(name) {
59
+ return component(({ slots }) => {
60
+ const registry = useScreenRegistry();
61
+ setSlot(registry, name, () => slots.default?.());
62
+ onUnmounted(() => setSlot(registry, name, undefined));
63
+ return () => null;
64
+ });
65
+ }
66
+ const Header = makeSlotFiller('header');
67
+ const HeaderLeft = makeSlotFiller('headerLeft');
68
+ const HeaderRight = makeSlotFiller('headerRight');
69
+ const TabBarItem = component(({ slots }) => {
70
+ const registry = useScreenRegistry();
71
+ setSlot(registry, 'tabBarItem', (ctx) => {
72
+ const out = slots.default?.();
73
+ // Children may be a render function `({active}) => JSX` or plain
74
+ // JSX (in which case `active` is ignored). Normalise to a value.
75
+ if (typeof out === 'function')
76
+ return out(ctx);
77
+ if (Array.isArray(out)) {
78
+ const first = out[0];
79
+ if (typeof first === 'function')
80
+ return first(ctx);
81
+ }
82
+ return out;
83
+ });
84
+ onUnmounted(() => setSlot(registry, 'tabBarItem', undefined));
85
+ return () => null;
86
+ });
87
+ /**
88
+ * Compound export. `Screen` is callable as a JSX element and exposes the
89
+ * sub-components as properties (`Screen.Header`, etc.) for the declarative
90
+ * call site shown in the file header.
91
+ */
92
+ export const Screen = Object.assign(ScreenRoot, {
93
+ Header,
94
+ HeaderLeft,
95
+ HeaderRight,
96
+ TabBarItem,
97
+ });
98
+ //# sourceMappingURL=Screen.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Screen.js","sourceRoot":"","sources":["../../src/components/Screen.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,257 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "@sigx/lynx/jsx-runtime";
2
+ import { component, defineProvide, effect, onUnmounted, untrack, useSharedValue, } from '@sigx/lynx';
3
+ import { createNavigatorState } from '../navigator/core.js';
4
+ import { useNav } from '../hooks/use-nav.js';
5
+ import { useCurrentEntry, useNavInternals, useNavRoutes, } from '../hooks/use-nav-internal.js';
6
+ import { animationVariant, computeLayers, isOverlayPresentation } from '../internal/layer-plan.js';
7
+ import { EdgeBackHandle } from './EdgeBackHandle.js';
8
+ import { Layer } from './Layer.js';
9
+ import { useTabScreenName, useTabs } from './Tabs.js';
10
+ let _nestedKeyCounter = 0;
11
+ /**
12
+ * Stack navigator — renders the topmost stack entry's component at rest, or
13
+ * the top + underneath entries during a transition.
14
+ *
15
+ * Two modes:
16
+ *
17
+ * **Bound** (no `initialRoute`): renders the enclosing navigator's stack.
18
+ * This is the shape used directly under `<NavigationRoot>` and is what
19
+ * single-stack apps want.
20
+ *
21
+ * **Nested-owner** (`initialRoute="…"`): mints a fresh `NavigatorState` with
22
+ * its own progress `SharedValue` and edge-back gesture, and provides
23
+ * `useNav` / `useNavInternals` / `useNavRoutes` to its subtree. `useNav()`
24
+ * inside this stack returns the nested nav; `nav.parent` points to the
25
+ * enclosing one. Per-tab stacks are the canonical use case:
26
+ *
27
+ * ```tsx
28
+ * <Tabs initialTab="trips">
29
+ * <Tabs.Screen name="trips"><Stack initialRoute="tripsHome" /></Tabs.Screen>
30
+ * <Tabs.Screen name="map"><Stack initialRoute="mapHome" /></Tabs.Screen>
31
+ * </Tabs>
32
+ * ```
33
+ *
34
+ * Modal/fullScreen pushes escalate up the parent chain automatically — so
35
+ * `nav.push('newTrip')` from inside Trips (where `newTrip` is `modal`)
36
+ * walks to root and overlays the whole UI. `replace` stays strictly local
37
+ * (asymmetric with `push`) so a modal `replace` never wipes the root stack.
38
+ *
39
+ * **Render strategy.** Stack always emits the same JSX shape — a
40
+ * relative wrapper containing one `<Layer>` per entry returned by
41
+ * `computeLayers(stack, transition, progress)`. Each Layer is an
42
+ * absolutely-positioned host view with optional MT-bound translate
43
+ * animation. The pure layer-plan function decides:
44
+ *
45
+ * - **Idle.** Topmost non-overlay base + any overlays above it. All
46
+ * static (no transform). Overlays (`modal` / `fullScreen` /
47
+ * `transparent-modal`) keep their underneath mounted; cards
48
+ * replace their underneath in the base layer.
49
+ * - **Card transition.** Both top and underneath animate (slide-in
50
+ * + parallax). After settle, idle rules apply — the underneath
51
+ * unmounts because the new top is the sole base.
52
+ * - **Overlay transition.** The full idle layer stack up through
53
+ * the underneath stays static; only the animated top has a
54
+ * transform. After settle, the overlay either joins the static
55
+ * idle stack (push) or unmounts (pop).
56
+ *
57
+ * Layer keys are `layer-${entry.key}-${animationVariant}`. The variant
58
+ * suffix forces a remount when an entry transitions from animated to
59
+ * static (or vice versa) — `useAnimatedStyle` binds once at setup and
60
+ * can't switch its mapper at runtime. Modal underneath layers never
61
+ * animate, so their key is stable across the modal lifecycle and the
62
+ * subtree's state (per-tab Stack navigators, scroll positions,
63
+ * in-flight inputs) survives.
64
+ */
65
+ export const Stack = component(({ props, slots }) => {
66
+ // Capture enclosing scope's nav + routes + internals BEFORE any of the
67
+ // defineProvide calls below override them for descendants. These are
68
+ // always the "outer" values regardless of whether this Stack is bound
69
+ // or nested-owner.
70
+ const parentNav = useNav();
71
+ const routes = useNavRoutes();
72
+ const parentInternals = useNavInternals();
73
+ // Decide mode at setup. `props.initialRoute` is captured once — the
74
+ // alternative (reactive switch between bound and nested-owner) would
75
+ // need to dispose and recreate the inner nav, which would lose all
76
+ // pushed state. Reasonable to pin it.
77
+ const initialName = props.initialRoute;
78
+ const isNested = typeof initialName === 'string' && initialName.length > 0;
79
+ let nav;
80
+ let internals;
81
+ if (isNested) {
82
+ if (!routes[initialName]) {
83
+ throw new Error(`[lynx-navigation] <Stack initialRoute='${initialName}'>: ` +
84
+ `route is not registered. Known routes: ` +
85
+ `${Object.keys(routes).join(', ') || '(none)'}`);
86
+ }
87
+ // Host entry — the parent's current top *when this Stack mounts*.
88
+ // Used by the focus chain so the nested nav is only "locally
89
+ // focused" while its host entry is still the top of the parent.
90
+ // Wrapped in try/catch because `<Stack initialRoute>` *may* be
91
+ // placed outside an EntryScope (e.g. directly under
92
+ // `<NavigationRoot>`); in that case there's no host-entry gate to
93
+ // apply and we just rely on `parent.isLocallyFocused`.
94
+ let hostEntryKey = null;
95
+ try {
96
+ hostEntryKey = useCurrentEntry().key;
97
+ }
98
+ catch {
99
+ hostEntryKey = null;
100
+ }
101
+ // Enclosing tab name (if any). Lets the focus chain gate on tab
102
+ // active state — Trips' inner stack reports `isLocallyFocused: false`
103
+ // while the user is on the Map tab, even though it's the top of
104
+ // its own stack.
105
+ let tabName = null;
106
+ let tabsHandle = null;
107
+ try {
108
+ tabName = useTabScreenName();
109
+ tabsHandle = useTabs();
110
+ }
111
+ catch {
112
+ tabName = null;
113
+ tabsHandle = null;
114
+ }
115
+ // Inherit animation enablement from the parent — if the root was
116
+ // created with `animated={false}` (tests), nested stacks should
117
+ // also commit instantly so test assertions don't have to wait on
118
+ // a SharedValue that won't tick.
119
+ const animationsEnabled = parentInternals.progress !== null;
120
+ const progressSv = useSharedValue(0);
121
+ const presentation = (routes[initialName].presentation ?? 'card');
122
+ // Counter-derived suffix keeps base-entry keys unique across
123
+ // concurrent nested stacks in a tab app. Plain `Math.random` would
124
+ // do but a counter is deterministic for test snapshots.
125
+ _nestedKeyCounter += 1;
126
+ const initial = {
127
+ key: `nested-${initialName}-${_nestedKeyCounter}`,
128
+ route: initialName,
129
+ params: props.initialParams ?? {},
130
+ search: props.initialSearch ?? {},
131
+ state: undefined,
132
+ presentation,
133
+ };
134
+ const navState = createNavigatorState({
135
+ routes,
136
+ initial,
137
+ progress: animationsEnabled ? progressSv : undefined,
138
+ parent: parentNav,
139
+ // Start un-focused; the effect below flips this once we observe
140
+ // the parent's current entry / tab-active state.
141
+ initialLocallyFocused: false,
142
+ });
143
+ nav = navState.nav;
144
+ internals = {
145
+ progress: animationsEnabled ? progressSv : null,
146
+ beginBackGesture: navState._gesture.beginBackGesture,
147
+ commitBackGesture: navState._gesture.commitBackGesture,
148
+ cancelBackGesture: navState._gesture.cancelBackGesture,
149
+ edgeSwipeEnabled:
150
+ // Gate on animationsEnabled too — if there's no progress
151
+ // SharedValue (e.g. parent is `animated={false}`), the edge
152
+ // swipe gesture would call `beginBackGesture()` with a null
153
+ // progress and leave the stack in an inconsistent state.
154
+ animationsEnabled && parentInternals.edgeSwipeEnabled,
155
+ screens: navState._screens,
156
+ };
157
+ // Reactive focus chain: this nav is locally focused iff
158
+ // 1. (no host entry captured) OR parent.current.key === hostEntryKey
159
+ // 2. parent.isLocallyFocused
160
+ // 3. (no enclosing tab) OR tabs.active === tabName
161
+ // Effect re-runs on any of those changing — parent's stack
162
+ // mutating, parent's own focus flipping, or the tab switching.
163
+ const focusRunner = effect(() => {
164
+ const hostMatch = hostEntryKey === null || parentNav.current.key === hostEntryKey;
165
+ const parentFocused = parentNav.isLocallyFocused;
166
+ const tabActive = tabName === null || tabsHandle === null
167
+ ? true
168
+ : tabsHandle.active === tabName;
169
+ const focused = hostMatch && parentFocused && tabActive;
170
+ // Write outside the read-tracking window — `_setLocallyFocused`
171
+ // bumps a signal that no consumer in *this* setup reads, but
172
+ // it's good hygiene anyway.
173
+ untrack(() => navState._setLocallyFocused(focused));
174
+ });
175
+ onUnmounted(() => {
176
+ focusRunner.stop();
177
+ parentNav._children.delete(nav);
178
+ });
179
+ defineProvide(useNav, () => nav);
180
+ defineProvide(useNavRoutes, () => routes);
181
+ defineProvide(useNavInternals, () => internals);
182
+ }
183
+ else {
184
+ nav = parentNav;
185
+ internals = parentInternals;
186
+ }
187
+ // Per-stack chrome (slots.default) renders *inside* this Stack's
188
+ // nav scope so a `<Header />` placed there resolves `useNav()` to
189
+ // the per-stack nav. Wrapping the active body in a flex-column
190
+ // with the slot above does that without disturbing layer-fill
191
+ // semantics — the slot takes natural height, the body keeps
192
+ // flex-fill.
193
+ const flexColumnFill = {
194
+ flexGrow: 1,
195
+ flexShrink: 1,
196
+ flexBasis: 0,
197
+ minHeight: 0,
198
+ display: 'flex',
199
+ flexDirection: 'column',
200
+ };
201
+ return () => {
202
+ const chrome = slots.default?.();
203
+ const layers = computeLayers(nav.stack, nav.transition, internals.progress);
204
+ const renderLayerNode = (layer) => layer ? (_jsx(Layer, { entry: layer.entry, routes: routes, animation: layer.animation }, `layer-${layer.entry.key}-${animationVariant(layer.animation)}`)) : null;
205
+ // sigx's reconciler treats a single array-valued JSX child as
206
+ // one "slot": when the array's *length* changes between
207
+ // renders, keyed children inside can be remounted even if
208
+ // their keys are stable. To make stacked-overlay state
209
+ // preservation work (modal A still mounted after modal B
210
+ // pushes on top), each layer is emitted as its own separate
211
+ // JSX child slot rather than as an array. The slots are
212
+ // position-stable across renders — the only thing that
213
+ // changes is a slot turning from `null` to a Layer (mount) or
214
+ // vice versa (unmount). MAX_LAYERS caps the supported stack
215
+ // depth; in practice apps rarely stack more than 2-3 overlays.
216
+ // If you hit the cap, increase the constant — the unrolled
217
+ // shape is just verbose, not algorithmically limited.
218
+ // Edge-swipe handle on top, gated on:
219
+ // - `internals.edgeSwipeEnabled` — opt-out flag (also off
220
+ // when the navigator has no progress SharedValue, i.e.
221
+ // animations disabled — no in-flight gesture to animate).
222
+ // - `nav.canGoBack` — something to pop back to.
223
+ // - `!nav.transition` — no animation already running.
224
+ // - The current top is a card (not an overlay). Edge-swipe
225
+ // is the iOS-style horizontal pop gesture for card stacks;
226
+ // using it to dismiss a modal would be the wrong axis +
227
+ // the wrong dismissal semantic.
228
+ //
229
+ // The handle only intercepts touches in the leftmost 20px and
230
+ // ignores small drags, so placing it last (highest z) doesn't
231
+ // disturb screen touches.
232
+ const top = nav.current;
233
+ const edgeHandle = (internals.edgeSwipeEnabled
234
+ && nav.canGoBack
235
+ && !nav.transition
236
+ && !isOverlayPresentation(top.presentation))
237
+ ? _jsx(EdgeBackHandle, {}, "edge-back")
238
+ : null;
239
+ const body = (_jsxs("view", { style: {
240
+ position: 'relative',
241
+ width: '100%',
242
+ // Flex-fill so the layer container has a real
243
+ // height — `<Layer>`s anchor via `position:
244
+ // absolute; top/right/bottom/left: 0`, which
245
+ // needs a sized relative parent.
246
+ ...flexColumnFill,
247
+ // Clip any animated layer that translates off-
248
+ // screen so the slide doesn't bleed past the
249
+ // Stack's bounds.
250
+ overflow: 'hidden',
251
+ }, children: [renderLayerNode(layers[0]), renderLayerNode(layers[1]), renderLayerNode(layers[2]), renderLayerNode(layers[3]), renderLayerNode(layers[4]), renderLayerNode(layers[5]), renderLayerNode(layers[6]), renderLayerNode(layers[7]), renderLayerNode(layers[8]), renderLayerNode(layers[9]), renderLayerNode(layers[10]), renderLayerNode(layers[11]), renderLayerNode(layers[12]), renderLayerNode(layers[13]), renderLayerNode(layers[14]), renderLayerNode(layers[15]), edgeHandle] }));
252
+ if (chrome == null)
253
+ return body;
254
+ return (_jsxs("view", { style: flexColumnFill, children: [chrome, _jsx("view", { style: flexColumnFill, children: body })] }));
255
+ };
256
+ });
257
+ //# sourceMappingURL=Stack.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Stack.js","sourceRoot":"","sources":["../../src/components/Stack.tsx"],"names":[],"mappings":"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"}
@@ -25,7 +25,7 @@
25
25
  * one so VoiceOver/TalkBack announces focus state on tab switch.
26
26
  */
27
27
  import { type JSXElement } from '@sigx/lynx';
28
- import { type TabInfo } from './Tabs';
28
+ import { type TabInfo } from './Tabs.js';
29
29
  /** Rendering context passed to a `renderTab` consumer. */
30
30
  export interface TabRenderContext {
31
31
  /** True when this tab is currently active. Reactive — re-runs render on change. */
@@ -1 +1 @@
1
- {"version":3,"file":"TabBar.d.ts","sourceRoot":"","sources":["../../src/components/TabBar.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,OAAO,EAGH,KAAK,UAAU,EAClB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAW,KAAK,OAAO,EAAE,MAAM,QAAQ,CAAC;AAE/C,0DAA0D;AAC1D,MAAM,WAAW,gBAAgB;IAC7B,mFAAmF;IACnF,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,2EAA2E;IAC3E,OAAO,IAAI,IAAI,CAAC;CACnB;AAoCD,eAAO,MAAM,MAAM;wBAjCmB,OAAO,OAAO,gBAAgB,KAAK,UAAU;YA6DjF,CAAC"}
1
+ {"version":3,"file":"TabBar.d.ts","sourceRoot":"","sources":["../../src/components/TabBar.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,OAAO,EAGH,KAAK,UAAU,EAClB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAW,KAAK,OAAO,EAAE,MAAM,WAAW,CAAC;AAElD,0DAA0D;AAC1D,MAAM,WAAW,gBAAgB;IAC7B,mFAAmF;IACnF,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,2EAA2E;IAC3E,OAAO,IAAI,IAAI,CAAC;CACnB;AAoCD,eAAO,MAAM,MAAM;wBAjCmB,OAAO,OAAO,gBAAgB,KAAK,UAAU;YA6DjF,CAAC"}
@@ -0,0 +1,63 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "@sigx/lynx/jsx-runtime";
2
+ /**
3
+ * `<TabBar>` — headless default chrome for `<Tabs>`.
4
+ *
5
+ * Renders the active-tab buttons reading from the enclosing `useTabs()`
6
+ * navigator. Intentionally **unstyled** — this lives in the (theme-less)
7
+ * navigation package, so it ships pure structure + accessibility wiring.
8
+ * Themed chrome belongs in a UI-kit package: see `<NavTabBar />` in
9
+ * `@sigx/lynx-daisyui` for the daisy-themed equivalent.
10
+ *
11
+ * Use this directly only if you want to handle styling yourself via the
12
+ * `renderTab` prop. For a "looks like a tab bar out of the box" component,
13
+ * pull `<NavTabBar />` from `@sigx/lynx-daisyui` (or your own UI kit).
14
+ *
15
+ * Customization:
16
+ * - `renderTab`: a function `(info, ctx) => JSX` that fully replaces the
17
+ * default button rendering for each tab. `ctx.active` tells the
18
+ * consumer whether this tab is currently focused; `ctx.onPress`
19
+ * activates the tab. **Recommended** for any visual treatment.
20
+ *
21
+ * Accessibility (baked into the default button — the one structural
22
+ * concern this component keeps):
23
+ * - `accessibility-label` from `info.accessibilityLabel ?? info.label ?? info.name`.
24
+ * - `accessibility-element="true"` so screen readers see the whole pill.
25
+ * - `accessibility-trait="button"` and a `selected` flag on the active
26
+ * one so VoiceOver/TalkBack announces focus state on tab switch.
27
+ */
28
+ import { component, } from '@sigx/lynx';
29
+ import { useTabs } from './Tabs.js';
30
+ /**
31
+ * Default per-tab button. Plain `<view>` with a `<text>` inside, an
32
+ * `accessibility-*` cluster for screen readers, and a tap handler. No
33
+ * styling beyond a minimal active-state opacity hint — consumers that
34
+ * want branded chrome pass `renderTab` or use a UI-kit-provided tab bar
35
+ * (e.g. `<NavTabBar />` from `@sigx/lynx-daisyui`).
36
+ */
37
+ const DefaultTabButton = component(({ props }) => {
38
+ return () => {
39
+ const label = props.info.label ?? props.info.name;
40
+ const a11y = props.info.accessibilityLabel ?? label;
41
+ return (_jsxs("view", { bindtap: () => props.onPress(), "accessibility-element": true, "accessibility-label": a11y, "accessibility-trait": "button", "accessibility-status": props.active ? 'selected' : undefined, style: { opacity: props.active ? 1 : 0.6 }, children: [props.info.icon ?? null, _jsx("text", { children: label })] }));
42
+ };
43
+ });
44
+ export const TabBar = component(({ props }) => {
45
+ const nav = useTabs();
46
+ return () => {
47
+ // Reading `nav.tabs` and `nav.active` here ties this render to both
48
+ // the registration list and the active signal — switching active or
49
+ // adding/removing a `<Tabs.Screen>` updates the bar reactively.
50
+ const tabs = nav.tabs;
51
+ const active = nav.active;
52
+ const renderer = props.renderTab;
53
+ return (_jsx("view", { "accessibility-element": false, children: tabs.map((info) => {
54
+ const isActive = info.name === active;
55
+ const onPress = () => nav.setActive(info.name);
56
+ if (renderer) {
57
+ return renderer(info, { active: isActive, onPress });
58
+ }
59
+ return (_jsx(DefaultTabButton, { info: info, active: isActive, onPress: onPress }));
60
+ }) }));
61
+ };
62
+ });
63
+ //# sourceMappingURL=TabBar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TabBar.js","sourceRoot":"","sources":["../../src/components/TabBar.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,OAAO,EACH,SAAS,GAGZ,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,OAAO,EAAgB,MAAM,WAAW,CAAC;AAalD;;;;;;GAMG;AACH,MAAM,gBAAgB,GAAG,SAAS,CAIhC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE;IACZ,OAAO,GAAG,EAAE;QACR,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;QAClD,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,kBAAkB,IAAI,KAAK,CAAC;QACpD,OAAO,CACH,gBACI,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,2BACP,IAAI,yBACN,IAAI,yBACL,QAAQ,0BACN,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,EAC3D,KAAK,EAAE,EAAE,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,aAEzC,KAAK,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,EACxB,yBAAO,KAAK,GAAQ,IACjB,CACV,CAAC;IACN,CAAC,CAAC;AACN,CAAC,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,MAAM,GAAG,SAAS,CAAc,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE;IACvD,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;IACtB,OAAO,GAAG,EAAE;QACR,oEAAoE;QACpE,oEAAoE;QACpE,gEAAgE;QAChE,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC;QACtB,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC;QAC1B,MAAM,QAAQ,GAAG,KAAK,CAAC,SAAS,CAAC;QACjC,OAAO,CACH,wCAA6B,KAAK,YAC7B,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;gBACf,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC;gBACtC,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC/C,IAAI,QAAQ,EAAE,CAAC;oBACX,OAAO,QAAQ,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;gBACzD,CAAC;gBACD,OAAO,CACH,KAAC,gBAAgB,IACb,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,QAAQ,EAChB,OAAO,EAAE,OAAO,GAClB,CACL,CAAC;YACN,CAAC,CAAC,GACC,CACV,CAAC;IACN,CAAC,CAAC;AACN,CAAC,CAAC,CAAC"}
@@ -32,12 +32,17 @@
32
32
  * tabs UI (TabBar included) and dismiss back into the originating tab.
33
33
  */
34
34
  import { type Define, type JSXElement } from '@sigx/lynx';
35
+ import type { IconSpec } from '@sigx/lynx-icons';
35
36
  /** Metadata about a registered `<Tabs.Screen>`. */
36
37
  export interface TabInfo {
37
38
  /** Stable tab id, used by `setActive`. */
38
39
  readonly name: string;
39
- /** Optional icon node — passed through to the default tab bar. */
40
- readonly icon?: JSXElement;
40
+ /**
41
+ * Optional icon. Either an `IconSpec` (the bar renders an `<Icon>` and
42
+ * controls color/size via theme) or a precomputed JSX node (full
43
+ * control — color, size, custom component).
44
+ */
45
+ readonly icon?: IconSpec | JSXElement;
41
46
  /** Optional human-readable label. Defaults to `name`. */
42
47
  readonly label?: string;
43
48
  /**
@@ -69,7 +74,7 @@ export declare const useTabs: import("@sigx/runtime-core").InjectableFunction<Ta
69
74
  */
70
75
  export declare const useTabScreenName: import("@sigx/runtime-core").InjectableFunction<string>;
71
76
  type TabsProps = Define.Prop<'initialTab', string> & Define.Slot<'default'>;
72
- type TabsScreenProps = Define.Prop<'name', string, true> & Define.Prop<'icon', JSXElement> & Define.Prop<'label', string> & Define.Prop<'accessibilityLabel', string> & Define.Slot<'default'>;
77
+ type TabsScreenProps = Define.Prop<'name', string, true> & Define.Prop<'icon', IconSpec | JSXElement> & Define.Prop<'label', string> & Define.Prop<'accessibilityLabel', string> & Define.Slot<'default'>;
73
78
  /**
74
79
  * Compound export. `Tabs` is the parent component; `Tabs.Screen` registers
75
80
  * an individual tab. Matches the `Screen` / `Screen.Header` shape used
@@ -1 +1 @@
1
- {"version":3,"file":"Tabs.d.ts","sourceRoot":"","sources":["../../src/components/Tabs.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,OAAO,EAQH,KAAK,MAAM,EACX,KAAK,UAAU,EAElB,MAAM,YAAY,CAAC;AAEpB,mDAAmD;AACnD,MAAM,WAAW,OAAO;IACpB,0CAA0C;IAC1C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,kEAAkE;IAClE,QAAQ,CAAC,IAAI,CAAC,EAAE,UAAU,CAAC;IAC3B,yDAAyD;IACzD,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB;;;;OAIG;IACH,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;CACxC;AAED,kDAAkD;AAClD,MAAM,WAAW,OAAO;IACpB,mFAAmF;IACnF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,wEAAwE;IACxE,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,mEAAmE;IACnE,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;CACzC;AAED;;GAEG;AACH,eAAO,MAAM,OAAO,0DAIlB,CAAC;AAsBH;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,yDAI3B,CAAC;AAEH,KAAK,SAAS,GACR,MAAM,CAAC,IAAI,CAAC,YAAY,EAAE,MAAM,CAAC,GACjC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;AAgE7B,KAAK,eAAe,GACd,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,GACjC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,GAC/B,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,GAC5B,MAAM,CAAC,IAAI,CAAC,oBAAoB,EAAE,MAAM,CAAC,GACzC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;AAsD7B;;;;;GAKG;AACH,eAAO,MAAM,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAEf,CAAC"}
1
+ {"version":3,"file":"Tabs.d.ts","sourceRoot":"","sources":["../../src/components/Tabs.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,OAAO,EAQH,KAAK,MAAM,EACX,KAAK,UAAU,EAElB,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEjD,mDAAmD;AACnD,MAAM,WAAW,OAAO;IACpB,0CAA0C;IAC1C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,QAAQ,GAAG,UAAU,CAAC;IACtC,yDAAyD;IACzD,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB;;;;OAIG;IACH,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;CACxC;AAED,kDAAkD;AAClD,MAAM,WAAW,OAAO;IACpB,mFAAmF;IACnF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,wEAAwE;IACxE,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,mEAAmE;IACnE,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;CACzC;AAED;;GAEG;AACH,eAAO,MAAM,OAAO,0DAIlB,CAAC;AAsBH;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,yDAI3B,CAAC;AAEH,KAAK,SAAS,GACR,MAAM,CAAC,IAAI,CAAC,YAAY,EAAE,MAAM,CAAC,GACjC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;AAgE7B,KAAK,eAAe,GACd,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,GACjC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,GAAG,UAAU,CAAC,GAC1C,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,GAC5B,MAAM,CAAC,IAAI,CAAC,oBAAoB,EAAE,MAAM,CAAC,GACzC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;AAsD7B;;;;;GAKG;AACH,eAAO,MAAM,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAEf,CAAC"}