Navigation Helpers
Navigation helpers are pure functions that plug into Expo Router. They do not replace the router — they provide reusable patterns for common navigation concerns. All four are exported from the main barrel.
createAuthGuard
Guards a route by reading the current auth status and returning a redirect path when the user is not authenticated.
import { createAuthGuard } from '@objectifthunes/limestone-sdk';
// Inside a layout component:
const guard = createAuthGuard({
useAuth, // () => { status: string }
loginPath: '/login',
authenticatedStatus: 'authenticated', // optional, defaults to 'authenticated'
});
if (guard.redirectPath) {
return <Redirect href={guard.redirectPath} />;
}
Options
| Field | Type | Default | Description |
|---|---|---|---|
useAuth | () => { status: string } | required | Hook or function that returns the current auth status |
loginPath | string | required | Path to redirect to when unauthenticated |
authenticatedStatus | string | 'authenticated' | The exact status string considered authenticated |
Result
| Field | Type | Description |
|---|---|---|
isAuthenticated | boolean | True when status === authenticatedStatus |
redirectPath | string | null | loginPath when unauthenticated, null when authenticated |
createOnboardingFlow
Produces helpers for navigating a multi-step onboarding sequence. Steps are expressed as route path strings.
import { createOnboardingFlow } from '@objectifthunes/limestone-sdk';
const flow = createOnboardingFlow({
steps: [
'/onboarding/welcome',
'/onboarding/profile',
'/onboarding/permissions',
'/onboarding/done',
],
completedKey: 'onboarding_complete',
});
flow.totalSteps; // 4
flow.getNextStep(0); // '/onboarding/profile'
flow.getNextStep(3); // null — last step reached
flow.isComplete(3); // true
flow.isComplete(1); // false
Options
| Field | Type | Description |
|---|---|---|
steps | string[] | Ordered list of route paths for each onboarding step |
completedKey | string | Storage key you use to persist completion (not read by the helper) |
Result
| Field | Type | Description |
|---|---|---|
totalSteps | number | Number of steps |
getNextStep(current) | (n: number) => string | null | Returns the next step’s path, or null on the last step |
isComplete(current) | (n: number) => boolean | True when current >= totalSteps - 1 |
createDeepLinkHandler
Maps deep link URLs to app routes and extracts URL parameters. Protocol prefixes (myapp://, https://, etc.) are stripped automatically.
import { createDeepLinkHandler } from '@objectifthunes/limestone-sdk';
const handler = createDeepLinkHandler({
'app/home': '/home',
'users/:id': '/user-detail',
'teams/:teamId/members/:userId': '/team-member',
});
handler.resolve('myapp://users/42');
// { path: '/user-detail', params: { id: '42' } }
handler.resolve('myapp://teams/abc/members/xyz');
// { path: '/team-member', params: { teamId: 'abc', userId: 'xyz' } }
handler.resolve('myapp://unknown/route');
// null
Routes map
Keys are URL patterns. Use :paramName segments to capture dynamic values. Patterns must have exactly the same number of segments as the incoming URL.
Result type
interface DeepLinkResult {
path: string;
params: Record<string, string>;
}
resolve returns DeepLinkResult when a route matches, or null when no route matches.
createTabLayout
Bundles a tab configuration array with a getTabIndex lookup function.
import { createTabLayout } from '@objectifthunes/limestone-sdk';
const layout = createTabLayout({
tabs: [
{ key: 'home', label: 'Home', icon: 'house' },
{ key: 'explore', label: 'Explore' },
{ key: 'profile', label: 'Profile', badge: 3 },
],
});
layout.tabs; // the full array
layout.getTabIndex('explore'); // 1
layout.getTabIndex('missing'); // -1
TabConfig fields
| Field | Type | Required | Description |
|---|---|---|---|
key | string | yes | Unique identifier for the tab |
label | string | yes | Display label |
icon | string | no | Icon name (passed to your icon component) |
badge | number | no | Badge count shown on the tab |
Result
| Field | Type | Description |
|---|---|---|
tabs | TabConfig[] | The original tabs array |
getTabIndex(key) | (key: string) => number | Index of the tab with the given key, or -1 if not found |