@sigx/lynx-navigation 0.1.3 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +189 -7
- package/dist/components/EntryScope.d.ts +1 -1
- package/dist/components/EntryScope.d.ts.map +1 -1
- package/dist/components/Layer.d.ts +34 -0
- package/dist/components/Layer.d.ts.map +1 -0
- package/dist/components/Link.d.ts +2 -2
- package/dist/components/Link.d.ts.map +1 -1
- package/dist/components/NavigationRoot.d.ts +2 -2
- package/dist/components/NavigationRoot.d.ts.map +1 -1
- package/dist/components/Screen.d.ts +6 -6
- package/dist/components/Screen.d.ts.map +1 -1
- package/dist/components/Stack.d.ts +83 -13
- package/dist/components/Stack.d.ts.map +1 -1
- package/dist/components/TabBar.d.ts +19 -20
- package/dist/components/TabBar.d.ts.map +1 -1
- package/dist/components/Tabs.d.ts +30 -21
- package/dist/components/Tabs.d.ts.map +1 -1
- package/dist/define-routes.d.ts +1 -1
- package/dist/define-routes.d.ts.map +1 -1
- package/dist/hooks/use-focus.d.ts.map +1 -1
- package/dist/hooks/use-hardware-back.d.ts +9 -2
- package/dist/hooks/use-hardware-back.d.ts.map +1 -1
- package/dist/hooks/use-linking-nav.d.ts +3 -3
- package/dist/hooks/use-linking-nav.d.ts.map +1 -1
- package/dist/hooks/use-nav-internal.d.ts +21 -3
- package/dist/hooks/use-nav-internal.d.ts.map +1 -1
- package/dist/hooks/use-nav-serializer.d.ts +1 -1
- package/dist/hooks/use-nav-serializer.d.ts.map +1 -1
- package/dist/hooks/use-nav.d.ts +38 -3
- package/dist/hooks/use-nav.d.ts.map +1 -1
- package/dist/hooks/use-params.d.ts +1 -1
- package/dist/hooks/use-params.d.ts.map +1 -1
- package/dist/hooks/use-screen-chrome.d.ts +19 -0
- package/dist/hooks/use-screen-chrome.d.ts.map +1 -0
- package/dist/hooks/use-screen-options.d.ts +1 -1
- package/dist/hooks/use-screen-options.d.ts.map +1 -1
- package/dist/hooks/use-search.d.ts +1 -1
- package/dist/hooks/use-search.d.ts.map +1 -1
- package/dist/href.d.ts +2 -2
- package/dist/href.d.ts.map +1 -1
- package/dist/index.d.ts +33 -31
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1160 -29
- package/dist/index.js.map +1 -1
- package/dist/internal/layer-plan.d.ts +69 -0
- package/dist/internal/layer-plan.d.ts.map +1 -0
- package/dist/internal/screen-registry.d.ts +1 -1
- package/dist/internal/screen-registry.d.ts.map +1 -1
- package/dist/internal/screen-width.d.ts +9 -7
- package/dist/internal/screen-width.d.ts.map +1 -1
- package/dist/navigator/core.d.ts +31 -4
- package/dist/navigator/core.d.ts.map +1 -1
- package/dist/register.d.ts +1 -1
- package/dist/register.d.ts.map +1 -1
- package/dist/url/index.d.ts +6 -6
- package/dist/url/index.d.ts.map +1 -1
- package/dist/url/parse.d.ts +1 -1
- package/dist/url/parse.d.ts.map +1 -1
- package/dist/url/registry.d.ts +2 -2
- package/dist/url/registry.d.ts.map +1 -1
- package/dist/url/validate.d.ts +1 -1
- package/dist/url/validate.d.ts.map +1 -1
- package/package.json +11 -10
- package/src/components/Drawer.d.ts +55 -0
- package/src/components/EdgeBackHandle.d.ts +1 -0
- package/src/components/EdgeBackHandle.tsx +2 -2
- package/{dist/components/EntryScope.js → src/components/EntryScope.d.ts} +7 -15
- package/src/components/EntryScope.tsx +15 -4
- package/src/components/Header.d.ts +6 -0
- package/src/components/Header.tsx +3 -3
- package/src/components/Layer.d.ts +33 -0
- package/src/components/Layer.tsx +96 -0
- package/src/components/Link.d.ts +60 -0
- package/src/components/Link.tsx +4 -4
- package/src/components/NavigationRoot.d.ts +36 -0
- package/src/components/NavigationRoot.tsx +6 -6
- package/src/components/Screen.d.ts +97 -0
- package/src/components/Screen.tsx +13 -11
- package/src/components/Stack.d.ts +90 -0
- package/src/components/Stack.tsx +333 -92
- package/src/components/TabBar.d.ts +38 -0
- package/src/components/TabBar.tsx +22 -22
- package/src/components/Tabs.d.ts +109 -0
- package/src/components/Tabs.tsx +54 -22
- package/{dist/define-routes.js → src/define-routes.d.ts} +2 -4
- package/src/define-routes.ts +1 -1
- package/{dist/hooks/use-focus.js → src/hooks/use-focus.d.ts} +3 -39
- package/src/hooks/use-focus.ts +9 -3
- package/src/hooks/use-hardware-back.d.ts +37 -0
- package/src/hooks/use-hardware-back.ts +43 -9
- package/src/hooks/use-linking-nav.d.ts +91 -0
- package/src/hooks/use-linking-nav.ts +4 -4
- package/src/hooks/use-nav-internal.d.ts +91 -0
- package/src/hooks/use-nav-internal.ts +24 -3
- package/src/hooks/use-nav-serializer.d.ts +82 -0
- package/src/hooks/use-nav-serializer.ts +3 -3
- package/src/hooks/use-nav.d.ts +111 -0
- package/src/hooks/use-nav.ts +40 -3
- package/{dist/hooks/use-params.js → src/hooks/use-params.d.ts} +2 -6
- package/src/hooks/use-params.ts +2 -2
- package/src/hooks/use-screen-chrome.d.ts +18 -0
- package/src/hooks/use-screen-chrome.ts +122 -0
- package/src/hooks/use-screen-options.d.ts +2 -0
- package/src/hooks/use-screen-options.ts +3 -3
- package/{dist/hooks/use-search.js → src/hooks/use-search.d.ts} +2 -6
- package/src/hooks/use-search.ts +2 -2
- package/src/href.d.ts +54 -0
- package/src/href.ts +6 -6
- package/src/index.d.ts +39 -0
- package/src/index.ts +33 -31
- package/src/internal/layer-plan.d.ts +68 -0
- package/src/internal/layer-plan.ts +187 -0
- package/{dist/internal/screen-registry.js → src/internal/screen-registry.d.ts} +21 -32
- package/src/internal/screen-registry.ts +1 -1
- package/src/internal/screen-width.d.ts +17 -0
- package/src/internal/screen-width.ts +22 -14
- package/src/navigator/core.d.ts +96 -0
- package/src/navigator/core.ts +90 -10
- package/src/register.d.ts +37 -0
- package/src/register.ts +1 -1
- package/src/types.d.ts +217 -0
- package/src/url/build.d.ts +15 -0
- package/src/url/build.ts +2 -2
- package/src/url/compile.d.ts +34 -0
- package/src/url/format.d.ts +28 -0
- package/src/url/index.ts +6 -6
- package/src/url/parse.d.ts +20 -0
- package/src/url/parse.ts +6 -6
- package/{dist/url/registry.js → src/url/registry.d.ts} +12 -28
- package/src/url/registry.ts +3 -3
- package/src/url/validate.d.ts +23 -0
- package/src/url/validate.ts +1 -1
- package/dist/components/Drawer.js +0 -74
- package/dist/components/Drawer.js.map +0 -1
- package/dist/components/EdgeBackHandle.js +0 -144
- package/dist/components/EdgeBackHandle.js.map +0 -1
- package/dist/components/EntryScope.js.map +0 -1
- package/dist/components/Header.js +0 -103
- package/dist/components/Header.js.map +0 -1
- package/dist/components/Link.js +0 -51
- package/dist/components/Link.js.map +0 -1
- package/dist/components/NavigationRoot.js +0 -67
- package/dist/components/NavigationRoot.js.map +0 -1
- package/dist/components/Screen.js +0 -94
- package/dist/components/Screen.js.map +0 -1
- package/dist/components/ScreenContainer.d.ts +0 -18
- package/dist/components/ScreenContainer.d.ts.map +0 -1
- package/dist/components/ScreenContainer.js +0 -77
- package/dist/components/ScreenContainer.js.map +0 -1
- package/dist/components/Stack.js +0 -75
- package/dist/components/Stack.js.map +0 -1
- package/dist/components/TabBar.js +0 -63
- package/dist/components/TabBar.js.map +0 -1
- package/dist/components/Tabs.js +0 -140
- package/dist/components/Tabs.js.map +0 -1
- package/dist/define-routes.js.map +0 -1
- package/dist/hooks/use-focus.js.map +0 -1
- package/dist/hooks/use-hardware-back.js +0 -50
- package/dist/hooks/use-hardware-back.js.map +0 -1
- package/dist/hooks/use-linking-nav.js +0 -109
- package/dist/hooks/use-linking-nav.js.map +0 -1
- package/dist/hooks/use-nav-internal.js +0 -44
- package/dist/hooks/use-nav-internal.js.map +0 -1
- package/dist/hooks/use-nav-serializer.js +0 -181
- package/dist/hooks/use-nav-serializer.js.map +0 -1
- package/dist/hooks/use-nav.js +0 -11
- package/dist/hooks/use-nav.js.map +0 -1
- package/dist/hooks/use-params.js.map +0 -1
- package/dist/hooks/use-screen-options.js +0 -43
- package/dist/hooks/use-screen-options.js.map +0 -1
- package/dist/hooks/use-search.js.map +0 -1
- package/dist/href.js +0 -57
- package/dist/href.js.map +0 -1
- package/dist/internal/screen-registry.js.map +0 -1
- package/dist/internal/screen-width.js +0 -30
- package/dist/internal/screen-width.js.map +0 -1
- package/dist/navigator/core.js +0 -344
- package/dist/navigator/core.js.map +0 -1
- package/dist/register.js +0 -2
- package/dist/register.js.map +0 -1
- package/dist/types.js +0 -9
- package/dist/types.js.map +0 -1
- package/dist/url/build.js +0 -30
- package/dist/url/build.js.map +0 -1
- package/dist/url/compile.js +0 -83
- package/dist/url/compile.js.map +0 -1
- package/dist/url/format.js +0 -102
- package/dist/url/format.js.map +0 -1
- package/dist/url/index.js +0 -13
- package/dist/url/index.js.map +0 -1
- package/dist/url/parse.js +0 -94
- package/dist/url/parse.js.map +0 -1
- package/dist/url/registry.js.map +0 -1
- package/dist/url/validate.js +0 -37
- package/dist/url/validate.js.map +0 -1
- package/src/components/ScreenContainer.tsx +0 -114
package/README.md
CHANGED
|
@@ -98,7 +98,95 @@ and every other API gets typed.
|
|
|
98
98
|
### `<Stack>`
|
|
99
99
|
|
|
100
100
|
Renders the topmost stack entry plus the entry beneath it during
|
|
101
|
-
transitions.
|
|
101
|
+
transitions. By default it binds to the enclosing navigator (the root one
|
|
102
|
+
under `<NavigationRoot>`).
|
|
103
|
+
|
|
104
|
+
Pass `initialRoute` to make `<Stack>` create its **own** nested navigator —
|
|
105
|
+
this is how per-tab stacks work. See [Per-tab nested stacks](#per-tab-nested-stacks).
|
|
106
|
+
|
|
107
|
+
```tsx
|
|
108
|
+
<Stack initialRoute="tripsHome" />
|
|
109
|
+
<Stack initialRoute="profile" initialParams={{ id: 'me' }} />
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Per-tab nested stacks
|
|
113
|
+
|
|
114
|
+
Drop a `<Stack initialRoute=…>` inside each `<Tabs.Screen>` to give every
|
|
115
|
+
tab its own back-stack. Card-presentation pushes stay inside the tab;
|
|
116
|
+
modal / fullScreen / transparent-modal pushes **escalate** to the root
|
|
117
|
+
navigator so they overlay the entire tabs UI (TabBar included).
|
|
118
|
+
|
|
119
|
+
```tsx
|
|
120
|
+
<NavigationRoot routes={routes} initialRoute="root">
|
|
121
|
+
<Header />
|
|
122
|
+
<Stack /> {/* root navigator — renders the `root` entry below */}
|
|
123
|
+
</NavigationRoot>
|
|
124
|
+
|
|
125
|
+
// `root` route renders this:
|
|
126
|
+
<Tabs initialTab="trips">
|
|
127
|
+
<Tabs.Screen name="trips" label="Trips">
|
|
128
|
+
<Stack initialRoute="tripsHome" />
|
|
129
|
+
</Tabs.Screen>
|
|
130
|
+
<Tabs.Screen name="map" label="Map">
|
|
131
|
+
<Stack initialRoute="mapHome" />
|
|
132
|
+
</Tabs.Screen>
|
|
133
|
+
<TabBar />
|
|
134
|
+
</Tabs>
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Inside a tab body, `useNav()` resolves to the **innermost** navigator:
|
|
138
|
+
|
|
139
|
+
- `nav.push('tripDetail', { tripId })` — `tripDetail` is a card route →
|
|
140
|
+
pushed onto the trips tab's stack, TabBar stays visible.
|
|
141
|
+
- `nav.push('newTrip')` — `newTrip` is `presentation: 'modal'` → walks up
|
|
142
|
+
`nav.parent` to root and pushes there, overlays the whole tabs UI.
|
|
143
|
+
- `nav.replace(...)` is **strictly local** and never escalates (asymmetric
|
|
144
|
+
with `push` by design — keeps the root stack stable).
|
|
145
|
+
- Hardware/edge back pops the focused inner nav first; only falls through
|
|
146
|
+
to root once the inner stack is empty.
|
|
147
|
+
- `useIsFocused()` is `true` only when the screen is the top of its own
|
|
148
|
+
nav **and** every ancestor is focused (parent's current entry matches +
|
|
149
|
+
enclosing tab is active).
|
|
150
|
+
|
|
151
|
+
**Modal preservation.** When a `modal` / `fullScreen` /
|
|
152
|
+
`transparent-modal` push goes onto the root navigator (via escalation
|
|
153
|
+
from a per-tab stack), `<Stack>` keeps the underneath entry mounted
|
|
154
|
+
behind the overlay. Per-tab stack state, scroll positions, and in-flight
|
|
155
|
+
inputs all survive the modal lifecycle. Card pushes still replace the
|
|
156
|
+
underneath in the base layer — the user's mental model is "back
|
|
157
|
+
recreates the previous screen from history".
|
|
158
|
+
|
|
159
|
+
**Limitations (current slice)**:
|
|
160
|
+
|
|
161
|
+
- One global route registry — there's no per-tab whitelist yet. Deep-link
|
|
162
|
+
routing always pushes against the innermost nav of the caller site
|
|
163
|
+
(modal routes still escalate). A future slice may add `<Stack routes={…}>`.
|
|
164
|
+
- `useNavSerializer` snapshots one nav only — nested-tab stack state isn't
|
|
165
|
+
persisted across reload yet.
|
|
166
|
+
|
|
167
|
+
### Per-stack header chrome
|
|
168
|
+
|
|
169
|
+
`<Stack>` accepts a default slot — its children render *inside* the
|
|
170
|
+
stack's nav scope, above the active screen. That's how to give a
|
|
171
|
+
nested per-tab stack its own header, since the root-level `<Header />`
|
|
172
|
+
only tracks the root navigator:
|
|
173
|
+
|
|
174
|
+
```tsx
|
|
175
|
+
<Tabs.Screen name="trips" label="Trips">
|
|
176
|
+
<Stack initialRoute="tripsHome">
|
|
177
|
+
<Header /> {/* useNav() here resolves to the per-tab nav */}
|
|
178
|
+
</Stack>
|
|
179
|
+
</Tabs.Screen>
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Without this, a `<Header />` placed as a sibling of `<Stack>` would
|
|
183
|
+
resolve `useNav()` to the *enclosing* nav and never react to pushes
|
|
184
|
+
inside the nested stack — the back button + title wouldn't update on
|
|
185
|
+
`nav.push('tripDetail', ...)`.
|
|
186
|
+
|
|
187
|
+
For a daisy-themed bar (height, padding, centred title, separator),
|
|
188
|
+
use `<NavHeader />` from `@sigx/lynx-daisyui` — same slot position,
|
|
189
|
+
same `useScreenChrome()` data source.
|
|
102
190
|
|
|
103
191
|
### `<Screen>`
|
|
104
192
|
|
|
@@ -126,13 +214,61 @@ const Profile = component(() => () => (
|
|
|
126
214
|
All sub-slots are optional. Anything not declared falls back to the
|
|
127
215
|
navigator's default chrome.
|
|
128
216
|
|
|
217
|
+
**Placement — `<Screen>` is a child component, return it from
|
|
218
|
+
render.** `<Screen>` and its slot-filler siblings (`<Screen.Header>`,
|
|
219
|
+
`<Screen.HeaderRight>`, etc.) each call `useScreenRegistry()` from
|
|
220
|
+
their *own* setup, which means they have to actually mount inside
|
|
221
|
+
your screen's `<EntryScope>` to find the registry — and that only
|
|
222
|
+
happens when JSX returned from your render function is reconciled
|
|
223
|
+
into the tree. Constructing `<Screen ... />` JSX inside setup without
|
|
224
|
+
returning it doesn't mount anything:
|
|
225
|
+
|
|
226
|
+
```tsx
|
|
227
|
+
// ✗ Won't take effect — the JSX is created but never rendered.
|
|
228
|
+
const Profile = component(() => {
|
|
229
|
+
<Screen title="Profile" />;
|
|
230
|
+
return () => <view>profile body</view>;
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
// ✓ Returned from render — gets mounted, registers its options.
|
|
234
|
+
const Profile = component(() => {
|
|
235
|
+
return () => (
|
|
236
|
+
<Screen title="Profile">
|
|
237
|
+
<view>profile body</view>
|
|
238
|
+
</Screen>
|
|
239
|
+
);
|
|
240
|
+
});
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
When `<Screen>` *does* mount outside of any `<EntryScope>` — typically
|
|
244
|
+
because the consumer placed it at the app root instead of inside a
|
|
245
|
+
route component — it throws:
|
|
246
|
+
|
|
247
|
+
> `[lynx-navigation] No screen registry in scope. `<Screen>` (and
|
|
248
|
+
> `<Screen.Header>`, etc.) must be used inside a route component
|
|
249
|
+
> rendered by `<Stack>`.`
|
|
250
|
+
|
|
251
|
+
If you need to write options *imperatively* at setup time (e.g. to
|
|
252
|
+
react to a hook result before the first render), reach for
|
|
253
|
+
`useScreenOptions(...)` — it calls `useScreenRegistry()` directly
|
|
254
|
+
from your own setup, where the EntryScope's registry is already
|
|
255
|
+
visible.
|
|
256
|
+
|
|
129
257
|
### `<Header>`
|
|
130
258
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
259
|
+
**Headless** default navigator header — bare `<view>`/`<text>` nodes,
|
|
260
|
+
no flex direction, no padding, no theme. Reads the focused entry's
|
|
261
|
+
`<Screen.Header>` slot if set, otherwise renders
|
|
262
|
+
`headerLeft | title | headerRight` with a back button as the default
|
|
263
|
+
`headerLeft` when `nav.canGoBack` is true. Pulls `title` /
|
|
264
|
+
`headerShown` / `gestureEnabled` from the focused screen's
|
|
265
|
+
`useScreenOptions(...)` registration (or declarative `<Screen title=…>`).
|
|
266
|
+
|
|
267
|
+
For a daisy-themed bar with sensible defaults (surface colour,
|
|
268
|
+
separator, fixed ~48dp height, centred title), use `<NavHeader />`
|
|
269
|
+
from `@sigx/lynx-daisyui` — same data source via `useScreenChrome()`.
|
|
270
|
+
Custom designs can build their own component on top of
|
|
271
|
+
`useScreenChrome()` without touching internals.
|
|
136
272
|
|
|
137
273
|
```tsx
|
|
138
274
|
<NavigationRoot routes={routes} initialRoute="home">
|
|
@@ -143,7 +279,10 @@ screen's `useScreenOptions(...)` registration.
|
|
|
143
279
|
|
|
144
280
|
### `<Tabs>` + `<Tabs.Screen>` + `<TabBar>`
|
|
145
281
|
|
|
146
|
-
Persistent tab navigator. Each tab
|
|
282
|
+
Persistent tab navigator. Each tab body stays mounted (hidden via
|
|
283
|
+
`display: none`) so switching tabs preserves state. Drop a `<Stack
|
|
284
|
+
initialRoute=…>` inside a `<Tabs.Screen>` to give that tab its own
|
|
285
|
+
back-stack — see [Per-tab nested stacks](#per-tab-nested-stacks).
|
|
147
286
|
|
|
148
287
|
```tsx
|
|
149
288
|
<Tabs initialTab="home">
|
|
@@ -250,6 +389,49 @@ const Profile = component(() => {
|
|
|
250
389
|
});
|
|
251
390
|
```
|
|
252
391
|
|
|
392
|
+
Equivalent declarative form via `<Screen>`:
|
|
393
|
+
|
|
394
|
+
```tsx
|
|
395
|
+
<Screen title={() => `User ${id}`} />
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
`<Screen>` only patches keys you actually pass — omitting `title`
|
|
399
|
+
won't clear a title set elsewhere on the same entry. Safe to use a
|
|
400
|
+
bare `<Screen>` purely to host `<Screen.HeaderRight>` slots without
|
|
401
|
+
worrying about wiping a sibling `useScreenOptions(...)` write.
|
|
402
|
+
|
|
403
|
+
### `useScreenChrome()`
|
|
404
|
+
|
|
405
|
+
Reactive read of the focused screen's options + slot fills, plus
|
|
406
|
+
navigation helpers a header would need (`canGoBack`, `pop`). The
|
|
407
|
+
public foundation for building custom header components without
|
|
408
|
+
touching internal modules — `<NavHeader />` in `@sigx/lynx-daisyui` is
|
|
409
|
+
built on this.
|
|
410
|
+
|
|
411
|
+
```tsx
|
|
412
|
+
import { useScreenChrome } from '@sigx/lynx-navigation';
|
|
413
|
+
|
|
414
|
+
const MyHeader = component(() => {
|
|
415
|
+
const chrome = useScreenChrome();
|
|
416
|
+
return () => {
|
|
417
|
+
if (!chrome.headerShown) return null;
|
|
418
|
+
return (
|
|
419
|
+
<view class="my-header">
|
|
420
|
+
{chrome.canGoBack
|
|
421
|
+
? <view bindtap={chrome.pop}><text>‹ Back</text></view>
|
|
422
|
+
: null}
|
|
423
|
+
<text>{chrome.title}</text>
|
|
424
|
+
{chrome.headerRight?.()}
|
|
425
|
+
</view>
|
|
426
|
+
);
|
|
427
|
+
};
|
|
428
|
+
});
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
Every property is a getter — reading it inside a render or `computed`
|
|
432
|
+
subscribes to the underlying signal, so the consumer re-renders when
|
|
433
|
+
title / slots change.
|
|
434
|
+
|
|
253
435
|
### `useLinkingNav(options?)`
|
|
254
436
|
|
|
255
437
|
Bridges `@sigx/lynx-linking` URL events into the navigator. Call once
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type Define } from '@sigx/lynx';
|
|
2
|
-
import type { StackEntry } from '../types
|
|
2
|
+
import type { StackEntry } from '../types';
|
|
3
3
|
type EntryScopeProps = Define.Prop<'entry', StackEntry, true> & Define.Slot<'default'>;
|
|
4
4
|
/**
|
|
5
5
|
* Provider wrapper for a single screen mount.
|
|
@@ -1 +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;
|
|
1
|
+
{"version":3,"file":"EntryScope.d.ts","sourceRoot":"","sources":["../../src/components/EntryScope.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAyC,KAAK,MAAM,EAAE,MAAM,YAAY,CAAC;AAQhF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE3C,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;;EAgBrB,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `<Layer>` — one row in `<Stack>`'s layered render. Absolutely-
|
|
3
|
+
* positioned host view that fills the Stack's relative wrapper, with
|
|
4
|
+
* an optional MT-bound `translateX` / `translateY` animation driven
|
|
5
|
+
* by a `SharedValue<number>` from the navigator's transition state.
|
|
6
|
+
*
|
|
7
|
+
* `<Stack>` emits one `<Layer>` per entry returned by
|
|
8
|
+
* `computeLayers(...)`. Layer.key in the parent is
|
|
9
|
+
* `layer-${entry.key}-${animationVariant(animation)}` so that:
|
|
10
|
+
*
|
|
11
|
+
* - The same entry under the same animation state is preserved across
|
|
12
|
+
* renders (modal underneath stays mounted through the modal
|
|
13
|
+
* lifecycle; per-tab Stack state survives).
|
|
14
|
+
* - An entry transitioning between animated and static (e.g. a card
|
|
15
|
+
* top after its push transition completes) remounts so the
|
|
16
|
+
* `useAnimatedStyle` binding can be rebound — the underlying
|
|
17
|
+
* `useAnimatedStyle` is set-once at setup and can't switch its
|
|
18
|
+
* mapper at runtime.
|
|
19
|
+
*
|
|
20
|
+
* Layouts:
|
|
21
|
+
* - Host view is `position: absolute; top/right/bottom/left: 0;
|
|
22
|
+
* display: flex; flexDirection: column` so descendants that
|
|
23
|
+
* flex-fill (SafeAreaView, daisyui screens) get a sized parent.
|
|
24
|
+
* - No background. Screens own their own surface colour (typically
|
|
25
|
+
* via a daisy `bg-base-*` class on the screen body).
|
|
26
|
+
*/
|
|
27
|
+
import { type ComponentFactory, type Define } from '@sigx/lynx';
|
|
28
|
+
import type { LayerAnimation } from '../internal/layer-plan';
|
|
29
|
+
import type { RouteMap, StackEntry } from '../types';
|
|
30
|
+
export type LayerProps = Define.Prop<'entry', StackEntry, true> & Define.Prop<'routes', RouteMap, true>
|
|
31
|
+
/** When set, the host view animates per the transform spec. */
|
|
32
|
+
& Define.Prop<'animation', LayerAnimation | null, false>;
|
|
33
|
+
export declare const Layer: ComponentFactory<LayerProps, void, {}>;
|
|
34
|
+
//# sourceMappingURL=Layer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Layer.d.ts","sourceRoot":"","sources":["../../src/components/Layer.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,OAAO,EAIH,KAAK,gBAAgB,EACrB,KAAK,MAAM,EAEd,MAAM,YAAY,CAAC;AAEpB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAGrD,MAAM,MAAM,UAAU,GAChB,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,IAAI,CAAC,GACtC,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,CAAC;AACvC,+DAA+D;GAC7D,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,cAAc,GAAG,IAAI,EAAE,KAAK,CAAC,CAAC;AAE7D,eAAO,MAAM,KAAK,wCAkDhB,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { RouteId, RouteParams, RouteSearch } from '../register
|
|
2
|
-
import type { RoutesWithParams } from '../hooks/use-nav
|
|
1
|
+
import type { RouteId, RouteParams, RouteSearch } from '../register';
|
|
2
|
+
import type { RoutesWithParams } from '../hooks/use-nav';
|
|
3
3
|
/**
|
|
4
4
|
* Per-route conditional props for `<Link>`.
|
|
5
5
|
*
|
|
@@ -1 +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,
|
|
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,aAAa,CAAC;AACrE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEzD;;;;;;;;;;;;;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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type Define } from '@sigx/lynx';
|
|
2
|
-
import type { RouteId } from '../register
|
|
3
|
-
import type { RouteMap } from '../types
|
|
2
|
+
import type { RouteId } from '../register';
|
|
3
|
+
import type { RouteMap } from '../types';
|
|
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.
|
|
@@ -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,
|
|
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,aAAa,CAAC;AAC3C,OAAO,KAAK,EAAgB,QAAQ,EAAc,MAAM,UAAU,CAAC;AAGnE,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"}
|
|
@@ -50,9 +50,9 @@ type TabBarItemProps = Define.Slot<'default'>;
|
|
|
50
50
|
* call site shown in the file header.
|
|
51
51
|
*/
|
|
52
52
|
export declare const Screen: ((props: {
|
|
53
|
-
title?: string | (() => string) | undefined;
|
|
54
|
-
headerShown?: boolean | undefined;
|
|
55
53
|
gestureEnabled?: boolean | undefined;
|
|
54
|
+
headerShown?: boolean | undefined;
|
|
55
|
+
title?: string | (() => string) | undefined;
|
|
56
56
|
} & {} & {
|
|
57
57
|
slots?: Partial<{
|
|
58
58
|
default: () => import("@sigx/runtime-core").JSXElement | import("@sigx/runtime-core").JSXElement[] | null;
|
|
@@ -62,18 +62,18 @@ export declare const Screen: ((props: {
|
|
|
62
62
|
children?: any;
|
|
63
63
|
}) => import("@sigx/runtime-core").JSXElement) & {
|
|
64
64
|
__setup: import("@sigx/runtime-core").SetupFn<{
|
|
65
|
-
title?: string | (() => string) | undefined;
|
|
66
|
-
headerShown?: boolean | undefined;
|
|
67
65
|
gestureEnabled?: boolean | undefined;
|
|
66
|
+
headerShown?: boolean | undefined;
|
|
67
|
+
title?: string | (() => string) | undefined;
|
|
68
68
|
}, ScreenProps, void, {
|
|
69
69
|
default: () => import("@sigx/runtime-core").JSXElement | import("@sigx/runtime-core").JSXElement[] | null;
|
|
70
70
|
}>;
|
|
71
71
|
__name?: string;
|
|
72
72
|
__islandId?: string;
|
|
73
73
|
__props: {
|
|
74
|
-
title?: string | (() => string) | undefined;
|
|
75
|
-
headerShown?: boolean | undefined;
|
|
76
74
|
gestureEnabled?: boolean | undefined;
|
|
75
|
+
headerShown?: boolean | undefined;
|
|
76
|
+
title?: string | (() => string) | undefined;
|
|
77
77
|
};
|
|
78
78
|
__events: ScreenProps;
|
|
79
79
|
__ref: void;
|
|
@@ -1 +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;
|
|
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;AAKjE,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;AAiB7B,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;;;4BA1EwB,MAAM;;;;;;;;;;;;gCAAN,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+E/C,CAAC"}
|
|
@@ -1,21 +1,91 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type Define } from '@sigx/lynx';
|
|
2
|
+
type StackProps =
|
|
3
|
+
/**
|
|
4
|
+
* Mint a nested navigator with this route at its base. When set, the
|
|
5
|
+
* `<Stack>` becomes the owner of a new `NavigatorState` and provides
|
|
6
|
+
* `useNav` / `useNavInternals` / `useNavRoutes` to its subtree, so
|
|
7
|
+
* `nav.push('card-route', …)` from inside the stack stays *inside* it
|
|
8
|
+
* (e.g. for per-tab stacks). Routes presented as `modal` / `fullScreen` /
|
|
9
|
+
* `transparent-modal` automatically escalate to the parent navigator
|
|
10
|
+
* via `nav.parent`, walking up until they reach the root — so modals
|
|
11
|
+
* still overlay the whole app.
|
|
12
|
+
*
|
|
13
|
+
* Omit to render the *enclosing* navigator's stack (the default — this
|
|
14
|
+
* is how `<NavigationRoot> → <Stack />` works).
|
|
15
|
+
*/
|
|
16
|
+
Define.Prop<'initialRoute', string>
|
|
17
|
+
/** Initial params for the nested-stack base entry. */
|
|
18
|
+
& Define.Prop<'initialParams', Record<string, unknown>>
|
|
19
|
+
/** Initial search for the nested-stack base entry. */
|
|
20
|
+
& Define.Prop<'initialSearch', Record<string, unknown>>
|
|
21
|
+
/**
|
|
22
|
+
* Optional chrome rendered *above* the active screen, **inside this
|
|
23
|
+
* Stack's nav scope**. The intended use is `<Header />`, which needs
|
|
24
|
+
* to resolve `useNav()` to the per-stack nav (not the enclosing one)
|
|
25
|
+
* so it can react to pushes inside this stack — e.g. show a back
|
|
26
|
+
* button when a card is pushed onto a per-tab stack.
|
|
27
|
+
*
|
|
28
|
+
* Without this, a `<Header />` placed as a sibling of `<Stack>`
|
|
29
|
+
* would see the enclosing nav and never update when pushes happen
|
|
30
|
+
* inside the nested stack.
|
|
31
|
+
*/
|
|
32
|
+
& Define.Slot<'default'>;
|
|
2
33
|
/**
|
|
3
34
|
* Stack navigator — renders the topmost stack entry's component at rest, or
|
|
4
35
|
* the top + underneath entries during a transition.
|
|
5
36
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
37
|
+
* Two modes:
|
|
38
|
+
*
|
|
39
|
+
* **Bound** (no `initialRoute`): renders the enclosing navigator's stack.
|
|
40
|
+
* This is the shape used directly under `<NavigationRoot>` and is what
|
|
41
|
+
* single-stack apps want.
|
|
42
|
+
*
|
|
43
|
+
* **Nested-owner** (`initialRoute="…"`): mints a fresh `NavigatorState` with
|
|
44
|
+
* its own progress `SharedValue` and edge-back gesture, and provides
|
|
45
|
+
* `useNav` / `useNavInternals` / `useNavRoutes` to its subtree. `useNav()`
|
|
46
|
+
* inside this stack returns the nested nav; `nav.parent` points to the
|
|
47
|
+
* enclosing one. Per-tab stacks are the canonical use case:
|
|
48
|
+
*
|
|
49
|
+
* ```tsx
|
|
50
|
+
* <Tabs initialTab="trips">
|
|
51
|
+
* <Tabs.Screen name="trips"><Stack initialRoute="tripsHome" /></Tabs.Screen>
|
|
52
|
+
* <Tabs.Screen name="map"><Stack initialRoute="mapHome" /></Tabs.Screen>
|
|
53
|
+
* </Tabs>
|
|
54
|
+
* ```
|
|
55
|
+
*
|
|
56
|
+
* Modal/fullScreen pushes escalate up the parent chain automatically — so
|
|
57
|
+
* `nav.push('newTrip')` from inside Trips (where `newTrip` is `modal`)
|
|
58
|
+
* walks to root and overlays the whole UI. `replace` stays strictly local
|
|
59
|
+
* (asymmetric with `push`) so a modal `replace` never wipes the root stack.
|
|
60
|
+
*
|
|
61
|
+
* **Render strategy.** Stack always emits the same JSX shape — a
|
|
62
|
+
* relative wrapper containing one `<Layer>` per entry returned by
|
|
63
|
+
* `computeLayers(stack, transition, progress)`. Each Layer is an
|
|
64
|
+
* absolutely-positioned host view with optional MT-bound translate
|
|
65
|
+
* animation. The pure layer-plan function decides:
|
|
9
66
|
*
|
|
10
|
-
* **
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
67
|
+
* - **Idle.** Topmost non-overlay base + any overlays above it. All
|
|
68
|
+
* static (no transform). Overlays (`modal` / `fullScreen` /
|
|
69
|
+
* `transparent-modal`) keep their underneath mounted; cards
|
|
70
|
+
* replace their underneath in the base layer.
|
|
71
|
+
* - **Card transition.** Both top and underneath animate (slide-in
|
|
72
|
+
* + parallax). After settle, idle rules apply — the underneath
|
|
73
|
+
* unmounts because the new top is the sole base.
|
|
74
|
+
* - **Overlay transition.** The full idle layer stack up through
|
|
75
|
+
* the underneath stays static; only the animated top has a
|
|
76
|
+
* transform. After settle, the overlay either joins the static
|
|
77
|
+
* idle stack (push) or unmounts (pop).
|
|
14
78
|
*
|
|
15
|
-
* `
|
|
16
|
-
*
|
|
17
|
-
* (
|
|
18
|
-
*
|
|
79
|
+
* Layer keys are `layer-${entry.key}-${animationVariant}`. The variant
|
|
80
|
+
* suffix forces a remount when an entry transitions from animated to
|
|
81
|
+
* static (or vice versa) — `useAnimatedStyle` binds once at setup and
|
|
82
|
+
* can't switch its mapper at runtime. Modal underneath layers never
|
|
83
|
+
* animate, so their key is stable across the modal lifecycle and the
|
|
84
|
+
* subtree's state (per-tab Stack navigators, scroll positions,
|
|
85
|
+
* in-flight inputs) survives.
|
|
19
86
|
*/
|
|
20
|
-
export declare const Stack: ComponentFactory<
|
|
87
|
+
export declare const Stack: import("@sigx/runtime-core").ComponentFactory<StackProps, void, {
|
|
88
|
+
default: () => import("@sigx/runtime-core").JSXElement | import("@sigx/runtime-core").JSXElement[] | null;
|
|
89
|
+
}>;
|
|
90
|
+
export {};
|
|
21
91
|
//# sourceMappingURL=Stack.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Stack.d.ts","sourceRoot":"","sources":["../../src/components/Stack.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"Stack.d.ts","sourceRoot":"","sources":["../../src/components/Stack.tsx"],"names":[],"mappings":"AAAA,OAAO,EAOH,KAAK,MAAM,EACd,MAAM,YAAY,CAAC;AAepB,KAAK,UAAU;AACX;;;;;;;;;;;;GAYG;AACD,MAAM,CAAC,IAAI,CAAC,cAAc,EAAE,MAAM,CAAC;AACrC,sDAAsD;GACpD,MAAM,CAAC,IAAI,CAAC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AACvD,sDAAsD;GACpD,MAAM,CAAC,IAAI,CAAC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AACvD;;;;;;;;;;GAUG;GACD,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;AAI7B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AACH,eAAO,MAAM,KAAK;;EAuPhB,CAAC"}
|
|
@@ -1,32 +1,31 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `<TabBar>` — default chrome for `<Tabs>`.
|
|
2
|
+
* `<TabBar>` — headless default chrome for `<Tabs>`.
|
|
3
3
|
*
|
|
4
|
-
* Renders
|
|
5
|
-
* navigator.
|
|
6
|
-
*
|
|
4
|
+
* Renders the active-tab buttons reading from the enclosing `useTabs()`
|
|
5
|
+
* navigator. Intentionally **unstyled** — this lives in the (theme-less)
|
|
6
|
+
* navigation package, so it ships pure structure + accessibility wiring.
|
|
7
|
+
* Themed chrome belongs in a UI-kit package: see `<NavTabBar />` in
|
|
8
|
+
* `@sigx/lynx-daisyui` for the daisy-themed equivalent.
|
|
7
9
|
*
|
|
8
|
-
*
|
|
10
|
+
* Use this directly only if you want to handle styling yourself via the
|
|
11
|
+
* `renderTab` prop. For a "looks like a tab bar out of the box" component,
|
|
12
|
+
* pull `<NavTabBar />` from `@sigx/lynx-daisyui` (or your own UI kit).
|
|
13
|
+
*
|
|
14
|
+
* Customization:
|
|
9
15
|
* - `renderTab`: a function `(info, ctx) => JSX` that fully replaces the
|
|
10
16
|
* default button rendering for each tab. `ctx.active` tells the
|
|
11
17
|
* consumer whether this tab is currently focused; `ctx.onPress`
|
|
12
|
-
* activates the tab.
|
|
13
|
-
*
|
|
14
|
-
* Accessibility:
|
|
15
|
-
* - Each default button gets `accessibility-label` from
|
|
16
|
-
* `info.accessibilityLabel ?? info.label ?? info.name`.
|
|
17
|
-
* - Each default button gets `accessibility-element="true"` so screen
|
|
18
|
-
* readers see the whole pill, not just the inner `<text>`.
|
|
19
|
-
* - Each default button gets `accessibility-trait="button"` and a
|
|
20
|
-
* `selected` flag on the active one so VoiceOver/TalkBack announces
|
|
21
|
-
* focus state on tab switch.
|
|
18
|
+
* activates the tab. **Recommended** for any visual treatment.
|
|
22
19
|
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
20
|
+
* Accessibility (baked into the default button — the one structural
|
|
21
|
+
* concern this component keeps):
|
|
22
|
+
* - `accessibility-label` from `info.accessibilityLabel ?? info.label ?? info.name`.
|
|
23
|
+
* - `accessibility-element="true"` so screen readers see the whole pill.
|
|
24
|
+
* - `accessibility-trait="button"` and a `selected` flag on the active
|
|
25
|
+
* one so VoiceOver/TalkBack announces focus state on tab switch.
|
|
27
26
|
*/
|
|
28
27
|
import { type JSXElement } from '@sigx/lynx';
|
|
29
|
-
import { type TabInfo } from './Tabs
|
|
28
|
+
import { type TabInfo } from './Tabs';
|
|
30
29
|
/** Rendering context passed to a `renderTab` consumer. */
|
|
31
30
|
export interface TabRenderContext {
|
|
32
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
|
|
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"}
|
|
@@ -4,31 +4,32 @@
|
|
|
4
4
|
* Usage:
|
|
5
5
|
*
|
|
6
6
|
* ```tsx
|
|
7
|
-
* <NavigationRoot routes={routes}>
|
|
8
|
-
* <
|
|
9
|
-
* <Tabs.Screen name="feed" icon={<FeedIcon />} label="Feed">
|
|
10
|
-
* <FeedView />
|
|
11
|
-
* </Tabs.Screen>
|
|
12
|
-
* <Tabs.Screen name="me" icon={<MeIcon />} label="Profile">
|
|
13
|
-
* <ProfileView />
|
|
14
|
-
* </Tabs.Screen>
|
|
15
|
-
* </Tabs>
|
|
7
|
+
* <NavigationRoot routes={routes} initialRoute="root">
|
|
8
|
+
* <Stack />
|
|
16
9
|
* </NavigationRoot>
|
|
17
|
-
* ```
|
|
18
10
|
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
11
|
+
* // The route "root" component renders:
|
|
12
|
+
* <Tabs initialTab="feed">
|
|
13
|
+
* <Tabs.Screen name="feed" icon={<FeedIcon />} label="Feed">
|
|
14
|
+
* <Stack initialRoute="feedHome" />
|
|
15
|
+
* </Tabs.Screen>
|
|
16
|
+
* <Tabs.Screen name="me" icon={<MeIcon />} label="Profile">
|
|
17
|
+
* <Stack initialRoute="profileHome" />
|
|
18
|
+
* </Tabs.Screen>
|
|
19
|
+
* <TabBar />
|
|
20
|
+
* </Tabs>
|
|
21
|
+
* ```
|
|
22
22
|
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
* - Named navigators (`useNav('root')`)
|
|
23
|
+
* Tab bodies stay mounted across switches (the inactive ones render with
|
|
24
|
+
* `display: 'none'`), so each tab's nested `<Stack>` keeps its history when
|
|
25
|
+
* the user flips back to it. The active tab is reactive via `useTabs()`.
|
|
27
26
|
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
27
|
+
* Per-tab stacks: each `<Tabs.Screen>` can host a `<Stack initialRoute="…">`
|
|
28
|
+
* which mints its own navigator. `useNav()` inside that subtree resolves to
|
|
29
|
+
* the tab's stack, so `nav.push('card-route', …)` stays inside the tab.
|
|
30
|
+
* Routes presented as `modal` / `fullScreen` / `transparent-modal` escalate
|
|
31
|
+
* up `nav.parent` to the root navigator automatically — they overlay the
|
|
32
|
+
* tabs UI (TabBar included) and dismiss back into the originating tab.
|
|
32
33
|
*/
|
|
33
34
|
import { type Define, type JSXElement } from '@sigx/lynx';
|
|
34
35
|
/** Metadata about a registered `<Tabs.Screen>`. */
|
|
@@ -59,6 +60,14 @@ export interface TabsNav {
|
|
|
59
60
|
* Access the enclosing Tabs navigator. Throws when called outside `<Tabs>`.
|
|
60
61
|
*/
|
|
61
62
|
export declare const useTabs: import("@sigx/runtime-core").InjectableFunction<TabsNav>;
|
|
63
|
+
/**
|
|
64
|
+
* @internal
|
|
65
|
+
* Provided by each `<Tabs.Screen>` so a nested `<Stack initialRoute>` can
|
|
66
|
+
* discover *which* tab it's hosted by, and gate its focus state on that
|
|
67
|
+
* tab being active. Throws when called outside a `<Tabs.Screen>` body so
|
|
68
|
+
* the gate degrades to "always active" via the caller's try/catch.
|
|
69
|
+
*/
|
|
70
|
+
export declare const useTabScreenName: import("@sigx/runtime-core").InjectableFunction<string>;
|
|
62
71
|
type TabsProps = Define.Prop<'initialTab', string> & Define.Slot<'default'>;
|
|
63
72
|
type TabsScreenProps = Define.Prop<'name', string, true> & Define.Prop<'icon', JSXElement> & Define.Prop<'label', string> & Define.Prop<'accessibilityLabel', string> & Define.Slot<'default'>;
|
|
64
73
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tabs.d.ts","sourceRoot":"","sources":["../../src/components/Tabs.tsx"],"names":[],"mappings":"AAAA
|
|
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"}
|
package/dist/define-routes.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"define-routes.d.ts","sourceRoot":"","sources":["../src/define-routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"define-routes.d.ts","sourceRoot":"","sources":["../src/define-routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAExC;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,YAAY,CAAC,KAAK,CAAC,CAAC,SAAS,QAAQ,EAAE,MAAM,EAAE,CAAC,GAAG,CAAC,CAEnE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-focus.d.ts","sourceRoot":"","sources":["../../src/hooks/use-focus.ts"],"names":[],"mappings":"AAAA,OAAO,EAKH,KAAK,QAAQ,EAChB,MAAM,YAAY,CAAC;AAIpB;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,YAAY,IAAI,QAAQ,CAAC,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"use-focus.d.ts","sourceRoot":"","sources":["../../src/hooks/use-focus.ts"],"names":[],"mappings":"AAAA,OAAO,EAKH,KAAK,QAAQ,EAChB,MAAM,YAAY,CAAC;AAIpB;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,YAAY,IAAI,QAAQ,CAAC,OAAO,CAAC,CAahD;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CA0BlE"}
|