TextInput
A single-line text field with label, error, hint, and icon support.
Prop Type Default Description valuestring— Controlled value onChangeText(v: string) => void— Change handler label?string— Field label rendered above the input error?string— Error message rendered below the input hint?string— Helper text rendered below the input disabled?booleanfalseDisables the field size?'xs' | 'sm' | 'md' | 'lg' | 'xl''md'Field height and font size variant?'outline' | 'filled' | 'underline''outline'Visual style clearable?booleanfalseShow a clear button when value is non-empty iconLeft?React.ReactElement— Icon rendered on the left side iconRight?React.ReactElement— Icon rendered on the right side keyboardType?KeyboardTypeOptions— Native keyboard type secureTextEntry?booleanfalseMask input (passwords)
Variants
import { TextInput } from '@objectifthunes/limestone-sdk' ;
// Outline (default)
< TextInput value = {value} onChangeText = {setValue} label = "Email" variant = "outline" />
// Filled — solid background, no border
< TextInput value = {value} onChangeText = {setValue} label = "Password" variant = "filled" secureTextEntry />
// Underline — bottom border only
< TextInput value = {value} onChangeText = {setValue} label = "Username" variant = "underline" />
Sizes
< TextInput value = {v} onChangeText = {setV} label = "Extra Small" size = "xs" />
< TextInput value = {v} onChangeText = {setV} label = "Small" size = "sm" />
< TextInput value = {v} onChangeText = {setV} label = "Medium" size = "md" />
< TextInput value = {v} onChangeText = {setV} label = "Large" size = "lg" />
< TextInput value = {v} onChangeText = {setV} label = "Extra Large" size = "xl" />
With icons and error
import { TextInput, Icon } from '@objectifthunes/limestone-sdk' ;
< TextInput
value = {email}
onChangeText = {setEmail}
label = "Email address"
error = {errors.email}
hint = "We'll never share your email."
keyboardType = "email-address"
iconLeft = {<Icon name = "mail" size = "sm" color = "mutedForeground" /> }
clearable
/>
SearchBar
A debounced search input with optional cancel button.
Prop Type Default Description valuestring— Controlled value onChangeText(v: string) => void— Immediate change handler onDebouncedChange?(v: string) => void— Fires after debounceMs of inactivity debounceMs?number300Debounce delay in milliseconds placeholder?string'Search'Placeholder text showCancel?booleanfalseShow a Cancel button to clear and blur size?'xs' | 'sm' | 'md' | 'lg' | 'xl''md'Bar height and font size
import { SearchBar } from '@objectifthunes/limestone-sdk' ;
import { useState } from 'react' ;
function ProductSearch () {
const [ query , setQuery ] = useState ( '' );
return (
< SearchBar
value = {query}
onChangeText = {setQuery}
onDebouncedChange = {(q) => fetchProducts ( q )}
debounceMs = { 400 }
placeholder = "Search products…"
showCancel
/>
);
}
Select
A modal-based picker supporting single and multi-select modes with optional search.
Prop Type Default Description optionsSelectOption[]— Array of { label, value, disabled? } value?string— Selected value (single mode) values?string[]— Selected values (multi mode) onValueChange?(v: string) => void— Single mode change handler onValuesChange?(v: string[]) => void— Multi mode change handler multiple?booleanfalseEnable multi-select searchable?booleanfalseShow a search field inside the picker placeholder?string— Trigger button placeholder text size?'xs' | 'sm' | 'md' | 'lg' | 'xl''md'Trigger button size variant?'outline' | 'filled' | 'underline''outline'Trigger button variant
import { Select } from '@objectifthunes/limestone-sdk' ;
import type { SelectOption } from '@objectifthunes/limestone-sdk' ;
const COUNTRY_OPTIONS : SelectOption [] = [
{ label: 'United States' , value: 'us' },
{ label: 'France' , value: 'fr' },
{ label: 'Germany' , value: 'de' },
];
// Single select
function CountryPicker () {
const [ country , setCountry ] = useState ( '' );
return (
< Select
options = {COUNTRY_OPTIONS}
value = {country}
onValueChange = {setCountry}
placeholder = "Select a country"
searchable
/>
);
}
// Multi-select
function TagPicker () {
const [ tags , setTags ] = useState < string []>([]);
return (
< Select
options = {TAG_OPTIONS}
values = {tags}
onValuesChange = {setTags}
multiple
placeholder = "Select tags"
/>
);
}
Switch
A toggle switch with optional label.
Prop Type Default Description valueboolean— Controlled state onValueChange(v: boolean) => void— Change handler size?'xs' | 'sm' | 'md' | 'lg' | 'xl''md'Switch size trackColor?{ on: string; off: string }— Custom track colors thumbColor?string— Custom thumb color label?string— Label text labelPosition?'left' | 'right''right'Label side
import { Switch } from '@objectifthunes/limestone-sdk' ;
function NotificationToggle () {
const [ enabled , setEnabled ] = useState ( true );
return (
< Switch
value = {enabled}
onValueChange = {setEnabled}
label = "Push notifications"
labelPosition = "left"
/>
);
}
Checkbox and CheckboxGroup
Checkbox is a standalone checked/unchecked control. CheckboxGroup manages a set of CheckboxGroupItem children by value.
Checkbox props
Prop Type Default Description checkedboolean— Controlled state onCheckedChange(v: boolean) => void— Change handler size?SpacingProp'md'Box size variant?'filled' | 'outline''filled'Visual style label?string— Label text labelPosition?'left' | 'right''right'Label side
CheckboxGroup props
Prop Type Default Description valuesstring[]— Array of currently checked values onValuesChange(v: string[]) => void— Change handler direction?'horizontal' | 'vertical''vertical'Layout direction gap?SpacingProp— Gap between items
import { Checkbox, CheckboxGroup, CheckboxGroupItem } from '@objectifthunes/limestone-sdk' ;
import { useState } from 'react' ;
// Standalone
function AcceptTerms () {
const [ accepted , setAccepted ] = useState ( false );
return (
< Checkbox
checked = {accepted}
onCheckedChange = {setAccepted}
label = "I accept the terms and conditions"
/>
);
}
// Group
function PermissionsForm () {
const [ perms , setPerms ] = useState < string []>([ 'camera' ]);
return (
< CheckboxGroup values = {perms} onValuesChange = {setPerms} gap = "sm" >
< CheckboxGroupItem value = "camera" label = "Camera" />
< CheckboxGroupItem value = "microphone" label = "Microphone" />
< CheckboxGroupItem value = "location" label = "Location" />
</ CheckboxGroup >
);
}
RadioGroup and RadioItem
A controlled single-select group. RadioGroup provides context; RadioItem renders each option.
RadioGroup props
Prop Type Default Description valuestring— Currently selected value onValueChange(v: string) => void— Change handler direction?'horizontal' | 'vertical''vertical'Layout direction gap?SpacingProp— Gap between items
RadioItem props
Prop Type Default Description valuestring— Option value label?string— Option label labelPosition?'left' | 'right''right'Label side size?SpacingProp'md'Radio circle size
import { RadioGroup, RadioItem } from '@objectifthunes/limestone-sdk' ;
function ThemePicker () {
const [ theme , setTheme ] = useState ( 'light' );
return (
< RadioGroup value = {theme} onValueChange = {setTheme} gap = "sm" >
< RadioItem value = "light" label = "Light" />
< RadioItem value = "dark" label = "Dark" />
< RadioItem value = "system" label = "System default" />
</ RadioGroup >
);
}
Slider
A range slider with optional value display.
Prop Type Default Description valuenumber— Controlled value minnumber— Minimum value maxnumber— Maximum value step?number1Step increment onValueChange(v: number) => void— Change handler trackHeight?number— Track bar height in pixels thumbSize?number— Thumb circle diameter minimumTrackColor?string— Color for the filled portion maximumTrackColor?string— Color for the unfilled portion thumbColor?string— Thumb color showValue?booleanfalseDisplay current value above thumb formatValue?(v: number) => string— Custom value formatter
import { Slider } from '@objectifthunes/limestone-sdk' ;
function VolumeControl () {
const [ volume , setVolume ] = useState ( 75 );
return (
< Slider
value = {volume}
min = { 0 }
max = { 100 }
step = { 5 }
onValueChange = {setVolume}
showValue
formatValue = {(v) => `${ v }%` }
/>
);
}
A one-time password input rendered as individual digit boxes. secure mode renders each digit as a dot (PinInput style).
Prop Type Default Description length?number6Number of digit boxes value?string— Controlled value onComplete?(v: string) => void— Fires when all boxes are filled secure?booleanfalseMask digits (PinInput mode) keyboardType?KeyboardTypeOptions'number-pad'Keyboard type size?'xs' | 'sm' | 'md' | 'lg' | 'xl''md'Box size gap?SpacingProp'sm'Gap between boxes variant?'outline' | 'filled' | 'underline''outline'Box style
import { OTPInput } from '@objectifthunes/limestone-sdk' ;
// Normal OTP
function VerifyEmail () {
return (
< OTPInput
length = { 6 }
onComplete = {(code) => verifyCode ( code )}
/>
);
}
// Secure PinInput mode
function SetPin () {
return (
< OTPInput
length = { 4 }
secure
onComplete = {(pin) => savePin ( pin )}
/>
);
}
A phone number field with country code picker.
Prop Type Default Description value?string— E.164-formatted phone number, e.g. '+14155552671' onValueChange?(v: string) => void— Change handler (E.164 string) countries?Country[]allCountriesCountry list for the picker defaultCountry?string'US'ISO 3166-1 alpha-2 default size?'xs' | 'sm' | 'md' | 'lg' | 'xl''md'Field size variant?'outline' | 'filled' | 'underline''outline'Field variant
import { PhoneInput, allCountries, popularCountries } from '@objectifthunes/limestone-sdk' ;
// With all countries
function SignupPhone () {
const [ phone , setPhone ] = useState ( '' );
return (
< PhoneInput
value = {phone}
onValueChange = {setPhone}
countries = {allCountries}
defaultCountry = "FR"
/>
);
}
// With a shortened popular-country list
function QuickPhone () {
return (
< PhoneInput
onValueChange = {setPhone}
countries = {popularCountries}
/>
);
}
Tip
popularCountries is a curated short list of commonly-used countries. Use it when you want a faster-scrolling picker without the full 200+ country list.
SegmentedControl
A horizontal tab-style selector for mutually exclusive options.
Prop Type Default Description segmentsSegment[]— Array of { label, value, disabled? } valuestring— Currently selected value onValueChange(v: string) => void— Change handler size?'xs' | 'sm' | 'md' | 'lg' | 'xl''md'Control height
import { SegmentedControl } from '@objectifthunes/limestone-sdk' ;
import type { Segment } from '@objectifthunes/limestone-sdk' ;
const VIEW_SEGMENTS : Segment [] = [
{ label: 'List' , value: 'list' },
{ label: 'Grid' , value: 'grid' },
{ label: 'Map' , value: 'map' },
];
function ViewToggle () {
const [ view , setView ] = useState ( 'list' );
return (
< SegmentedControl
segments = {VIEW_SEGMENTS}
value = {view}
onValueChange = {setView}
/>
);
}
DatePicker
A date, time, or datetime picker that opens a native OS picker modal.
Prop Type Default Description value?Date— Controlled date value onValueChange?(d: Date) => void— Change handler mode?'date' | 'time' | 'datetime''date'Picker mode minimumDate?Date— Earliest selectable date maximumDate?Date— Latest selectable date displayFormat?string— Format string for the trigger button label size?'xs' | 'sm' | 'md' | 'lg' | 'xl''md'Trigger button size variant?'outline' | 'filled' | 'underline''outline'Trigger button variant
import { DatePicker } from '@objectifthunes/limestone-sdk' ;
function EventScheduler () {
const [ date , setDate ] = useState < Date >( new Date ());
return (
< DatePicker
value = {date}
onValueChange = {setDate}
mode = "datetime"
minimumDate = {new Date ()}
displayFormat = "MMM d, yyyy h:mm a"
/>
);
}
Chip
A compact, pressable label used for filters, tags, and selections. Renders with an active/inactive state and an optional dismiss button.
Prop Type Default Description labelstring— Chip text selected?booleanfalseWhether the chip is in the active state onPress?() => void— Called when the chip is tapped onDismiss?() => void— When provided, a dismiss × button is rendered icon?string— Icon name rendered to the left of the label size?'xs' | 'sm' | 'md' | 'lg' | 'xl''sm'Chip height and font size variant?'default' | 'primary' | 'secondary''default'Color scheme disabled?booleanfalseDisables interaction accessibilityLabel?string— Accessibility label testID?string— Test identifier
import { Chip, Stack } from '@objectifthunes/limestone-sdk' ;
import { useState } from 'react' ;
const CATEGORIES = [ 'Design' , 'Engineering' , 'Marketing' , 'Sales' ];
function CategoryFilter () {
const [ selected , setSelected ] = useState < string []>([]);
const toggle = ( cat : string ) =>
setSelected (( prev ) =>
prev. includes (cat) ? prev. filter (( c ) => c !== cat) : [ ... prev, cat],
);
return (
< Stack direction = "horizontal" gap = "sm" wrap >
{ CATEGORIES . map (( cat ) => (
< Chip
key = {cat}
label = {cat}
selected = {selected.includes(cat)}
onPress = {() => toggle ( cat )}
/>
))}
</ Stack >
);
}
A text field that converts each confirmed entry into an inline Chip. Supports keyboard submission and backspace-to-delete.
Prop Type Default Description valuesstring[]— Controlled array of chip values onValuesChange(v: string[]) => void— Called when a chip is added or removed placeholder?string— Input placeholder shown when no chips are present maxValues?number— Maximum number of chips allowed validate?(v: string) => boolean— Return false to reject an entry size?'xs' | 'sm' | 'md' | 'lg' | 'xl''md'Field height variant?'outline' | 'filled' | 'underline''outline'Visual style accessibilityLabel?string— Accessibility label testID?string— Test identifier
import { ChipInput } from '@objectifthunes/limestone-sdk' ;
import { useState } from 'react' ;
function TagsField () {
const [ tags , setTags ] = useState < string []>([]);
return (
< ChipInput
values = {tags}
onValuesChange = {setTags}
placeholder = "Add a tag…"
maxValues = { 10 }
validate = {(v) => v.length >= 2 }
/>
);
}
QuantityPicker
A numeric stepper with decrement and increment buttons. Enforces min/max bounds and supports a custom step.
Prop Type Default Description valuenumber— Controlled value onValueChange(v: number) => void— Change handler min?number0Minimum allowed value max?number— Maximum allowed value step?number1Increment/decrement step size?'xs' | 'sm' | 'md' | 'lg' | 'xl''md'Control height disabled?booleanfalseDisables both buttons formatValue?(v: number) => string— Custom display formatter accessibilityLabel?string— Accessibility label testID?string— Test identifier
import { QuantityPicker } from '@objectifthunes/limestone-sdk' ;
import { useState } from 'react' ;
function CartItem ({ productId } : { productId : string }) {
const [ qty , setQty ] = useState ( 1 );
return (
< QuantityPicker
value = {qty}
onValueChange = {setQty}
min = { 1 }
max = { 99 }
/>
);
}
Autocomplete
A text input with a dropdown list of suggestions that filter as the user types. Supports free-text entry (combo-box mode) or constrained selection.
Prop Type Default Description optionsSelectOption[]— Full list of { label, value } options value?string— Controlled selected value onValueChange?(v: string) => void— Called when the user picks a suggestion inputValue?string— Controlled text input value (unfiltered) onInputChange?(v: string) => void— Called on every keystroke placeholder?string— Input placeholder maxSuggestions?number5Maximum rows shown in the dropdown freeInput?booleanfalseAllow values not in options size?'xs' | 'sm' | 'md' | 'lg' | 'xl''md'Input size variant?'outline' | 'filled' | 'underline''outline'Input variant accessibilityLabel?string— Accessibility label testID?string— Test identifier
import { Autocomplete } from '@objectifthunes/limestone-sdk' ;
import type { SelectOption } from '@objectifthunes/limestone-sdk' ;
import { useState } from 'react' ;
const CITIES : SelectOption [] = [
{ label: 'Paris' , value: 'CDG' },
{ label: 'New York' , value: 'JFK' },
{ label: 'Tokyo' , value: 'NRT' },
{ label: 'London' , value: 'LHR' },
];
function CityPicker () {
const [ city , setCity ] = useState ( '' );
return (
< Autocomplete
options = {CITIES}
value = {city}
onValueChange = {setCity}
placeholder = "Search cities…"
maxSuggestions = { 4 }
/>
);
}
Calendar
A full-month calendar grid for date selection, date-range selection, and event display. Supports single and range modes with optional event dot indicators.
Prop Type Default Description value?Date— Selected date (single mode) startDate?Date— Range start date (range mode) endDate?Date— Range end date (range mode) mode?'single' | 'range' | 'multiple''single'Selection mode selectedDates?Date[]— Selected dates (multiple mode) onValueChange?(date: Date) => void— Called on date tap (single mode) onRangeChange?(start: Date, end: Date | null) => void— Called on date tap (range mode) onDatesChange?(dates: Date[]) => void— Called on date tap (multiple mode) events?CalendarEvent[]— Array of { date: Date; color?: ColorProp } dot markers minimumDate?Date— Earliest selectable date maximumDate?Date— Latest selectable date disabledDates?Date[]— Dates that cannot be selected firstDayOfWeek?0 | 100 = Sunday, 1 = MondayshowWeekNumbers?booleanfalseRender ISO week numbers in the left gutter size?'sm' | 'md' | 'lg''md'Cell size accessibilityLabel?string— Accessibility label testID?string— Test identifier
import { Calendar } from '@objectifthunes/limestone-sdk' ;
import { useState } from 'react' ;
// Single date picker
function AppointmentPicker () {
const [ date , setDate ] = useState < Date >( new Date ());
return (
< Calendar
value = {date}
onValueChange = {setDate}
minimumDate = {new Date ()}
/>
);
}
// Date range picker
function StayDates () {
const [ start , setStart ] = useState < Date | null >( null );
const [ end , setEnd ] = useState < Date | null >( null );
return (
< Calendar
mode = "range"
startDate = {start ?? undefined}
endDate = {end ?? undefined}
onRangeChange = {(s, e) => { setStart (s); setEnd (e); }}
/>
);
}
// Calendar with event dots
const myEvents = [
{ date: new Date ( 2026 , 3 , 5 ), color: 'primary' },
{ date: new Date ( 2026 , 3 , 12 ), color: 'success' },
];
< Calendar
value = {selectedDate}
onValueChange = {setSelectedDate}
events = {myEvents}
firstDayOfWeek = { 1 }
/>
SignaturePad
A freehand signature capture canvas. The user draws with their finger; the result can be exported as a base64 PNG or SVG path string.
Prop Type Default Description onSave(data: SignatureData) => void— Called when the user taps the save/confirm button; receives { png: string; svg: string } onClear?() => void— Called when the pad is cleared strokeColor?string'#000000'Ink stroke color strokeWidth?number2.5Ink stroke width in pixels backgroundColor?string'#ffffff'Canvas background color height?number200Canvas height in pixels placeholder?string'Sign here'Placeholder text shown on an empty canvas showClearButton?booleantrueRender a clear button below the canvas showSaveButton?booleantrueRender a save/confirm button below the canvas clearLabel?string'Clear'Label for the clear button saveLabel?string'Confirm'Label for the save button accessibilityLabel?string— Accessibility label testID?string— Test identifier
import { SignaturePad } from '@objectifthunes/limestone-sdk' ;
import type { SignatureData } from '@objectifthunes/limestone-sdk' ;
function ConsentForm ({ onSigned } : { onSigned : ( png : string ) => void }) {
return (
< SignaturePad
strokeColor = "#1a1a2e"
strokeWidth = { 3 }
height = { 180 }
placeholder = "Draw your signature"
onSave = {({ png }) => onSigned ( png )}
/>
);
}
Tip
SignaturePad requires react-native-svg for SVG export support. The PNG export works without any additional dependencies.