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

FieldTypeDefaultDescription
useAuth() => { status: string }requiredHook or function that returns the current auth status
loginPathstringrequiredPath to redirect to when unauthenticated
authenticatedStatusstring'authenticated'The exact status string considered authenticated

Result

FieldTypeDescription
isAuthenticatedbooleanTrue when status === authenticatedStatus
redirectPathstring | nullloginPath 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

FieldTypeDescription
stepsstring[]Ordered list of route paths for each onboarding step
completedKeystringStorage key you use to persist completion (not read by the helper)

Result

FieldTypeDescription
totalStepsnumberNumber of steps
getNextStep(current)(n: number) => string | nullReturns the next step’s path, or null on the last step
isComplete(current)(n: number) => booleanTrue 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

FieldTypeRequiredDescription
keystringyesUnique identifier for the tab
labelstringyesDisplay label
iconstringnoIcon name (passed to your icon component)
badgenumbernoBadge count shown on the tab

Result

FieldTypeDescription
tabsTabConfig[]The original tabs array
getTabIndex(key)(key: string) => numberIndex of the tab with the given key, or -1 if not found