Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .cursor/rules/testing-guidelines.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ alwaysApply: true
```typescript
import React from 'react'
import {render, fireEvent} from '@testing-library/react-native'
import {Button} from '../components/Button'
import {ButtonPrimary} from '../components/Button'
import {BaseProvider} from '../core/BaseProvider'

const renderWithProvider = (component: React.ReactElement) => {
Expand Down Expand Up @@ -55,9 +55,9 @@ describe('Button Component', () => {

it('applies correct styles for variants', () => {
const {getByTestId} = renderWithProvider(
<Button variant="primary" testID="primary-button">Primary</Button>
<ButtonPrimary testID="primary-button">Primary</ButtonPrimary>
)

const button = getByTestId('primary-button')
// Test styling expectations
})
Expand Down
34 changes: 23 additions & 11 deletions example/app/_layout.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,26 @@
import { Stack } from 'expo-router'
import { ScreenProps, Stack } from 'expo-router'
import { StatusBar } from 'expo-status-bar'
import 'react-native-reanimated'

import React from 'react'
import { BaseProvider } from 'rn-base-component'

const baseHeaderOptions: ScreenProps['options']
= {
headerShown: true,
headerBackTitle: 'Back',
headerStyle: {
backgroundColor: '#f8f9fa',
},
headerTintColor: '#1a1a1a',
headerTitleStyle: {
fontWeight: 'bold',
fontSize: 18,
},
}

export default function RootLayout() {

return (
<BaseProvider>
<Stack>
Expand All @@ -20,16 +34,14 @@ export default function RootLayout() {
name="code-input"
options={{
title: 'CodeInput Component',
headerShown: true,
headerBackTitle: 'Back',
headerStyle: {
backgroundColor: '#f8f9fa',
},
headerTintColor: '#1a1a1a',
headerTitleStyle: {
fontWeight: 'bold',
fontSize: 18,
},
...baseHeaderOptions,
}}
/>
<Stack.Screen
name="text-input"
options={{
title: 'TextInput Component',
...baseHeaderOptions,
}}
/>
</Stack>
Expand Down
8 changes: 8 additions & 0 deletions example/app/text-input.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import React from 'react'
import { TextInputDemo } from '@/components/TextInputDemo'

const TextInputDemoScreen = () => {
return <TextInputDemo />
}

export default TextInputDemoScreen
60 changes: 60 additions & 0 deletions example/components/TextInputDemo/BasicExamples.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import React, { useState } from 'react'
import { Text, View } from 'react-native'
import { TextInput } from 'rn-base-component'
import { demoStyles } from './styles'

export const BasicExamples = () => {
const [name, setName] = useState('')
const [email, setEmail] = useState('')
const [phone, setPhone] = useState('')

return (
<View style={demoStyles.section}>
<Text style={demoStyles.sectionTitle}>📝 Basic Examples</Text>

<View style={demoStyles.example}>
<Text style={demoStyles.exampleTitle}>Default TextInput</Text>
<TextInput
label="Full Name"
placeholder="Enter your full name"
value={name}
onChangeText={setName}
/>
</View>

<View style={demoStyles.example}>
<Text style={demoStyles.exampleTitle}>Required Field with Label</Text>
<TextInput
label="Email Address"
placeholder="Enter your email"
value={email}
onChangeText={setEmail}
isRequire
keyboardType="email-address"
autoCapitalize="none"
/>
</View>

<View style={demoStyles.example}>
<Text style={demoStyles.exampleTitle}>With Placeholder and Keyboard Type</Text>
<TextInput
label="Phone Number"
placeholder="(123) 456-7890"
value={phone}
onChangeText={setPhone}
keyboardType="phone-pad"
/>
</View>

<View style={demoStyles.example}>
<Text style={demoStyles.exampleTitle}>Password Input</Text>
<TextInput
label="Password"
placeholder="Enter your password"
secureTextEntry
isRequire
/>
</View>
</View>
)
}
106 changes: 106 additions & 0 deletions example/components/TextInputDemo/DisabledState.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import React from 'react'
import { Text, View } from 'react-native'
import { TextInput } from 'rn-base-component'
import { demoStyles } from './styles'

export const DisabledState = () => {
return (
<View style={demoStyles.section}>
<Text style={demoStyles.sectionTitle}>🚫 Disabled States</Text>
<Text style={demoStyles.sectionDescription}>
TextInput in disabled state for read-only scenarios
</Text>

<View style={demoStyles.example}>
<Text style={demoStyles.exampleTitle}>Disabled Default Input</Text>
<TextInput
label="Disabled Field"
placeholder="This input is disabled"
editable={false}
value="This field is read-only"
/>
</View>

<View style={demoStyles.example}>
<Text style={demoStyles.exampleTitle}>Disabled Outlined Input</Text>
<TextInput.Outlined
label="Read-only Email"
placeholder="user@example.com"
editable={false}
value="user@example.com"
/>
</View>

<View style={demoStyles.example}>
<Text style={demoStyles.exampleTitle}>Disabled Flat Input</Text>
<TextInput.Flat
label="Read-only Name"
placeholder="John Doe"
editable={false}
value="John Doe"
/>
</View>

<View style={demoStyles.example}>
<Text style={demoStyles.exampleTitle}>Disabled with Required Indicator</Text>
<TextInput
label="Required but Disabled"
placeholder="This is required but disabled"
isRequire
editable={false}
value="Pre-filled value"
/>
</View>

<View style={demoStyles.example}>
<Text style={demoStyles.exampleTitle}>Disabled with Icons</Text>
<TextInput
label="Contact Info"
placeholder="Contact information"
editable={false}
value="+1 (555) 123-4567"
leftComponent={
<View style={{ paddingHorizontal: 8 }}>
<Text style={{ fontSize: 16 }}>📞</Text>
</View>
}
rightComponent={
<View style={{ paddingHorizontal: 8 }}>
<Text style={{ fontSize: 16 }}>✅</Text>
</View>
}
/>
</View>

<View style={demoStyles.example}>
<Text style={demoStyles.exampleTitle}>Disabled Multiline Input</Text>
<TextInput
label="Read-only Description"
placeholder="Description"
editable={false}
multiline
numberOfLines={3}
value="This is a multi-line read-only text field that contains some example content to demonstrate how disabled multiline inputs appear in the interface."
/>
</View>

<View style={demoStyles.example}>
<Text style={demoStyles.exampleTitle}>Comparison: Enabled vs Disabled</Text>
<View style={{ gap: 12 }}>
<TextInput
label="Enabled Input"
placeholder="You can type here"
value=""
/>

<TextInput
label="Disabled Input"
placeholder="You cannot type here"
editable={false}
value="Disabled content"
/>
</View>
</View>
</View>
)
}
133 changes: 133 additions & 0 deletions example/components/TextInputDemo/IconsAndComponents.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import React, { useState } from 'react'
import { Text, TouchableOpacity, View } from 'react-native'
import { TextInput } from 'rn-base-component'
import { demoStyles } from './styles'

export const IconsAndComponents = () => {
const [searchText, setSearchText] = useState('')
const [phoneNumber, setPhoneNumber] = useState('')
const [isPasswordVisible, setIsPasswordVisible] = useState(false)

const SearchIcon = () => (
<View style={{ paddingHorizontal: 8 }}>
<Text style={{ fontSize: 16 }}>🔍</Text>
</View>
)

const PhoneIcon = () => (
<View style={{ paddingHorizontal: 8 }}>
<Text style={{ fontSize: 16 }}>📞</Text>
</View>
)

const EyeIcon = ({ visible }: { visible: boolean }) => (
<TouchableOpacity
onPress={() => setIsPasswordVisible(!visible)}
style={{ paddingHorizontal: 8 }}
>
<Text style={{ fontSize: 16 }}>{visible ? '👁️' : '🙈'}</Text>
</TouchableOpacity>
)

const ClearButton = ({ onClear }: { onClear: () => void }) => (
<TouchableOpacity onPress={onClear} style={{ paddingHorizontal: 8 }}>
<Text style={{ fontSize: 16 }}>❌</Text>
</TouchableOpacity>
)

const UnitLabel = ({ unit }: { unit: string }) => (
<View style={{ paddingHorizontal: 8, backgroundColor: '#f0f0f0', borderRadius: 4, paddingVertical: 2 }}>
<Text style={{ fontSize: 12, color: '#666' }}>{unit}</Text>
</View>
)

return (
<View style={demoStyles.section}>
<Text style={demoStyles.sectionTitle}>🎨 Icons and Components</Text>
<Text style={demoStyles.sectionDescription}>
TextInput with left and right components for enhanced UX
</Text>

<View style={demoStyles.example}>
<Text style={demoStyles.exampleTitle}>Search Input with Icon</Text>
<TextInput
label="Search"
placeholder="Search for something..."
value={searchText}
onChangeText={setSearchText}
leftComponent={<SearchIcon />}
rightComponent={
searchText ? <ClearButton onClear={() => setSearchText('')} /> : undefined
}
/>
</View>

<View style={demoStyles.example}>
<Text style={demoStyles.exampleTitle}>Phone Number Input</Text>
<TextInput
label="Phone Number"
placeholder="(123) 456-7890"
value={phoneNumber}
onChangeText={setPhoneNumber}
keyboardType="phone-pad"
leftComponent={<PhoneIcon />}
/>
</View>

<View style={demoStyles.example}>
<Text style={demoStyles.exampleTitle}>Password with Visibility Toggle</Text>
<TextInput
label="Password"
placeholder="Enter your password"
secureTextEntry={!isPasswordVisible}
rightComponent={<EyeIcon visible={isPasswordVisible} />}
/>
</View>

<View style={demoStyles.example}>
<Text style={demoStyles.exampleTitle}>Weight Input with Unit</Text>
<TextInput
label="Weight"
placeholder="Enter weight"
keyboardType="numeric"
rightComponent={<UnitLabel unit="kg" />}
/>
</View>

<View style={demoStyles.example}>
<Text style={demoStyles.exampleTitle}>Price Input with Currency</Text>
<TextInput
label="Price"
placeholder="0.00"
keyboardType="numeric"
leftComponent={<UnitLabel unit="$" />}
/>
</View>

<View style={demoStyles.example}>
<Text style={demoStyles.exampleTitle}>Complex Example - Email with Actions</Text>
<TextInput
label="Email Address"
placeholder="your@email.com"
keyboardType="email-address"
autoCapitalize="none"
leftComponent={
<View style={{ paddingHorizontal: 8 }}>
<Text style={{ fontSize: 16 }}>✉️</Text>
</View>
}
rightComponent={
<View style={{ flexDirection: 'row' }}>
<TouchableOpacity style={{ paddingHorizontal: 8 }}>
<Text style={{ fontSize: 16 }}>📎</Text>
</TouchableOpacity>
<TouchableOpacity style={{ paddingHorizontal: 8 }}>
<Text style={{ fontSize: 16 }}>⚙️</Text>
</TouchableOpacity>
</View>
}
/>
</View>
</View>
)
}
Loading
Loading