npm package: @shiplypalestine/ui
Description: A comprehensive React Native UI component library with a modern design system.
Latest version: 1.2.21

# Shiply UI Library

A comprehensive React Native UI component library with a modern design system.

## Features

- 🎨 Theme support (Light/Dark mode)
- 🌐 RTL (Right-to-Left) support
- 📱 Cross-platform (iOS, Android, Web)
- 🎯 TypeScript support
- 🎨 NativeWind for styling
- 🔧 Customizable components

## Installation

```bash
npm install @shiplypalestine/ui
# or
yarn add @shiplypalestine/ui
```

### Required Setup

1. Install peer dependencies:
```bash
npm install nativewind@^2.0.11 tailwindcss@^3.3.2 postcss@^8.4.23 autoprefixer@^10.4.14 @react-native-async-storage/async-storage
# or
yarn add nativewind@^2.0.11 tailwindcss@^3.3.2 postcss@^8.4.23 autoprefixer@^10.4.14 @react-native-async-storage/async-storage
```

2. For React Native CLI projects, run:
```bash
npx pod-install ios
```

3. For Expo projects, run:
```bash
npx expo prebuild
```

4. Configure your `tailwind.config.js`:
```javascript
module.exports = {
  content: [
    "./App.{js,jsx,ts,tsx}",
    "./src/**/*.{js,jsx,ts,tsx}",
    "./node_modules/@shiplypalestine/ui/**/*.{js,jsx,ts,tsx}"
  ],
  theme: {
    extend: {
      colors: {
        primary: {
          DEFAULT: '#007AFF',
          dark: '#0056B3',
        },
        secondary: {
          DEFAULT: '#5856D6',
          dark: '#3634A3',
        },
        accent: {
          DEFAULT: '#FF2D55',
          dark: '#D6002F',
        },
        background: {
          light: '#FFFFFF',
          dark: '#121212',
        },
        text: {
          light: '#000000',
          dark: '#FFFFFF',
        },
      },
    },
  },
  plugins: [],
}
```

5. Add the following to your `babel.config.js`:
```javascript
module.exports = {
  plugins: ["nativewind/babel"],
};
```

## Usage

### Theme Provider

Wrap your app with the ThemeProvider to enable theming and RTL support:

```tsx
import { ThemeProvider } from '@shiplypalestine/ui';
import { SafeAreaProvider } from 'react-native-safe-area-context';

export default function App() {
  return (
    <SafeAreaProvider>
      <ThemeProvider>
        {/* Your app content */}
      </ThemeProvider>
    </SafeAreaProvider>
  );
}
```

**Note on Safe Area:**

Components like `Toast` use `SafeAreaView` internally to avoid rendering under device notches or home indicators. For `SafeAreaView` to work correctly, your entire application must be wrapped with a single `<SafeAreaProvider>` at its root. Make sure you have `react-native-safe-area-context` installed and configured as shown in the example above.

## Hooks

### useDisclose

A utility hook for managing open/close state of components like modals, action sheets, and dropdowns.

```tsx
import { useDisclose } from '@shiplypalestine/ui';

export function MyComponent() {
  const { isOpen, onOpen, onClose, onToggle } = useDisclose();

  return (
    <View>
      <Button title="Open Modal" onPress={onOpen} />
      
      <Modal visible={isOpen} onClose={onClose}>
        <Text>Modal content</Text>
        <Button title="Close" onPress={onClose} />
      </Modal>
    </View>
  );
}
```

**Hook API:**
- `isOpen: boolean` - Current open/close state
- `onOpen: () => void` - Function to open
- `onClose: () => void` - Function to close  
- `onToggle: () => void` - Function to toggle state

**Initial State:**
```tsx
// Start with closed state (default)
const { isOpen, onOpen, onClose } = useDisclose();

// Start with open state
const { isOpen, onOpen, onClose } = useDisclose(true);
```

### Components

Import and use components as needed:

```tsx
import { Button, Input, Card, Modal, Select } from '@shiplypalestine/ui';

export function MyComponent() {
  const [isModalVisible, setIsModalVisible] = useState(false);
  const [inputValue, setInputValue] = useState('');
  const [selectedOption, setSelectedOption] = useState('');

  return (
    <View style={{ padding: 16 }}>
      {/* Button Component */}
      <Button 
        title="Click Me" 
        onPress={() => setIsModalVisible(true)} 
        variant="primary"
        size="medium"
      />
      
      {/* Input Component */}
      <Input
        value={inputValue}
        onChangeText={setInputValue}
        placeholder="Enter text..."
        label="Example Input"
      />
      
      {/* Card Component */}
      <Card title="Example Card">
        <Text>This is a card component</Text>
      </Card>
      
      {/* Select Component */}
      <Select
        options={[
          { label: 'Option 1', value: '1' },
          { label: 'Option 2', value: '2' },
          { label: 'Option 3', value: '3' },
        ]}
        onSelect={(value) => setSelectedOption(value)}
        placeholder="Select an option"
      />
      
      {/* Modal Component */}
      <Modal
        visible={isModalVisible}
        onClose={() => setIsModalVisible(false)}
        title="Example Modal"
      >
        <Text>This is a modal component</Text>
        <Button 
          title="Close" 
          onPress={() => setIsModalVisible(false)} 
          variant="secondary"
        />
      </Modal>
    </View>
  );
}
```

## Style Customization

All components support both NativeWind classes and StyleSheet props for customization. This allows you to override default styles using either approach:

### Using StyleSheet Props

```tsx
import { Button } from '@shiplypalestine/ui';
import { StyleSheet } from 'react-native';

export function MyComponent() {
  return (
    <Button 
      title="Custom Button" 
      onPress={() => {}} 
      style={styles.button}
      textStyle={styles.buttonText}
    />
  );
}

const styles = StyleSheet.create({
  button: {
    backgroundColor: 'purple',
    borderRadius: 20,
  },
  buttonText: {
    fontSize: 18,
    fontWeight: 'bold',
  },
});
```

### Using NativeWind Classes

```tsx
import { Button } from '@shiplypalestine/ui';

export function MyComponent() {
  return (
    <Button 
      title="Custom Button" 
      onPress={() => {}} 
      className="bg-purple-500 rounded-full"
      textClassName="text-lg font-bold"
    />
  );
}
```

## Available Components

### Button

A customizable button component with multiple variants, states, and icon support.

Props:
- `title`: string (required)
- `onPress`: () => void (required)
- `variant`: 'primary' | 'secondary' | 'outline' (optional)
- `size`: 'small' | 'medium' | 'large' (optional)
- `disabled`: boolean (optional)
- `loading`: boolean (optional)
- `startIcon`: React.ReactNode (optional) - Icon to display before text
- `endIcon`: React.ReactNode (optional) - Icon to display after text
- `iconSpacing`: number (optional) - Space between icon and text (default: 8)
- `style`: ViewStyle (optional)
- `textStyle`: TextStyle (optional)
- `className`: string (optional)
- `textClassName`: string (optional)

Example usage:

```tsx
import { Button } from '@shiplypalestine/ui';

// Basic usage
<Button title="Click Me" onPress={() => {}} />

// With icons
<Button 
  title="Next" 
  onPress={() => {}} 
  endIcon={<MyIcon name="arrow-right" />}
/>

<Button 
  title="Back" 
  onPress={() => {}} 
  startIcon={<MyIcon name="arrow-left" />}
/>

// With custom icon spacing
<Button 
  title="Download" 
  onPress={() => {}} 
  startIcon={<MyIcon name="download" />}
  iconSpacing={12}
/>
```

### Input

A customizable input component with label and error support.

Props:
- `label`: string (optional)
- `error`: string (optional)
- `disabled`: boolean (optional)
- `multiline`: boolean (optional)
- `containerStyle`: ViewStyle (optional)
- `inputStyle`: TextStyle (optional)
- `labelStyle`: TextStyle (optional)
- `errorStyle`: TextStyle (optional)
- `containerClassName`: string (optional)
- `inputClassName`: string (optional)
- `labelClassName`: string (optional)
- `errorClassName`: string (optional)
- `startComponent`: ReactNode (optional) - Component to display at the start of the input
- `startComponentContainerStyle`: ViewStyle (optional) - Style for the startComponent container
- `startComponentContainerClassName`: string (optional) - Classes for the startComponent container
- `forceRTL`: boolean (optional) - Force right-to-left text direction
- `forceLTR`: boolean (optional) - Force left-to-right text direction
- All other TextInput props are supported

Example usage:

```tsx
import { Input } from '@shiplypalestine/ui';

// Basic usage
<Input placeholder="Enter text" />

// With label and error
<Input 
  label="Email"
  error="Invalid email"
  placeholder="Enter your email"
/>

// With start component (icon or other element)
<Input
  label="Search"
  placeholder="Search..."
  startComponent={<SearchIcon size={20} color="#007AFF" />}
/>

// With start component in RTL mode
<Input
  label="بحث"
  placeholder="أدخل كلمة البحث..."
  forceRTL={true}
  startComponent={<SearchIcon size={20} color="#007AFF" />}
/>

// With custom styles
<Input
  placeholder="Custom input"
  containerStyle={{ marginBottom: 20 }}
  inputStyle={{ fontSize: 16 }}
  labelStyle={{ color: 'blue' }}
  containerClassName="bg-gray-100"
  inputClassName="border-2"
/>

// With styled start component
<Input
  label="Username"
  placeholder="Enter username"
  startComponent={
    <Text style={{ color: '#5856D6', fontWeight: 'bold' }}>@</Text>
  }
  startComponentContainerClassName="bg-gray-100 h-full rounded-l-lg border-r"
/>

// Disabled input
<Input
  placeholder="Disabled input"
  disabled
/>

// Multiline input
<Input
  placeholder="Enter multiple lines"
  multiline
/>
```

### TextArea

A multi-line text input component with advanced features like auto-growing, character counting, and customizable styling. Extends TextInput functionality with TextArea-specific props.

```tsx
import { TextArea } from '@shiplypalestine/ui';

// Basic usage
<TextArea
  value={value}
  onChangeText={setValue}
  placeholder="Enter your message here..."
  label="Message"
/>

// With auto-growing
<TextArea
  value={value}
  onChangeText={setValue}
  placeholder="This will grow as you type..."
  label="Auto-growing Message"
  autoGrow={true}
  minRows={3}
  maxRows={8}
/>

// With character count
<TextArea
  value={value}
  onChangeText={setValue}
  placeholder="Type something (max 200 characters)..."
  label="Limited Message"
  maxLength={200}
  showCharacterCount={true}
  rows={4}
/>

// With error state
<TextArea
  value={value}
  onChangeText={setValue}
  placeholder="Enter your message..."
  label="Message"
  error="This field is required"
/>

// With start component
<TextArea
  value={value}
  onChangeText={setValue}
  placeholder="Enter your message..."
  label="Message with Icon"
  startComponent={<Text style={{ color: 'blue' }}>📝</Text>}
/>

// RTL support
<TextArea
  value={value}
  onChangeText={setValue}
  placeholder="اكتب رسالتك هنا..."
  label="رسالة"
  forceRTL={true}
  rows={3}
/>

// Custom styling
<TextArea
  value={value}
  onChangeText={setValue}
  placeholder="Custom styled textarea..."
  label="Custom Style"
  containerStyle={{ backgroundColor: '#F9FAFB', padding: 16, borderRadius: 12 }}
  inputStyle={{ fontSize: 18, fontStyle: 'italic' }}
  labelStyle={{ color: 'blue', fontWeight: 'bold' }}
  rows={5}
/>
```

#### Props

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `value` | `string` | `''` | The current value of the textarea |
| `onChangeText` | `(text: string) => void` | - | Callback when text changes |
| `placeholder` | `string` | - | Placeholder text |
| `label` | `string` | - | Label text displayed above the textarea |
| `error` | `string` | - | Error message to display |
| `disabled` | `boolean` | `false` | Whether the textarea is disabled |
| `rows` | `number` | `4` | Number of visible rows |
| `maxRows` | `number` | `10` | Maximum number of rows when auto-growing |
| `minRows` | `number` | `2` | Minimum number of rows when auto-growing |
| `autoGrow` | `boolean` | `false` | Whether the textarea should grow with content |
| `showCharacterCount` | `boolean` | `false` | Whether to show character count |
| `maxLength` | `number` | - | Maximum number of characters allowed |
| `resize` | `'none' \| 'vertical' \| 'horizontal' \| 'both'` | `'vertical'` | Resize behavior (web only) |
| `forceRTL` | `boolean` | `false` | Force right-to-left text direction |
| `forceLTR` | `boolean` | `false` | Force left-to-right text direction |

#### Style Props

| Prop | Type | Description |
|------|------|-------------|
| `style` | `ViewStyle` | Custom style for the container |
| `className` | `string` | NativeWind classes for the container |
| `containerStyle` | `ViewStyle` | Custom style for the main container |
| `containerClassName` | `string` | NativeWind classes for the main container |
| `inputStyle` | `TextStyle` | Custom style for the text input |
| `inputClassName` | `string` | NativeWind classes for the text input |
| `labelStyle` | `TextStyle` | Custom style for the label |
| `labelClassName` | `string` | NativeWind classes for the label |
| `errorStyle` | `TextStyle` | Custom style for the error message |
| `errorClassName` | `string` | NativeWind classes for the error message |
| `characterCountStyle` | `TextStyle` | Custom style for the character count |
| `characterCountClassName` | `string` | NativeWind classes for the character count |

#### Start/End Component Props

| Prop | Type | Description |
|------|------|-------------|
| `startComponent` | `React.ReactNode` | Component to display at the start of the textarea |
| `startComponentContainerStyle` | `ViewStyle` | Style for the start component container |
| `startComponentContainerClassName` | `string` | Classes for the start component container |
| `endComponent` | `React.ReactNode` | Component to display at the end of the textarea |
| `endComponentContainerStyle` | `ViewStyle` | Style for the end component container |
| `endComponentContainerClassName` | `string` | Classes for the end component container |

#### Features

- **Multi-line Support**: Built-in multiline text input
- **Auto-growing**: Automatically resize based on content
- **Character Counting**: Display character count with max length
- **RTL Support**: Right-to-left text direction support
- **Start/End Components**: Add icons or other components
- **Custom Styling**: Full style customization support
- **Error Handling**: Built-in error state and messaging
- **Accessibility**: Proper accessibility support
- **Cross-platform**: Works on web, iOS, and Android

### Card

A customizable card component with title and content.

Props:
- `title`: string (optional)
- `children`: React.ReactNode (required)
- `variant`: 'elevated' | 'outlined' | 'filled' (optional)
- `padding`: 'none' | 'small' | 'medium' | 'large' (optional)
- `onPress`: () => void (optional)
- `style`: ViewStyle (optional)
- `titleStyle`: TextStyle (optional)
- `className`: string (optional)
- `titleClassName`: string (optional)

### Modal

A customizable modal component with title and close button.

Props:
- `visible`: boolean (required)
- `onClose`: () => void (required)
- `title`: string (optional)
- `children`: React.ReactNode (required)
- `showCloseButton`: boolean (optional)
- `animationType`: 'fade' | 'slide' (optional)
- `containerStyle`: ViewStyle (optional)
- `contentStyle`: ViewStyle (optional)
- `titleStyle`: TextStyle (optional)
- `closeButtonStyle`: ViewStyle (optional)
- `closeButtonTextStyle`: TextStyle (optional)
- `containerClassName`: string (optional)
- `contentClassName`: string (optional)
- `titleClassName`: string (optional)
- `closeButtonClassName`: string (optional)
- `closeButtonTextClassName`: string (optional)

### Select

A customizable select component with dropdown options.

Props:
- `options`: Array<{ label: string, value: string }> (required)
- `onSelect`: (value: string) => void (required)
- `placeholder`: string (optional)
- `disabled`: boolean (optional)
- `value`: string (optional) - Initial selected value
- `containerStyle`: ViewStyle (optional)
- `triggerStyle`: ViewStyle (optional)
- `triggerTextStyle`: TextStyle (optional)
- `dropdownStyle`: ViewStyle (optional)
- `optionStyle`: ViewStyle (optional)
- `optionTextStyle`: TextStyle (optional)
- `containerClassName`: string (optional)
- `triggerClassName`: string (optional)
- `triggerTextClassName`: string (optional)
- `dropdownClassName`: string (optional)
- `optionClassName`: string (optional)
- `optionTextClassName`: string (optional)

### Radio & RadioGroup

Customizable radio components with group support.

Props for Radio:
- `value`: string (required)
- `label`: string (required)
- `selected`: boolean (required)
- `onSelect`: (value: string) => void (required)
- `disabled`: boolean (optional)
- `containerStyle`: ViewStyle (optional)
- `radioStyle`: ViewStyle (optional)
- `labelStyle`: TextStyle (optional)
- `containerClassName`: string (optional)
- `radioClassName`: string (optional)
- `labelClassName`: string (optional)

Props for RadioGroup:
- `value`: string (required)
- `onChange`: (value: string) => void (required)
- `children`: React.ReactNode (required)
- `containerStyle`: ViewStyle (optional)
- `containerClassName`: string (optional)

### Checkbox & CheckboxGroup

Customizable checkbox components with group support.

Props for Checkbox:
- `value`: string (required)
- `label`: string (required)
- `checked`: boolean (required)
- `onCheck`: (values: string[]) => void (required)
- `disabled`: boolean (optional)
- `containerStyle`: ViewStyle (optional)
- `checkboxStyle`: ViewStyle (optional)
- `labelStyle`: TextStyle (optional)
- `checkmarkStyle`: TextStyle (optional)
- `containerClassName`: string (optional)
- `checkboxClassName`: string (optional)
- `labelClassName`: string (optional)
- `checkmarkClassName`: string (optional)

Props for CheckboxGroup:
- `value`: string[] (required)
- `onChange`: (values: string[]) => void (required)
- `children`: React.ReactNode (required)
- `containerStyle`: ViewStyle (optional)
- `containerClassName`: string (optional)

### Progress

A customizable progress component.

Props:
- `value`: number (required)
- `max`: number (optional)
- `variant`: 'linear' | 'circular' (optional)
- `color`: 'primary' | 'secondary' | 'accent' (optional)
- `size`: 'small' | 'medium' | 'large' (optional)
- `showValue`: boolean (optional)
- `containerStyle`: ViewStyle (optional)
- `trackStyle`: ViewStyle (optional)
- `progressStyle`: ViewStyle (optional)
- `valueStyle`: TextStyle (optional)
- `containerClassName`: string (optional)
- `trackClassName`: string (optional)
- `progressClassName`: string (optional)
- `valueClassName`: string (optional)

### Spinner

A customizable spinner component.

Props:
- `size`: 'small' | 'medium' | 'large' (optional)
- `color`: 'primary' | 'secondary' | 'accent' | 'white' (optional)
- `fullScreen`: boolean (optional)
- `containerStyle`: ViewStyle (optional)
- `spinnerStyle`: ViewStyle (optional)
- `containerClassName`: string (optional)
- `spinnerClassName`: string (optional)

### Switch

A customizable switch component.

Props:
- `value`: boolean (required)
- `onValueChange`: (value: boolean) => void (required)
- `disabled`: boolean (optional)
- `style`: ViewStyle (optional)
- `className`: string (optional)
- `trackColorFalse`: string (optional)
- `trackColorTrue`: string (optional)
- `thumbColor`: string (optional)

### Toast

A flexible toast notification system that supports multiple usage patterns: context-based, hook-based, and direct function calls.

#### Usage Patterns

1. Using the `useToast` hook (Recommended):
```tsx
import { useToast } from '@shiplypalestine/ui';

function MyComponent() {
  const { showToast } = useToast();

  const handleSuccess = () => {
    showToast({
      message: 'Operation completed successfully!',
      type: 'success',
      duration: 3000,
      position: 'top'
    });
  };

  return (
    <Button 
      title="Show Success Toast" 
      onPress={handleSuccess} 
    />
  );
}
```

2. Using the `ToastProvider`:
```tsx
import { ToastProvider } from '@shiplypalestine/ui';

function App() {
  return (
    <ToastProvider>
      {/* Your app content */}
    </ToastProvider>
  );
}
```

3. Using the direct `showToast` function (Deprecated):
```tsx
import { showToast } from '@shiplypalestine/ui';

function MyComponent() {
  const handleError = () => {
    showToast({
      message: 'An error occurred',
      type: 'error'
    });
  };

  return (
    <Button 
      title="Show Error Toast" 
      onPress={handleError} 
    />
  );
}
```

#### Toast Options

The `showToast` function accepts the following options:

- `message`: string (required) - The message to display
- `type`: 'success' | 'error' | 'info' | 'warning' (optional) - The type of toast
- `duration`: number (optional) - Duration in milliseconds (default: 3000)
- `position`: 'top' | 'bottom' (optional) - Position of the toast (default: 'top')

#### Toast Types

- `success`: Green background, used for successful operations
- `error`: Red background, used for error messages
- `warning`: Yellow background, used for warnings
- `info`: Blue background, used for general information

#### Example Usage

```tsx
import { useToast } from '@shiplypalestine/ui';

function MyComponent() {
  const { showToast } = useToast();

  // Success toast
  const handleSuccess = () => {
    showToast({
      message: 'Data saved successfully!',
      type: 'success'
    });
  };

  // Error toast
  const handleError = () => {
    showToast({
      message: 'Failed to save data',
      type: 'error'
    });
  };

  // Warning toast
  const handleWarning = () => {
    showToast({
      message: 'Please fill all required fields',
      type: 'warning'
    });
  };

  // Info toast
  const handleInfo = () => {
    showToast({
      message: 'New features available',
      type: 'info'
    });
  };

  // Custom duration and position
  const handleCustom = () => {
    showToast({
      message: 'Custom toast',
      type: 'success',
      duration: 5000,
      position: 'bottom'
    });
  };

  return (
    <View>
      <Button title="Success" onPress={handleSuccess} />
      <Button title="Error" onPress={handleError} />
      <Button title="Warning" onPress={handleWarning} />
      <Button title="Info" onPress={handleInfo} />
      <Button title="Custom" onPress={handleCustom} />
    </View>
  );
}
```

### Typography

A flexible text component that automatically handles text wrapping and supports various text styles.

```tsx
import { Typography } from '@shiplypalestine/ui';

// Basic usage with automatic text wrapping
<Typography>
  This text will automatically wrap when it reaches the end of its container.
</Typography>

// Different variants
<Typography variant="body">Body text</Typography>
<Typography variant="subtitle">Subtitle text</Typography>
<Typography variant="caption">Caption text</Typography>
<Typography variant="overline">OVERLINE TEXT</Typography>

// Different weights
<Typography weight="normal">Normal weight</Typography>
<Typography weight="medium">Medium weight</Typography>
<Typography weight="semibold">Semibold weight</Typography>
<Typography weight="bold">Bold weight</Typography>

// Text truncation with ellipsis
<Typography numberOfLines={2}>
  This text will be truncated after 2 lines with an ellipsis.
</Typography>

// Different colors
<Typography color="primary">Primary color</Typography>
<Typography color="secondary">Secondary color</Typography>
<Typography color="accent">Accent color</Typography>
<Typography color="muted">Muted color</Typography>
```

#### Props
- `variant`: 'body' | 'caption' | 'overline' | 'subtitle' (default: 'body')
- `weight`: 'normal' | 'medium' | 'semibold' | 'bold' (default: 'normal')
- `color`: 'primary' | 'secondary' | 'accent' | 'default' | 'muted' | 'white' (default: 'default')
- `align`: 'left' | 'center' | 'right' (default: 'left')
- `numberOfLines`: number - Limits text to specified number of lines with ellipsis
- `ellipsizeMode`: 'head' | 'middle' | 'tail' | 'clip' (default: 'tail')
- `style`: Custom styles for the text
- `className`: NativeWind classes

### Heading

A customizable heading component for titles and section headers.

Props:
- `children`: React.ReactNode (required)
- `level`: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' (optional)
- `color`: 'primary' | 'secondary' | 'accent' | 'default' | 'muted' | 'white' (optional)
- `align`: 'left' | 'center' | 'right' (optional)
- `style`: TextStyle (optional)
- `className`: string (optional)

### Accordion & AccordionItem

Customizable accordion components for expandable content sections.

Props for Accordion:
- `children`: React.ReactNode (required)
- `containerStyle`: ViewStyle (optional)
- `containerClassName`: string (optional)

Props for AccordionItem:
- `title`: string (required)
- `children`: React.ReactNode (required)
- `initiallyExpanded`: boolean (optional)
- `containerStyle`: ViewStyle (optional)
- `headerStyle`: ViewStyle (optional)
- `contentStyle`: ViewStyle (optional)
- `titleStyle`: TextStyle (optional)
- `containerClassName`: string (optional)
- `headerClassName`: string (optional)
- `contentClassName`: string (optional)
- `titleClassName`: string (optional)

### IconButton

A customizable icon button component that accepts any React element as an icon.

Props:
- `icon`: React.ReactNode (required) - Any React element to display as the icon
- `onPress`: () => void (required)
- `size`: 'small' | 'medium' | 'large' (optional)
- `color`: 'primary' | 'secondary' | 'accent' | 'default' | 'muted' | 'white' (optional)
- `variant`: 'solid' | 'outline' | 'ghost' (optional)
- `disabled`: boolean (optional)
- `loading`: boolean (optional)
- `style`: ViewStyle (optional)
- `className`: string (optional)

Example usage:

```tsx
import { IconButton } from '@shiplypalestine/ui';
import { Feather } from '@expo/vector-icons';

// With Expo Icons
<IconButton 
  icon={<Feather name="heart" size={20} color="white" />}
  onPress={() => {}}
  color="primary"
/>

// With custom component
<IconButton 
  icon={<Text style={{ color: 'white', fontSize: 16 }}>⭐</Text>}
  onPress={() => {}}
  color="secondary"
/>

// With SVG icon
<IconButton 
  icon={<MySvgIcon width={20} height={20} color="white" />}
  onPress={() => {}}
  color="accent"
/>

// Different variants
<IconButton 
  icon={<Feather name="bell" size={20} color="white" />}
  onPress={() => {}}
  variant="solid"
  color="primary"
/>

<IconButton 
  icon={<Feather name="bell" size={20} color="#007AFF" />}
  onPress={() => {}}
  variant="outline"
  color="primary"
/>
```

### FlatList & SectionList

Customizable list components with built-in empty state support and performance optimizations for large data sets.

Props for both FlatList and SectionList:
- `containerStyle`: ViewStyle (optional)
- `contentContainerStyle`: ViewStyle (optional)
- `containerClassName`: string (optional)
- `contentContainerClassName`: string (optional)
- `showEmptyState`: boolean (optional) - Default: true
- `emptyStateComponent`: React.ReactElement (optional)

Performance Props:
- `initialNumToRender`: number (optional) - Default: 10
  - Number of items to render in the initial batch
- `maxToRenderPerBatch`: number (optional) - Default: 10
  - Maximum number of items to render in each batch
- `windowSize`: number (optional) - Default: 5
  - Number of items to render outside the visible area
- `removeClippedSubviews`: boolean (optional) - Default: true
  - Remove items that are off-screen to save memory
- `updateCellsBatchingPeriod`: number (optional) - Default: 50
  - Time in ms between batch updates
- `onEndReachedThreshold`: number (optional) - Default: 0.5
  - How far from the end to trigger onEndReached
- `getItemLayout`: (data: any, index: number) => { length: number, offset: number, index: number } (optional)
  - Optimize rendering by providing item dimensions

Example usage with performance optimizations:

```tsx
import { FlatList, SectionList } from '@shiplypalestine/ui';

// Optimized FlatList for large data sets
<FlatList
  data={largeDataSet}
  renderItem={({ item }) => (
    <View className="p-2 bg-surface-light dark:bg-surface-dark rounded">
      <Text className="text-text-light dark:text-text-dark">{item.title}</Text>
    </View>
  )}
  keyExtractor={item => item.id}
  // Performance optimizations
  initialNumToRender={20}
  maxToRenderPerBatch={20}
  windowSize={10}
  removeClippedSubviews={true}
  updateCellsBatchingPeriod={100}
  onEndReachedThreshold={0.7}
  getItemLayout={(data, index) => ({
    length: 60, // Height of your item
    offset: 60 * index,
    index,
  })}
/>

// Optimized SectionList for large data sets
<SectionList
  sections={largeSectionData}
  renderItem={({ item }) => (
    <View className="p-2 bg-surface-light dark:bg-surface-dark rounded">
      <Text className="text-text-light dark:text-text-dark">{item.title}</Text>
    </View>
  )}
  renderSectionHeader={({ section }) => (
    <View className="bg-primary-light dark:bg-primary-dark p-2 rounded-t">
      <Text className="text-white font-bold">{section.title}</Text>
    </View>
  )}
  keyExtractor={item => item.id}
  // Performance optimizations
  initialNumToRender={20}
  maxToRenderPerBatch={20}
  windowSize={10}
  removeClippedSubviews={true}
  updateCellsBatchingPeriod={100}
  onEndReachedThreshold={0.7}
  getItemLayout={(data, index) => ({
    length: 60, // Height of your item
    offset: 60 * index,
    index,
  })}
/>
```

Performance Tips:
1. Always provide `getItemLayout` for fixed-height items
2. Use `removeClippedSubviews` for large lists
3. Adjust `windowSize` based on your list's complexity
4. Use `initialNumToRender` and `maxToRenderPerBatch` to control rendering batches
5. Consider using `onEndReached` for infinite scrolling
6. Memoize your `renderItem` function if it's complex
7. Use `keyExtractor` with stable, unique keys

### Box

A versatile container component that extends React Native's View with additional styling capabilities and layout features.

Props:
- `style`: ViewStyle (optional) - Custom styles
- `className`: string (optional) - NativeWind class names
- `bg`: string (optional) - Background color
- `rounded`: number | 'sm' | 'md' | 'lg' | 'full' (optional) - Border radius
- `borderWidth`: number (optional) - Border width
- `borderColor`: string (optional) - Border color
- `shadow`: object (optional) - Shadow properties
  - `color`: string (optional)
  - `offset`: { width: number, height: number } (optional)
  - `opacity`: number (optional)
  - `radius`: number (optional)
  - `elevation`: number (optional)
- `flex`: number (optional) - Flex value
- `flexDirection`: 'row' | 'column' | 'row-reverse' | 'column-reverse' (optional)
- `flexWrap`: 'wrap' | 'nowrap' | 'wrap-reverse' (optional)
- `justifyContent`: 'flex-start' | 'flex-end' | 'center' | 'space-between' | 'space-around' | 'space-evenly' (optional)
- `alignItems`: 'flex-start' | 'flex-end' | 'center' | 'stretch' | 'baseline' (optional)
- `alignSelf`: 'auto' | 'flex-start' | 'flex-end' | 'center' | 'stretch' | 'baseline' (optional)
- `position`: 'absolute' | 'relative' (optional)
- `top`: number (optional)
- `right`: number (optional)
- `bottom`: number (optional)
- `left`: number (optional)
- `p`: number (optional) - Padding
- `px`: number (optional) - Horizontal padding
- `py`: number (optional) - Vertical padding
- `pt`: number (optional) - Top padding
- `pr`: number (optional) - Right padding
- `pb`: number (optional) - Bottom padding
- `pl`: number (optional) - Left padding
- `m`: number (optional) - Margin
- `mx`: number (optional) - Horizontal margin
- `my`: number (optional) - Vertical margin
- `mt`: number (optional) - Top margin
- `mr`: number (optional) - Right margin
- `mb`: number (optional) - Bottom margin
- `ml`: number (optional) - Left margin
- `w`: number | string (optional) - Width
- `h`: number | string (optional) - Height
- `minW`: number | string (optional) - Minimum width
- `minH`: number | string (optional) - Minimum height
- `maxW`: number | string (optional) - Maximum width
- `maxH`: number | string (optional) - Maximum height
- `overflow`: 'visible' | 'hidden' | 'scroll' (optional)
- `opacity`: number (optional)
- `zIndex`: number (optional)
- `transform`: ViewStyle['transform'] (optional)

Example usage:

```tsx
import { Box } from '@shiplypalestine/ui';

// Basic Box
<Box
  bg="blue.500"
  p={4}
  rounded="md"
>
  <Text className="text-white">Basic Box</Text>
</Box>

// Box with Shadow
<Box
  bg="white"
  p={4}
  rounded="md"
  shadow={{
    color: '#000',
    offset: { width: 0, height: 2 },
    opacity: 0.25,
    radius: 3.84,
    elevation: 5,
  }}
>
  <Text>Box with shadow</Text>
</Box>

// Box with Flex Layout
<Box
  flexDirection="row"
  justifyContent="space-between"
  alignItems="center"
  p={4}
  bg="gray.100"
  rounded="md"
>
  <Box bg="blue.500" p={2} rounded="sm">
    <Text className="text-white">Item 1</Text>
  </Box>
  <Box bg="green.500" p={2} rounded="sm">
    <Text className="text-white">Item 2</Text>
  </Box>
  <Box bg="red.500" p={2} rounded="sm">
    <Text className="text-white">Item 3</Text>
  </Box>
</Box>

// Box with Position
<Box
  position="absolute"
  top={10}
  right={10}
  bg="purple.500"
  p={4}
  rounded="full"
>
  <Text className="text-white">Positioned Box</Text>
</Box>

// Box with Transform
<Box
  bg="yellow.500"
  p={4}
  rounded="md"
  transform={[{ rotate: '45deg' }]}
>
  <Text>Rotated Box</Text>
</Box>

// Box with Overflow
<Box
  h={100}
  w={200}
  overflow="scroll"
  bg="gray.100"
  p={4}
  rounded="md"
>
  <Text>Scrollable content</Text>
</Box>
```

### CenterBox

A layout component that centers its children both horizontally and vertically.

```tsx
import { CenterBox } from '@shiplypalestine/ui';

// Basic usage
<CenterBox>
  <Text>Centered Content</Text>
</CenterBox>

// With flex
<CenterBox flex={1}>
  <Text>Centered with flex</Text>
</CenterBox>

// Full-width and full-height
<CenterBox fullWidth fullHeight>
  <Text>Centered in the entire container</Text>
</CenterBox>

// With NativeWind classes
<CenterBox className="bg-blue-100 p-4 rounded-lg">
  <Text>Centered with NativeWind</Text>
</CenterBox>
```

#### Props
- `style`: Custom styles for the container
- `className`: NativeWind classes
- `flex`: Flex value (default: 0)
- `fullWidth`: Whether to take full width (default: false)
- `fullHeight`: Whether to take full height (default: false)

### Divider

A horizontal line component that can be used to separate content.

Props:
- `style`: Custom styles for the Divider
- `className`: NativeWind classes
- `color`: Line color (defaults to theme border color)
- `thickness`: Line thickness in pixels (default: 1)
- `margin`: Vertical margin in pixels (default: 8)

### Label

A status-based label component that displays text with a colored background.

Props:
- `text`: The text to display (required)
- `status`: The status type ('success' | 'error' | 'warning' | 'info')
- `style`: Custom styles for the container
- `textStyle`: Custom styles for the text
- `className`: NativeWind classes for the container
- `textClassName`: NativeWind classes for the text

## RTL Support

The Shiply UI Library includes comprehensive support for right-to-left (RTL) languages such as Arabic, Hebrew, and Persian. This allows you to create applications that cater to global audiences with proper text and layout direction.

### Setting Up RTL Support

The library provides an `RTLProvider` that automatically handles RTL detection based on the current language:

```tsx
import { RTLProvider } from '@shiplypalestine/ui';

export default function App() {
  return (
    <RTLProvider>
      {/* Your app content */}
    </RTLProvider>
  );
}
```

### Using the RTL Hooks and Components

#### RTL Hook

Use the `useRTL` hook to access RTL state and controls:

```tsx
import { useRTL } from '@shiplypalestine/ui';

function MyComponent() {
  const { isRTL, toggleRTL, setRTL } = useRTL();
  
  return (
    <View>
      <Text>Current direction: {isRTL ? 'RTL' : 'LTR'}</Text>
      <Button title="Toggle Direction" onPress={toggleRTL} />
      <Button title="Set to RTL" onPress={() => setRTL(true)} />
      <Button title="Set to LTR" onPress={() => setRTL(false)} />
    </View>
  );
}
```

#### RTLView Component

Use the `RTLView` component to create containers that automatically handle text direction:

```tsx
import { RTLView } from '@shiplypalestine/ui';

function MyComponent() {
  return (
    <RTLView>
      <Text>This text will follow the current RTL setting</Text>
    </RTLView>
  );
}
```

You can also force a specific direction regardless of the global setting:

```tsx
<RTLView forceLTR={true}>
  <Text>This will always be left-to-right</Text>
</RTLView>
```

### RTL-Aware Input Component

The `Input` component includes built-in RTL support with properties to control text direction:

```tsx
import { Input } from '@shiplypalestine/ui';

function MyForm() {
  return (
    <View>
      {/* Automatically follows the global RTL setting */}
      <Input label="Username" placeholder="Enter username" />
      
      {/* Force RTL regardless of global setting */}
      <Input 
        label="الاسم"
        placeholder="أدخل الاسم" 
        forceRTL={true}
      />
      
      {/* Force LTR regardless of global setting */}
      <Input 
        label="Email"
        placeholder="Enter email" 
        forceLTR={true}
      />
    </View>
  );
}
```

### Language Selection

The library includes a `LanguageSelector` component that integrates with the RTL system:

```tsx
import { LanguageSelector } from '@shiplypalestine/ui';

function SettingsScreen() {
  return (
    <View>
      <LanguageSelector 
        onLanguageChange={(language) => {
          console.log(`Language changed to ${language}`);
          // The RTL direction will automatically update based on the language
        }}
      />
    </View>
  );
}
```

### Best Practices for RTL Support

1. **Use Relative Positioning**: Always use `start` and `end` instead of `left` and `right` in your styles.

2. **Avoid Hardcoded Directions**: Don't hardcode text alignment or flex direction; use the RTL utilities.

3. **Test with RTL Languages**: Always test your UI with RTL languages to ensure proper alignment and visual formatting.

4. **Accommodate Text Expansion**: RTL languages often require more horizontal space, so design with flexibility.

5. **Icons and Images**: Make sure directional icons (arrows, back buttons) are flipped in RTL mode.

## Tabs

The Tabs component provides a way to organize content into different views that can be switched between.

### Basic Usage

```tsx
import { Tabs } from '@shiplypalestine/ui';

function TabsExample() {
  return (
    <Tabs
      tabs={[
        {
          key: 'tab1',
          label: 'Tab 1',
          content: <Text>Content for Tab 1</Text>,
        },
        {
          key: 'tab2',
          label: 'Tab 2',
          content: <Text>Content for Tab 2</Text>,
        },
        {
          key: 'tab3',
          label: 'Tab 3',
          content: <Text>Content for Tab 3</Text>,
        },
      ]}
      onTabChange={(tabKey) => console.log(`Tab changed to ${tabKey}`)}
    />
  );
}
```

### Tabs with Icons

```tsx
import { Tabs } from '@shiplypalestine/ui';
import { HomeIcon, ProfileIcon, SettingsIcon } from './icons';

function TabsWithIconsExample() {
  return (
    <Tabs
      tabs={[
        {
          key: 'home',
          label: 'Home',
          icon: <HomeIcon />,
          content: <Text>Home content</Text>,
        },
        {
          key: 'profile',
          label: 'Profile',
          icon: <ProfileIcon />,
          content: <Text>Profile content</Text>,
        },
        {
          key: 'settings',
          label: 'Settings',
          icon: <SettingsIcon />,
          content: <Text>Settings content</Text>,
        },
      ]}
    />
  );
}
```

### Custom Styled Tabs

```tsx
import { Tabs } from '@shiplypalestine/ui';

function StyledTabsExample() {
  return (
    <Tabs
      tabs={[
        {
          key: 'photos',
          label: 'Photos',
          content: <Text>Photos content</Text>,
        },
        {
          key: 'videos',
          label: 'Videos',
          content: <Text>Videos content</Text>,
        },
        {
          key: 'files',
          label: 'Files',
          content: <Text>Files content</Text>,
        },
      ]}
      tabsContainerClassName="bg-gray-100 dark:bg-gray-800 rounded-t-lg"
      tabButtonClassName="flex-1"
      activeTabButtonClassName="bg-white dark:bg-gray-700"
      contentContainerClassName="bg-white dark:bg-gray-700 rounded-b-lg"
    />
  );
}
```

### Props

#### Tabs Component Props

| Prop | Type | Description |
|------|------|-------------|
| `tabs` | `TabItemProps[]` | Array of tab items |
| `initialTabKey` | `string` | Key of the initially active tab |
| `containerStyle` | `ViewStyle` | Style for the main container |
| `tabsContainerStyle` | `ViewStyle` | Style for the tabs container |
| `tabButtonStyle` | `ViewStyle` | Style for the tab buttons |
| `activeTabButtonStyle` | `ViewStyle` | Style for the active tab button |
| `tabTextStyle` | `TextStyle` | Style for the tab text |
| `activeTabTextStyle` | `TextStyle` | Style for the active tab text |
| `contentContainerStyle` | `ViewStyle` | Style for the content container |
| `containerClassName` | `string` | NativeWind class for the main container |
| `tabsContainerClassName` | `string` | NativeWind class for the tabs container |
| `tabButtonClassName` | `string` | NativeWind class for the tab buttons |
| `activeTabButtonClassName` | `string` | NativeWind class for the active tab button |
| `tabTextClassName` | `string` | NativeWind class for the tab text |
| `activeTabTextClassName` | `string` | NativeWind class for the active tab text |
| `contentContainerClassName` | `string` | NativeWind class for the content container |
| `onTabChange` | `(tabKey: string) => void` | Callback fired when a tab is selected |

#### TabItemProps Interface

| Property | Type | Description |
|----------|------|-------------|
| `key` | `string` | Unique identifier for the tab |
| `label` | `string` | Display label for the tab |
| `icon` | `ReactNode` | Optional icon for the tab |
| `content` | `ReactNode` | Content to be displayed when tab is active |

### PhoneNumber

A component for international phone number input that combines country code selection with a phone number input field.

Props:
- `value`: string (required) - The current full phone number value
- `onChangeText`: (value: string) => void (required) - Callback for when the phone number changes
- `countryCodes`: CountryCode[] (required) - Array of country codes to select from
- `initialCountryCode`: string (optional) - Initial country code to select
- `label`: string (optional) - Label for the input
- `error`: string (optional) - Error message
- `placeholder`: string (optional) - Placeholder for the phone number input
- `required`: boolean (optional) - Whether the field is required
- `disabled`: boolean (optional) - Whether the field is disabled
- `containerStyle`: ViewStyle (optional) - Style for the container
- `inputStyle`: TextStyle (optional) - Style for the input
- `labelStyle`: TextStyle (optional) - Style for the label
- `errorStyle`: TextStyle (optional) - Style for the error message
- `dropdownStyle`: ViewStyle (optional) - Style for the dropdown
- `countryCodeStyle`: TextStyle (optional) - Style for the country code text
- `countryCodeContainerStyle`: ViewStyle (optional) - Style for the country code container
- `containerClassName`: string (optional) - Class for the container
- `inputClassName`: string (optional) - Class for the input
- `labelClassName`: string (optional) - Class for the label
- `errorClassName`: string (optional) - Class for the error message
- `dropdownClassName`: string (optional) - Class for the dropdown
- `countryCodeClassName`: string (optional) - Class for the country code text
- `countryCodeContainerClassName`: string (optional) - Class for the country code container
- `forceRTL`: boolean (optional) - Force right-to-left text direction
- `forceLTR`: boolean (optional) - Force left-to-right text direction

Example usage:

```tsx
import { PhoneNumber, CountryCode } from '@shiplypalestine/ui';

// Define country codes
const countryCodes: CountryCode[] = [
  { code: '+1', name: 'United States', flag: '🇺🇸' },
  { code: '+44', name: 'United Kingdom', flag: '🇬🇧' },
  { code: '+33', name: 'France', flag: '🇫🇷' },
  // Add more country codes...
];

// Basic usage
function PhoneNumberExample() {
  const [phoneNumber, setPhoneNumber] = useState('');

  return (
    <PhoneNumber
      value={phoneNumber}
      onChangeText={setPhoneNumber}
      countryCodes={countryCodes}
      label="Phone Number"
      placeholder="Enter phone number"
    />
  );
}

// With initial country code
<PhoneNumber
  value={phoneNumber}
  onChangeText={setPhoneNumber}
  countryCodes={countryCodes}
  initialCountryCode="+44"
  label="UK Phone Number"
  placeholder="Enter UK phone number"
/>

// With error state
<PhoneNumber
  value={phoneNumber}
  onChangeText={setPhoneNumber}
  countryCodes={countryCodes}
  label="Phone Number"
  error="Invalid phone number"
/>

// With RTL support
<PhoneNumber
  value={phoneNumber}
  onChangeText={setPhoneNumber}
  countryCodes={countryCodes}
  label="رقم الهاتف"
  placeholder="أدخل رقم الهاتف"
  forceRTL={true}
/>

// Required field
<PhoneNumber
  value={phoneNumber}
  onChangeText={setPhoneNumber}
  countryCodes={countryCodes}
  label="Phone Number"
  required={true}
/>
```

#### CountryCode Interface
```typescript
interface CountryCode {
  code: string;    // The country dial code, e.g., '+1'
  name: string;    // The country name, e.g., 'United States'
  flag?: string;   // Optional emoji flag, e.g., '🇺🇸'
}
```

## Autocomplete

A high-performance autocomplete component that supports large datasets, API integration, and customizable styling.

### Props

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `value` | `string` | Yes | The current input value |
| `onChangeText` | `(text: string) => void` | Yes | Callback when the input text changes |
| `onSelect` | `(item: AutocompleteItem) => void` | Yes | Callback when an item is selected |
| `fetchData` | `(query: string) => Promise<AutocompleteItem[]>` | Yes | Function to fetch data based on the query |
| `label` | `string` | No | Label text for the input |
| `placeholder` | `string` | No | Placeholder text for the input |
| `error` | `string` | No | Error message to display |
| `required` | `boolean` | No | Whether the field is required |
| `disabled` | `boolean` | No | Whether the input is disabled |
| `forceRTL` | `boolean` | No | Force RTL layout |
| `containerClassName` | `string` | No | Custom class for the container |
| `inputClassName` | `string` | No | Custom class for the input |
| `listClassName` | `string` | No | Custom class for the results list |
| `itemClassName` | `string` | No | Custom class for list items |

### AutocompleteItem Interface

```typescript
interface AutocompleteItem {
  id: string;
  label: string;
  value: string;
}
```

### Example Usage

```tsx
import { Autocomplete } from 'shiply-ui';

const MyComponent = () => {
  const [value, setValue] = useState('');
  const [selectedItem, setSelectedItem] = useState<AutocompleteItem | null>(null);

  const fetchData = async (query: string): Promise<AutocompleteItem[]> => {
    // Your API call here
    const response = await fetch(`/api/search?q=${query}`);
    return response.json();
  };

  return (
    <Autocomplete
      value={value}
      onChangeText={setValue}
      onSelect={setSelectedItem}
      fetchData={fetchData}
      label="Search"
      placeholder="Type to search..."
    />
  );
};
```

### Features

- Debounced search to prevent excessive API calls
- Virtualized list for handling large datasets
- Loading states and error handling
- Keyboard navigation support
- RTL support
- Customizable styling
- Clear button with loading indicator

## ActionSheet

A bottom sheet component that slides up from the bottom of the screen, commonly used for presenting a set of actions or options. Supports both web and mobile platforms with proper positioning and z-index handling.

```tsx
import { ActionSheet } from 'shiply-ui';

// Basic usage
<ActionSheet
  visible={isVisible}
  onClose={() => setIsVisible(false)}
  title="Options"
>
  <View>
    <Text>Content goes here</Text>
  </View>
</ActionSheet>

// With custom styles
<ActionSheet
  visible={isVisible}
  onClose={() => setIsVisible(false)}
  title="Custom Styled Options"
  containerStyle={{ backgroundColor: 'rgba(0, 0, 0, 0.7)' }}
  contentStyle={{ 
    backgroundColor: '#F7FAFC',
    borderTopLeftRadius: 20,
    borderTopRightRadius: 20,
  }}
  titleStyle={{ 
    color: '#2D3748',
    fontSize: 20,
    fontWeight: 'bold',
  }}
  searchContainerStyle={{ 
    backgroundColor: '#EDF2F7',
    borderRadius: 8,
    margin: 16,
  }}
  searchInputStyle={{ 
    backgroundColor: '#FFFFFF',
    borderRadius: 6,
  }}
>
  <View>
    <Text>Custom styled content</Text>
  </View>
</ActionSheet>

// With default search
<ActionSheet
  visible={isVisible}
  onClose={() => setIsVisible(false)}
  title="Search Options"
  showSearch
  searchPlaceholder="Search items..."
  onSearch={(query) => {
    console.log('Searching for:', query);
  }}
  searchValue={searchQuery}
  isLoading={isLoading}
  searchInputProps={{
    autoCapitalize: 'none',
    autoCorrect: false,
  }}
>
  <View>
    <Text>Search results go here</Text>
  </View>
</ActionSheet>

// With custom search input
<ActionSheet
  visible={isVisible}
  onClose={() => setIsVisible(false)}
  title="Custom Search"
  showSearch
  searchInputComponent={
    <Input
      placeholder="Search with custom input..."
      value={searchQuery}
      onChangeText={setSearchQuery}
      placeholderType="search"
      startComponent={
        <View style={{ width: 20, height: 20, backgroundColor: 'blue', borderRadius: 10 }} />
      }
    />
  }
  isLoading={isLoading}
>
  <View>
    <Text>Search results go here</Text>
  </View>
</ActionSheet>
```

#### Props

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `visible` | `boolean` | `false` | Controls the visibility of the action sheet |
| `onClose` | `() => void` | - | Callback function called when the action sheet is closed |
| `title` | `string` | - | Optional title displayed at the top of the action sheet |
| `children` | `React.ReactNode` | - | Content to be displayed in the action sheet |
| `showSearch` | `boolean` | `false` | Whether to show the search input |
| `searchPlaceholder` | `string` | `'Search...'` | Placeholder text for the search input |
| `onSearch` | `(query: string) => void` | - | Callback function called when the search query changes |
| `searchValue` | `string` | `''` | Current value of the search input |
| `isLoading` | `boolean` | `false` | Whether to show a loading indicator |
| `searchInputProps` | `TextInputProps` | - | Additional props to pass to the default search input |
| `searchInputComponent` | `React.ReactNode` | - | Custom search input component to use instead of the default |
| `emptyMessage` | `string` | `'No items found'` | Message to display when no content is provided |
| `minHeight` | `number` | `500` | Minimum height of the action sheet |

#### Style Props

| Prop | Type | Description |
|------|------|-------------|
| `style` | `ViewStyle` | Custom style for the content container |
| `className` | `string` | NativeWind classes for the content container |
| `containerStyle` | `ViewStyle` | Custom style for the main container |
| `containerClassName` | `string` | NativeWind classes for the main container |
| `contentStyle` | `ViewStyle` | Custom style for the action sheet content |
| `contentClassName` | `string` | NativeWind classes for the action sheet content |
| `overlayStyle` | `ViewStyle` | Custom style for the overlay background |
| `overlayClassName` | `string` | NativeWind classes for the overlay background |
| `titleStyle` | `TextStyle` | Custom style for the title text |
| `titleClassName` | `string` | NativeWind classes for the title text |
| `searchContainerStyle` | `ViewStyle` | Custom style for the search container |
| `searchContainerClassName` | `string` | NativeWind classes for the search container |
| `searchInputStyle` | `TextStyle` | Custom style for the search input |
| `searchInputClassName` | `string` | NativeWind classes for the search input |

#### Platform Support

- **Web**: Uses `position: fixed` with proper z-index for overlay positioning
- **Mobile**: Uses React Native Modal with slide-up animation
- **Cross-platform**: Consistent API and behavior across platforms

## Overlay

A flexible overlay component that creates a backdrop and can wrap other components like spinners, modals, or notifications. Supports multiple positions and customizable styling.

```tsx
import { Overlay } from '@shiplypalestine/ui';

// Basic overlay with centered content
<Overlay
  isOpen={isVisible}
  onClose={() => setIsVisible(false)}
  position="center"
>
  <View style={{ backgroundColor: 'white', padding: 20, borderRadius: 8 }}>
    <Text>Overlay Content</Text>
  </View>
</Overlay>

// Overlay with spinner for loading states
<Overlay
  isOpen={isLoading}
  position="center"
  dismissible={false}
  closeOnBackdropPress={false}
>
  <View style={{ backgroundColor: 'white', padding: 32, borderRadius: 16, alignItems: 'center' }}>
    <Spinner size="large" color="primary" />
    <Text style={{ marginTop: 16 }}>Loading...</Text>
  </View>
</Overlay>

// Top position notification
<Overlay
  isOpen={showNotification}
  onClose={() => setShowNotification(false)}
  position="top"
  backdropOpacity={0.4}
>
  <View style={{ backgroundColor: 'white', padding: 16, borderRadius: 8 }}>
    <Text>Top notification message</Text>
  </View>
</Overlay>

// Bottom position with custom styling and unmountOnExit
<Overlay
  isOpen={isVisible}
  onClose={() => setIsVisible(false)}
  position="bottom"
  backdropColor="rgba(0, 0, 0, 0.3)"
  contentStyle={{ marginBottom: 20 }}
  unmountOnExit={true}
>
  <View style={{ backgroundColor: 'white', padding: 20, borderRadius: 12 }}>
    <Text>Bottom positioned content</Text>
  </View>
</Overlay>
```

#### Props

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `isOpen` | `boolean` | `false` | Controls the visibility of the overlay |
| `onClose` | `() => void` | - | Callback function called when the overlay is closed |
| `children` | `React.ReactNode` | - | Content to be displayed in the overlay |
| `dismissible` | `boolean` | `true` | Whether the overlay can be dismissed |
| `closeOnBackdropPress` | `boolean` | `true` | Whether tapping the backdrop closes the overlay |
| `unmountOnExit` | `boolean` | `false` | Whether to unmount the component when closed |
| `animationType` | `'fade' \| 'slide' \| 'none'` | `'fade'` | Animation type for mobile modal |
| `position` | `'center' \| 'top' \| 'bottom' \| 'left' \| 'right'` | `'center'` | Position of the content within the overlay |
| `backdropColor` | `string` | `'rgba(0, 0, 0, 0.5)'` | Color of the backdrop |
| `backdropOpacity` | `number` | `0.5` | Opacity of the backdrop |
| `zIndex` | `number` | `9999` | Z-index for web positioning |

#### Style Props

| Prop | Type | Description |
|------|------|-------------|
| `style` | `ViewStyle` | Custom style for the content container |
| `className` | `string` | NativeWind classes for the content container |
| `containerStyle` | `ViewStyle` | Custom style for the main container |
| `containerClassName` | `string` | NativeWind classes for the main container |
| `backdropStyle` | `ViewStyle` | Custom style for the backdrop |
| `backdropClassName` | `string` | NativeWind classes for the backdrop |
| `contentStyle` | `ViewStyle` | Custom style for the content wrapper |
| `contentClassName` | `string` | NativeWind classes for the content wrapper |

#### Position Options

- **`center`**: Content is centered both horizontally and vertically
- **`top`**: Content appears at the top of the screen with margin
- **`bottom`**: Content appears at the bottom of the screen with margin
- **`left`**: Content appears at the left side of the screen with margin
- **`right`**: Content appears at the right side of the screen with margin

#### Use Cases

1. **Loading States**: Wrap a Spinner component for loading overlays
2. **Notifications**: Use top/bottom positions for toast-like notifications
3. **Modals**: Create custom modal dialogs with centered content
4. **Full-screen Overlays**: Use for complex overlays that need full screen coverage
5. **Side Panels**: Use left/right positions for slide-out panels

#### Platform Support

- **Web**: Uses `position: fixed` with proper z-index for overlay positioning
- **Mobile**: Uses React Native Modal with customizable animation types
- **Cross-platform**: Consistent API and behavior across platforms

## Skeleton

A flexible skeleton placeholder component for loading states. Supports shimmer animation, shape variants, and full style customization.

**Note:** You must install `react-native-linear-gradient` in your project for shimmer animation to work:

```bash
npm install react-native-linear-gradient
# or
yarn add react-native-linear-gradient
```

#### Usage

```tsx
import { Skeleton } from '@shiplypalestine/ui';

// Rectangle skeleton (default)
<Skeleton width={120} height={16} />

// Rounded skeleton
<Skeleton width={120} height={16} variant="rounded" />

// Circle skeleton (e.g. avatar)
<Skeleton width={40} height={40} variant="circle" />

// Custom border radius
<Skeleton width={100} height={20} borderRadius={8} />

// No animation
<Skeleton width={120} height={16} animation="none" />

// Full width skeleton (shimmer will be disabled if width is not a number)
<Skeleton width="100%" height={16} />
```

#### Props

| Prop         | Type                          | Default     | Description                                      |
|--------------|-------------------------------|-------------|--------------------------------------------------|
| width        | number \| string               | '100%'      | Width of the skeleton                            |
| height       | number \| string               | 16          | Height of the skeleton                           |
| borderRadius | number                        | -           | Border radius (overrides variant)                |
| variant      | 'rect' \| 'circle' \| 'rounded'| 'rect'      | Shape of the skeleton                            |
| style        | ViewStyle                     | -           | Custom style for the container                   |
| className    | string                        | -           | NativeWind classes for the container             |
| animation    | 'shimmer' \| 'none'           | 'shimmer'   | Animation type                                   |

- If `variant` is `circle`, the skeleton will be perfectly round.
- If `variant` is `rounded`, the skeleton will have a default border radius of 12 unless overridden.
- If `width` is not a number, shimmer animation will be disabled and a warning will be shown in development.

## Development

1. Clone the repository
2. Install dependencies: `npm install`
3. Start the development server: `
```

### Link

A customizable link component for navigation or actions. Supports custom styles and classes for both the container and text.

#### Usage

```tsx
import { Link } from '@shiplypalestine/ui';

// Basic usage
<Link onPress={() => {}}>Default Link</Link>

// With custom styles
<Link
  onPress={() => {}}
  style={{ margin: 8 }}
  textStyle={{ color: 'red', fontWeight: 'bold' }}
>
  Custom Styled Link
</Link>

// With NativeWind/Tailwind classes
<Link
  onPress={() => {}}
  className="rounded"
  textClassName="text-lg underline text-green-600"
>
  Tailwind Link
</Link>
```

#### Props

| Prop           | Type                        | Default     | Description                                 |
|----------------|-----------------------------|-------------|---------------------------------------------|
| onPress        | () => void                  | required    | Function to call when link is pressed       |
| children       | React.ReactNode             | required    | Link content                                |
| variant        | 'default' \| 'primary' \| 'secondary' | 'default' | Color variant                              |
| disabled       | boolean                     | false       | Disable the link                            |
| underline      | boolean                     | false       | Underline the link text                     |
| size           | 'small' \| 'medium' \| 'large' | 'medium'  | Text size                                   |
| style          | ViewStyle                   | -           | Custom style for the container              |
| textStyle      | TextStyle                   | -           | Custom style for the text                   |
| className      | string                      | -           | NativeWind classes for the container        |
| textClassName  | string                      | -           | NativeWind classes for the text             |

## Icon Component

A flexible icon wrapper for any icon library (e.g., Feather, MaterialIcons, Ionicons, etc.).

### Props
| Prop   | Type   | Required | Description |
|--------|--------|----------|-------------|
| as     | React.ReactNode | Yes | The icon element (e.g., <Ionicons name="receipt" size={32} color="#2563EB" />) |
| style  | object | No       | Custom style for the wrapper |
| className | string | No    | NativeWind/Tailwind classes for the wrapper |
| ...rest| any    | No       | Any other props for the wrapper |

### Usage

```tsx
import { Icon } from '@shiplypalestine/ui';
import { Feather, MaterialIcons, Ionicons } from '@expo/vector-icons';

// Feather icon
<Icon as={<Feather name="home" color="#2563EB" size={32} />} />

// MaterialIcons icon
<Icon as={<MaterialIcons name="favorite" color="#EF4444" size={32} />} />

// Ionicons icon
<Icon as={<Ionicons name="receipt" size={32} color="#2563EB" />} />

// With custom style and Tailwind/NativeWind classes
<Icon as={<Feather name="user" color="#22C55E" size={32} />} className="rounded-full bg-gray-100 p-2" style={{ margin: 8 }} />
```

- The `as` prop is the icon element itself (not a component type or string).
- You can use any icon component from libraries like `@expo/vector-icons` or `react-native-vector-icons`.
- All other props are applied to the wrapper `<View>`.

## Image Component

A flexible image component that supports fallback alt text, size, and NativeWind/Tailwind classes.

### Props
| Prop      | Type                | Required | Description |
|-----------|---------------------|----------|-------------|
| size      | number              | No       | Sets both width and height of the image |
| alt       | string              | No       | Fallback text to show if image fails to load |
| source    | object              | Yes      | The image source (same as React Native Image) |
| className | string              | No       | NativeWind/Tailwind classes for styling |
| style     | object              | No       | Custom style |
| ...rest   | any                 | No       | Any other native Image props |

### Usage

```tsx
import { Image } from '@shiplypalestine/ui';

// Basic usage
<Image
  size={150}
  alt="fallback text"
  source={{ uri: 'https://reactnative.dev/img/tiny_logo.png' }}
/>

// With fallback/alt text
<Image
  size={100}
  alt="Logo not found"
  source={{ uri: 'https://invalid-url-to-trigger-fallback.png' }}
/>

// With Tailwind/NativeWind classes
<Image
  size={60}
  alt="Avatar"
  source={{ uri: 'https://reactnative.dev/img/tiny_logo.png' }}
  className="rounded-full border border-blue-500"
/>
```

- If the image fails to load, the `alt` text will be shown in a styled fallback box.
- The `size` prop sets both width and height. You can also use `style` or `className` for more control.
- All native Image props are supported.