Screens


AuthScreen

A complete authentication screen with support for login, registration, and OTP flows. Renders a form, optional OAuth provider buttons, and an optional footer slot.

PropTypeDefaultDescription
variant?'login' | 'register' | 'otp''login'Which authentication flow to render
title?stringScreen heading
subtitle?stringText below the heading
logo?React.ReactNodeLogo rendered above the title
onSubmit?(values: Record<string, string>) => voidCalled when the form is submitted
onOAuthPress?(provider: string) => voidCalled when an OAuth button is pressed
oauthProviders?Array<{ key: string; label: string; icon?: string }>List of OAuth provider buttons to render
footer?React.ReactNodeSlot rendered below the form (e.g. sign-up link)
loading?booleanfalseDisables interaction and shows loading state
accessibilityLabel?stringAccessibility label
import { AuthScreen } from '@objectifthunes/limestone-sdk';

<AuthScreen
  variant="login"
  title="Welcome back"
  subtitle="Sign in to your account"
  oauthProviders={[
    { key: 'google', label: 'Continue with Google', icon: 'google' },
    { key: 'apple', label: 'Continue with Apple', icon: 'apple' },
  ]}
  onSubmit={(values) => signIn(values.email, values.password)}
  onOAuthPress={(provider) => signInWithOAuth(provider)}
  loading={isSubmitting}
/>

OnboardingScreen

A paginated onboarding flow rendered as a sequence of full-screen slides. Each slide contains a title, description, and optional illustration.

PropTypeDefaultDescription
stepsOnboardingStep[]Ordered array of slides; each has title, description, and optional image
onComplete?() => voidCalled when the user reaches the last step and presses the complete button
onSkip?() => voidCalled when the user presses Skip
showSkip?booleantrueWhether to render the Skip button
completeLabel?string'Get started'Label for the button on the final slide
nextLabel?string'Next'Label for the next button on intermediate slides
skipLabel?string'Skip'Label for the skip button
accessibilityLabel?stringAccessibility label
import { OnboardingScreen } from '@objectifthunes/limestone-sdk';

const steps = [
  { title: 'Track anything', description: 'Add tasks, habits, and goals in seconds.' },
  { title: 'Stay in sync', description: 'Everything updates across all your devices.' },
  { title: 'Review and grow', description: 'Weekly summaries keep you on track.' },
];

<OnboardingScreen
  steps={steps}
  showSkip
  onSkip={() => router.replace('/home')}
  onComplete={() => router.replace('/home')}
/>

SettingsScreen

A grouped settings list where each row is a toggle, navigation link, or read-only info item. Groups have optional titled headers.

PropTypeDefaultDescription
groupsSettingsGroup[]Array of setting groups; each has an optional title and an array of SettingsItem
header?React.ReactNodeOptional slot rendered above all groups (e.g. user profile card)
accessibilityLabel?stringAccessibility label

Each SettingsItem has: key, label, type ('toggle' | 'navigation' | 'info'), optional value, onPress, onValueChange, icon, and destructive.

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

const groups = [
  {
    title: 'Account',
    items: [
      { key: 'profile', label: 'Edit profile', type: 'navigation', onPress: () => router.push('/profile') },
      { key: 'email', label: 'Email', type: 'info', value: 'alice@example.com' },
    ],
  },
  {
    title: 'Preferences',
    items: [
      { key: 'notifications', label: 'Push notifications', type: 'toggle', value: true, onValueChange: setNotifications },
      { key: 'darkMode', label: 'Dark mode', type: 'toggle', value: false, onValueChange: setDarkMode },
    ],
  },
  {
    items: [
      { key: 'signOut', label: 'Sign out', type: 'navigation', destructive: true, onPress: signOut },
    ],
  },
];

<SettingsScreen groups={groups} />

ProfileScreen

A user profile screen with avatar, name, email, bio, stats row, and an action list.

PropTypeDefaultDescription
namestringDisplay name (required)
email?stringEmail shown below the name
avatar?{ src?: string; name?: string }Avatar image URL and/or name for initials fallback
bio?stringShort biography text
stats?Array<{ label: string; value: string }>Numeric stats displayed in a horizontal row
actions?Array<{ label: string; onPress: () => void; destructive?: boolean }>Action buttons rendered below the bio
accessibilityLabel?stringAccessibility label
import { ProfileScreen } from '@objectifthunes/limestone-sdk';

<ProfileScreen
  name="Alice Martin"
  email="alice@example.com"
  avatar={{ src: 'https://example.com/alice.jpg', name: 'Alice Martin' }}
  bio="Product designer & weekend hiker."
  stats={[
    { label: 'Posts', value: '142' },
    { label: 'Followers', value: '1.2k' },
    { label: 'Following', value: '98' },
  ]}
  actions={[
    { label: 'Edit profile', onPress: () => router.push('/profile/edit') },
    { label: 'Delete account', onPress: deleteAccount, destructive: true },
  ]}
/>

ListDetailScreen

A detail screen with an optional hero image, title, subtitle, body content area, and an actions slot at the bottom.

PropTypeDefaultDescription
titlestringPrimary heading (required)
subtitle?stringSecondary text below the title
content?React.ReactNodeBody content rendered in the scrollable area
headerImage?React.ReactNodeHero image rendered at the top
onBack?() => voidCalled when the user presses the back affordance
actions?React.ReactNodeSlot for CTA buttons at the bottom
accessibilityLabel?stringAccessibility label
import { ListDetailScreen, Text, Stack } from '@objectifthunes/limestone-sdk';

<ListDetailScreen
  title="Getting started"
  subtitle="Read time: 5 min"
  onBack={() => router.back()}
  content={
    <Stack gap="md">
      <Text variant="body">Install the SDK and wrap your app with LimestoneProvider.</Text>
    </Stack>
  }
/>

PaywallScreen

A subscription paywall with a plan picker, feature list per plan, purchase button, and restore link.

PropTypeDefaultDescription
plansPlan[]Available plans; each has key, name, price, period?, features, popular?
selectedPlan?stringKey of the currently highlighted plan
onSelectPlan?(key: string) => voidCalled when the user taps a plan card
onPurchase?() => voidCalled when the purchase button is pressed
onRestore?() => voidCalled when the restore purchases link is pressed
title?stringScreen heading
subtitle?stringText below the heading
purchaseLabel?string'Subscribe'Label for the purchase button
restoreLabel?string'Restore purchases'Label for the restore link
termsText?stringLegal text rendered below the purchase button
accessibilityLabel?stringAccessibility label
import { PaywallScreen } from '@objectifthunes/limestone-sdk';

const plans = [
  {
    key: 'monthly',
    name: 'Monthly',
    price: '$9.99',
    period: 'per month',
    features: ['Unlimited projects', 'Priority support'],
  },
  {
    key: 'annual',
    name: 'Annual',
    price: '$79.99',
    period: 'per year',
    features: ['Unlimited projects', 'Priority support', '2 months free'],
    popular: true,
  },
];

<PaywallScreen
  title="Upgrade to Pro"
  subtitle="Unlock all features"
  plans={plans}
  selectedPlan={selectedPlan}
  onSelectPlan={setSelectedPlan}
  onPurchase={purchase}
  onRestore={restorePurchases}
/>

ChatScreen

A real-time chat interface with message bubbles, a typing indicator, and a text input bar.

PropTypeDefaultDescription
messagesChatMessage[]Ordered list of messages; each has id, text, sender ('user' | 'other'), timestamp?, avatar?
onSendMessage?(text: string) => voidCalled when the user submits a message
placeholder?string'Type a message…'Input placeholder text
isTyping?booleanfalseWhen true, a typing indicator is shown
typingLabel?string'Typing…'Text of the typing indicator
accessibilityLabel?stringAccessibility label
import { ChatScreen } from '@objectifthunes/limestone-sdk';

<ChatScreen
  messages={messages}
  onSendMessage={(text) => sendMessage({ text })}
  isTyping={otherUserIsTyping}
  placeholder="Say something…"
/>

SearchScreen

A search screen with a search bar, results list, loading state, and an empty state.

PropTypeDefaultDescription
onSearch?(query: string) => voidCalled when the query changes (debounced by the search bar)
results?unknown[][]Array of result items
renderResult?(item: unknown, index: number) => React.ReactNodeRow renderer for each result
keyExtractor?(item: unknown, index: number) => stringUnique key per result row
placeholder?string'Search…'Search bar placeholder
emptyTitle?string'No results'Heading shown when results is empty
emptyMessage?stringSupporting text for the empty state
loading?booleanfalseShows a loading indicator instead of results
accessibilityLabel?stringAccessibility label
import { SearchScreen, Text, Box } from '@objectifthunes/limestone-sdk';

interface Article { id: string; title: string; }

<SearchScreen
  placeholder="Search articles…"
  results={articles}
  loading={isLoading}
  keyExtractor={(item) => (item as Article).id}
  renderResult={(item) => (
    <Box py="sm" px="md">
      <Text variant="body">{(item as Article).title}</Text>
    </Box>
  )}
  onSearch={fetchArticles}
  emptyTitle="No articles found"
  emptyMessage="Try a different search term."
/>

ErrorScreen

A full-screen error state with an icon, title, message, retry button, and an optional home link.

PropTypeDefaultDescription
title?string'Something went wrong'Error heading
message?stringExplanatory text below the heading
icon?stringIcon name rendered above the title
retryLabel?string'Try again'Label for the retry button
onRetry?() => voidCalled when the retry button is pressed
homeLabel?string'Go home'Label for the home link
onHome?() => voidCalled when the home link is pressed
accessibilityLabel?stringAccessibility label
import { ErrorScreen } from '@objectifthunes/limestone-sdk';

<ErrorScreen
  title="Failed to load"
  message="Check your connection and try again."
  icon="wifi-off"
  onRetry={reload}
  onHome={() => router.replace('/home')}
/>

ForceUpdateScreen

A blocking screen shown when the installed app version is no longer supported. It renders a message and a single update button; it does not offer a way to dismiss.

PropTypeDefaultDescription
title?string'Update required'Screen heading
message?stringExplanation shown below the heading
icon?stringIcon name rendered above the title
updateLabel?string'Update now'Label for the update button
onUpdate?() => voidCalled when the update button is pressed (open the App Store / Play Store)
accessibilityLabel?stringAccessibility label
import { ForceUpdateScreen } from '@objectifthunes/limestone-sdk';

<ForceUpdateScreen
  title="Update required"
  message="This version is no longer supported. Please update to continue."
  onUpdate={() => Linking.openURL(APP_STORE_URL)}
/>

NotificationCenterScreen

A full-screen list of in-app notifications grouped by date (Today, Yesterday, Older). Each row shows the notification icon, title, body, and timestamp. Supports mark-as-read and bulk-clear actions.

PropTypeDefaultDescription
notificationsAppNotification[]Ordered list of notifications; each has id, title, body, timestamp, read, icon?, onPress?
onMarkAllRead?() => voidCalled when the user taps “Mark all as read”
onClearAll?() => voidCalled when the user clears all notifications
onNotificationPress?(id: string) => voidCalled when a notification row is tapped
loading?booleanfalseShows a loading skeleton
accessibilityLabel?stringAccessibility label
import { NotificationCenterScreen } from '@objectifthunes/limestone-sdk';

<NotificationCenterScreen
  notifications={notifications}
  onNotificationPress={(id) => handleNotificationTap(id)}
  onMarkAllRead={markAllRead}
/>

DashboardScreen

A composable summary screen with a greeting header, a stats grid, and configurable widget slots. Widgets are plain React.ReactNode — drop in any component.

PropTypeDefaultDescription
greeting?stringHeading text (e.g. “Good morning, Alice”)
stats?Array<{ label: string; value: string; delta?: string; trend?: 'up' | 'down' | 'neutral' }>KPI cards rendered in a horizontal row
widgets?React.ReactNode[]Full-width widget slots rendered below the stats
header?React.ReactNodeCustom content rendered above the greeting
refreshing?booleanfalseEnables pull-to-refresh
onRefresh?() => voidCalled on pull-to-refresh
accessibilityLabel?stringAccessibility label
import { DashboardScreen } from '@objectifthunes/limestone-sdk';

<DashboardScreen
  greeting="Good morning, Alice"
  stats={[
    { label: 'Revenue', value: '$12,400', delta: '+8%', trend: 'up' },
    { label: 'Orders',  value: '142',     delta: '-3%', trend: 'down' },
  ]}
  widgets={[<RevenueChart key="rev" />, <TopProductsList key="top" />]}
  refreshing={isRefreshing}
  onRefresh={reload}
/>

ProductDetailScreen

A product page with a media carousel, title, price, description, variant selector, and a sticky add-to-cart bar.

PropTypeDefaultDescription
namestringProduct name
imagesstring[]Array of image URIs for the carousel
pricenumberCurrent price
currency?string'USD'ISO 4217 currency code
originalPrice?numberOriginal price (renders discount badge)
description?stringProduct description
variants?ProductVariant[]Each variant: { key, label, options: string[] }
selectedVariants?Record<string, string>Currently selected variant values
onVariantChange?(key: string, value: string) => voidCalled when the user picks a variant
onAddToCart?() => voidCalled when the add-to-cart button is pressed
onBack?() => voidBack navigation handler
loading?booleanfalseShows a loading skeleton
accessibilityLabel?stringAccessibility label
import { ProductDetailScreen } from '@objectifthunes/limestone-sdk';

<ProductDetailScreen
  name="Wireless Headphones"
  images={['https://example.com/img1.jpg', 'https://example.com/img2.jpg']}
  price={89.99}
  originalPrice={129.99}
  description="Premium audio with 30-hour battery life."
  variants={[{ key: 'color', label: 'Color', options: ['Black', 'White', 'Blue'] }]}
  selectedVariants={selectedVariants}
  onVariantChange={setVariant}
  onAddToCart={addToCart}
  onBack={() => router.back()}
/>

OrderTrackingScreen

A live order status screen showing a step-by-step timeline from placement to delivery, with estimated arrival and a map preview.

PropTypeDefaultDescription
orderIdstringOrder reference shown at the top
status'placed' | 'confirmed' | 'preparing' | 'shipped' | 'out_for_delivery' | 'delivered'Current order status
estimatedDelivery?stringHuman-readable ETA label
stepsTrackingStep[]Each step: { key, label, completedAt? }
mapRegion?MapRegionIf provided, renders a small map with the delivery pin
onContactSupport?() => voidCalled when “Contact support” is tapped
onBack?() => voidBack navigation handler
accessibilityLabel?stringAccessibility label
import { OrderTrackingScreen } from '@objectifthunes/limestone-sdk';

<OrderTrackingScreen
  orderId="#10423"
  status="shipped"
  estimatedDelivery="Tomorrow, 12 PM – 4 PM"
  steps={[
    { key: 'placed',    label: 'Order placed',    completedAt: '10:00 AM' },
    { key: 'confirmed', label: 'Confirmed',        completedAt: '10:05 AM' },
    { key: 'preparing', label: 'Being prepared',   completedAt: '11:30 AM' },
    { key: 'shipped',   label: 'Shipped' },
    { key: 'delivered', label: 'Delivered' },
  ]}
  onContactSupport={openSupport}
  onBack={() => router.back()}
/>

TransactionDetailScreen

A financial transaction detail screen showing amount, direction (credit/debit), merchant info, status, and a line-item breakdown.

PropTypeDefaultDescription
amountnumberTransaction amount
currency?string'USD'ISO 4217 currency code
direction'credit' | 'debit'Whether the transaction is incoming or outgoing
merchantName?stringMerchant or counterparty name
merchantLogo?stringMerchant logo URI
status'pending' | 'completed' | 'failed' | 'refunded'Transaction status
date?stringFormatted date string
lineItems?Array<{ label: string; value: string }>Itemised breakdown
onBack?() => voidBack navigation handler
accessibilityLabel?stringAccessibility label
import { TransactionDetailScreen } from '@objectifthunes/limestone-sdk';

<TransactionDetailScreen
  amount={49.99}
  currency="USD"
  direction="debit"
  merchantName="Acme Store"
  status="completed"
  date="March 29, 2026"
  lineItems={[
    { label: 'Subtotal',  value: '$44.99' },
    { label: 'Tax',       value: '$5.00'  },
    { label: 'Total',     value: '$49.99' },
  ]}
  onBack={() => router.back()}
/>

CartScreen

A shopping cart screen listing selected items with quantity controls, a price summary, and a checkout button.

PropTypeDefaultDescription
itemsCartItem[]Each item: { id, name, imageUri?, price, quantity, variantLabel? }
onQuantityChange?(id: string, qty: number) => voidCalled when the user changes item quantity
onRemoveItem?(id: string) => voidCalled when the user removes an item
promoCode?stringApplied promo code
onApplyPromo?(code: string) => voidCalled when a promo code is submitted
subtotalnumberSubtotal before tax and shipping
tax?numberTax amount
shipping?numberShipping cost
totalnumberFinal total
currency?string'USD'ISO 4217 currency code
onCheckout?() => voidCalled when the checkout button is pressed
accessibilityLabel?stringAccessibility label
import { CartScreen } from '@objectifthunes/limestone-sdk';

<CartScreen
  items={cartItems}
  onQuantityChange={(id, qty) => updateQuantity(id, qty)}
  onRemoveItem={(id) => removeFromCart(id)}
  subtotal={subtotal}
  tax={tax}
  total={total}
  onCheckout={proceedToCheckout}
/>

FeedScreen

A social-style vertical feed with pull-to-refresh, infinite scroll, and a new-posts notification banner. Renders any item type via renderItem.

PropTypeDefaultDescription
itemsunknown[]Feed data array
renderItem(item: unknown, index: number) => React.ReactNodeRow renderer
keyExtractor(item: unknown, index: number) => stringUnique key per row
refreshing?booleanfalseControls pull-to-refresh spinner
onRefresh?() => voidCalled on pull-to-refresh
onEndReached?() => voidCalled when nearing the end of the list
newItemCount?number0When > 0, shows a “N new posts” tap-to-scroll banner
onNewItemsBannerPress?() => voidCalled when the new-posts banner is tapped
emptyTitle?string'Nothing here yet'Empty state heading
emptyMessage?stringEmpty state supporting text
accessibilityLabel?stringAccessibility label
import { FeedScreen } from '@objectifthunes/limestone-sdk';

<FeedScreen
  items={posts}
  keyExtractor={(item) => (item as Post).id}
  renderItem={(item) => <PostCard post={item as Post} />}
  refreshing={isRefreshing}
  onRefresh={reload}
  onEndReached={loadMore}
  newItemCount={newPosts.length}
  onNewItemsBannerPress={scrollToTop}
/>

FormWizardScreen

A multi-step form screen with a step indicator, per-step validation, back/next navigation, and a final submit action.

PropTypeDefaultDescription
stepsWizardStep[]Each step: { key, title, content, validate? }
currentStep?number0Controlled active step index
onStepChange?(index: number) => voidCalled when the step changes
onSubmit?() => voidCalled when the user completes the last step
nextLabel?string'Next'Label for the next button
backLabel?string'Back'Label for the back button
submitLabel?string'Submit'Label for the final submit button
loading?booleanfalseDisables navigation and shows loading on submit
accessibilityLabel?stringAccessibility label
import { FormWizardScreen } from '@objectifthunes/limestone-sdk';

const steps = [
  { key: 'account', title: 'Create account', content: <AccountStep /> },
  { key: 'profile', title: 'Your profile',   content: <ProfileStep /> },
  { key: 'billing', title: 'Billing info',   content: <BillingStep /> },
];

<FormWizardScreen
  steps={steps}
  onSubmit={handleSignup}
  loading={isSubmitting}
/>

HistoryScreen

A paginated, filterable history list (transactions, activity log, order history) with date grouping and an optional search bar.

PropTypeDefaultDescription
itemsHistoryItem[]Each item: { id, title, subtitle?, amount?, timestamp, icon?, variant? }
renderItem?(item: HistoryItem) => React.ReactNodeCustom row renderer (overrides default)
filters?HistoryFilter[]Each filter: { key, label } — rendered as chips above the list
activeFilter?stringKey of the currently active filter
onFilterChange?(key: string) => voidCalled when the user taps a filter chip
showSearch?booleanfalseShow a search bar above the filter chips
onSearch?(query: string) => voidCalled when the search query changes
refreshing?booleanfalseControls pull-to-refresh spinner
onRefresh?() => voidCalled on pull-to-refresh
onEndReached?() => voidCalled when nearing the end
emptyTitle?string'No history'Empty state heading
accessibilityLabel?stringAccessibility label
import { HistoryScreen } from '@objectifthunes/limestone-sdk';

<HistoryScreen
  items={transactions}
  filters={[
    { key: 'all',    label: 'All'    },
    { key: 'credit', label: 'Credits' },
    { key: 'debit',  label: 'Debits'  },
  ]}
  activeFilter={filter}
  onFilterChange={setFilter}
  showSearch
  onSearch={searchTransactions}
  onEndReached={loadMore}
/>

MediaDetailScreen

A full-screen media viewer for a single image or video with an optional caption, like/share actions, and a comments section.

PropTypeDefaultDescription
mediaUristringURI of the image or video
mediaType'image' | 'video'Determines which player to render
caption?stringText shown below the media
authorName?stringUploader name
authorAvatarUri?stringUploader avatar URI
likeCount?numberLike count
liked?booleanfalseWhether the current user has liked this item
onLike?() => voidCalled when the like button is pressed
onShare?() => voidCalled when the share button is pressed
comments?Comment[]Comments passed to an inline CommentThread
onAddComment?(text: string) => voidCalled when the user submits a comment
onBack?() => voidBack navigation handler
accessibilityLabel?stringAccessibility label
import { MediaDetailScreen } from '@objectifthunes/limestone-sdk';

<MediaDetailScreen
  mediaUri="https://example.com/photo.jpg"
  mediaType="image"
  caption="Sunset over the Alps."
  authorName="Alice Martin"
  likeCount={142}
  liked={hasLiked}
  onLike={toggleLike}
  onShare={shareMedia}
  comments={comments}
  onAddComment={postComment}
  onBack={() => router.back()}
/>