Hooks

All hooks require <LimestoneProvider> in the tree. Hooks that delegate to an adapter throw at call time if that adapter was not registered in defineConfig.

State hooks

useStore

import { useStore } from '@objectifthunes/limestone-sdk';

// Full snapshot — re-renders on any change
const state = useStore();

// Selector — re-renders only when the selected value changes
const count = useStore((s) => s.count);
const authStatus = useStore((s) => s.auth.status);

Returns AppState (full snapshot) or T (selector result). See the Store guide for details.

useAuth

import { useAuth } from '@objectifthunes/limestone-sdk';

function ProfileHeader() {
  const { status, user, tokens, login, logout } = useAuth();
  if (status !== 'authenticated') return null;
  return <Text>Hello {user?.name as string}</Text>;
}

Returns UseAuthReturn:

FieldTypeDescription
status'idle' | 'authenticating' | 'authenticated' | 'refreshing' | 'error'Current auth lifecycle state
userRecord<string, unknown> | nullAuthenticated user payload
tokens{ accessToken: string; refreshToken: string } | nullCurrent token pair
login(user, tokens)voidSet auth state to authenticated
logout()voidClear auth state and tokens

useNetwork

import { useNetwork } from '@objectifthunes/limestone-sdk';

function OfflineBanner() {
  const { connected, type } = useNetwork();
  if (connected) return null;
  return <Banner message="You are offline" variant="warning" />;
}

Returns NetworkState: { connected: boolean; type: 'wifi' | 'cellular' | 'none' | 'unknown' }.

API hook

useApi

import { useApi } from '@objectifthunes/limestone-sdk';

function UserScreen() {
  const api = useApi();

  React.useEffect(() => {
    api.get<User>('/users/me').then(setUser);
  }, [api]);
}

Returns the ApiClient wired by LimestoneProvider. Throws if api was not in the config.

Adapter hooks

These hooks return the adapter interface directly. Call the provider methods on the returned value.

useBiometrics

import { useBiometrics } from '@objectifthunes/limestone-sdk';

const bio = useBiometrics();
const result = await bio.authenticate({ promptMessage: 'Confirm your identity' });
const avail = await bio.isAvailable();

Returns BiometricProvider. Requires adapters.biometrics.

useHaptics

import { useHaptics } from '@objectifthunes/limestone-sdk';

const haptics = useHaptics();
await haptics.impact('medium');
await haptics.notification('success');
await haptics.selection();

Returns HapticsProvider. Requires adapters.haptics.

useNotifications

import { useNotifications } from '@objectifthunes/limestone-sdk';

const notifications = useNotifications();
const status = await notifications.requestPermission();
const id = await notifications.schedule({ title: 'Reminder', body: 'Check in!' }, { seconds: 60 });
await notifications.setBadgeCount(3);

Returns NotificationProvider. Requires adapters.notifications.

usePermissions

import { usePermissions } from '@objectifthunes/limestone-sdk';

const permissions = usePermissions();
const status = await permissions.check('camera');
if (status !== 'granted') {
  await permissions.request('camera');
}

Returns PermissionsProvider. Requires adapters.permissions.

useInAppReview

import { useInAppReview } from '@objectifthunes/limestone-sdk';

const review = useInAppReview();
const available = await review.isAvailable();
if (available) {
  await review.requestReview();
}

Returns ReviewProvider. Requires adapters.review.

Platform hooks

useKeyboard

import { useKeyboard } from '@objectifthunes/limestone-sdk';

function ChatInput() {
  const { visible, height, dismiss } = useKeyboard();
  return (
    <View style={{ paddingBottom: visible ? height : 0 }}>
      <TextInput onSubmitEditing={dismiss} />
    </View>
  );
}

Returns KeyboardState: { visible: boolean; height: number; dismiss: () => void }.

useAppState

import { useAppState } from '@objectifthunes/limestone-sdk';

function App() {
  const appState = useAppState();

  React.useEffect(() => {
    if (appState === 'active') {
      // refresh data on foreground
    }
  }, [appState]);
}

Returns AppStateStatus: 'active' | 'background' | 'inactive'. Mirrors the React Native AppState type.

import { useDeepLink } from '@objectifthunes/limestone-sdk';

function Navigator() {
  const { url } = useDeepLink();

  React.useEffect(() => {
    if (url) handleDeepLink(url);
  }, [url]);
}

Returns DeepLinkState: { url: string | null }. Updates whenever a deep link arrives.

useOrientation

import { useOrientation } from '@objectifthunes/limestone-sdk';

function VideoPlayer() {
  const orientation = useOrientation();
  const fullscreen = orientation === 'landscape';
  return <Video style={fullscreen ? styles.fullscreen : styles.normal} />;
}

Returns Orientation: 'portrait' | 'landscape'.

useDimensions

import { useDimensions } from '@objectifthunes/limestone-sdk';

function ResponsiveGrid() {
  const { width, height, scale, fontScale } = useDimensions();
  const columns = width > 600 ? 3 : 2;
  return <Grid columns={columns} />;
}

Returns DimensionsState: { width: number; height: number; scale: number; fontScale: number }.

useBackHandler

Android only. Receives a handler that returns true to consume the back event (prevent default navigation).

import { useBackHandler } from '@objectifthunes/limestone-sdk';

function SearchScreen({ isOpen, onClose }) {
  useBackHandler(() => {
    if (isOpen) {
      onClose();
      return true; // consume — do not navigate back
    }
    return false; // pass through to default back behavior
  });
}

Returns void. The handler is registered while the component is mounted and cleaned up on unmount.

useColorScheme

import { useColorScheme } from '@objectifthunes/limestone-sdk';

function AppContent() {
  const scheme = useColorScheme();
  const isDark = scheme === 'dark';
  return <StatusBar style={isDark ? 'light' : 'dark'} />;
}

Returns 'light' | 'dark' | 'unspecified'. Never returns null.

Utility hooks

useDebounce

import { useDebounce } from '@objectifthunes/limestone-sdk';

function SearchBar() {
  const [query, setQuery] = React.useState('');
  const debouncedQuery = useDebounce(query, 300);

  React.useEffect(() => {
    if (debouncedQuery) search(debouncedQuery);
  }, [debouncedQuery]);

  return <TextInput onChangeText={setQuery} />;
}

Signature: useDebounce<T>(value: T, delayMs: number): T. Returns the value after delayMs of quiet time.

Complete hook reference

HookCategoryReturn type
useStore(selector?)StateAppState | T
useAuth()StateUseAuthReturn
useNetwork()StateNetworkState
useApi()APIApiClient
useBiometrics()AdapterBiometricProvider
useHaptics()AdapterHapticsProvider
useNotifications()AdapterNotificationProvider
usePermissions()AdapterPermissionsProvider
useInAppReview()AdapterReviewProvider
useKeyboard()PlatformKeyboardState
useAppState()PlatformAppStateStatus
useDeepLink()PlatformDeepLinkState
useOrientation()PlatformOrientation
useDimensions()PlatformDimensionsState
useBackHandler(handler)Platformvoid
useColorScheme()Platform'light' | 'dark' | 'unspecified'
useDebounce(value, delayMs)UtilityT